From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gnu.wildebeest.org (gnu.wildebeest.org [45.83.234.184]) by sourceware.org (Postfix) with ESMTPS id 3B7993858409 for ; Tue, 10 Oct 2023 13:43:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3B7993858409 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=klomp.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=klomp.org Received: from r6.localdomain (82-217-174-174.cable.dynamic.v4.ziggo.nl [82.217.174.174]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by gnu.wildebeest.org (Postfix) with ESMTPSA id D2DC9301FE80; Tue, 10 Oct 2023 15:43:34 +0200 (CEST) Received: by r6.localdomain (Postfix, from userid 1000) id 224873403C4; Tue, 10 Oct 2023 15:43:34 +0200 (CEST) From: Mark Wielaard To: elfutils-devel@sourceware.org Cc: hsm2@rice.edu, Mark Wielaard Subject: [PATCH 06/16] libelf: Make elf32_getchdr and elf64_getchdr thread-safe Date: Tue, 10 Oct 2023 15:42:50 +0200 Message-ID: <20231010134300.53830-6-mark@klomp.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231010134300.53830-1-mark@klomp.org> References: <301fac87e83ebbbd677750579ae9a3429b461bdf.camel@klomp.org> <20231010134300.53830-1-mark@klomp.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3033.6 required=5.0 tests=BAYES_00,GIT_PATCH_0,JMQ_SPF_NEUTRAL,KAM_DMARC_STATUS,RCVD_IN_BARRACUDACENTRAL,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Heather McIntyre * libelf/elf32_getchdr.c: Move getchdr function to elf32_getchdr.h. * libelf/elf32_getchdr.h: New file. Add macro to create getchdr_wrlock. * libelf/elf32_updatenull.c: Change call from getchdr to getchdr_wrlock. * libelf/elf_getdata.c: Add elf_getdata_wrlock. * libelf/libelfP.h: Add internal function declarations. Signed-off-by: Heather S. McIntyre Signed-off-by: Mark Wielaard --- libelf/elf32_getchdr.c | 46 +++-------------------------- libelf/elf32_getchdr.h | 61 +++++++++++++++++++++++++++++++++++++++ libelf/elf32_updatenull.c | 2 +- libelf/elf_getdata.c | 14 +++++++++ libelf/libelfP.h | 4 +++ 5 files changed, 84 insertions(+), 43 deletions(-) create mode 100644 libelf/elf32_getchdr.h diff --git a/libelf/elf32_getchdr.c b/libelf/elf32_getchdr.c index 982a614c..41591300 100644 --- a/libelf/elf32_getchdr.c +++ b/libelf/elf32_getchdr.c @@ -38,46 +38,8 @@ # define LIBELFBITS 32 #endif +#define ELF_WRLOCK_HELD 1 +#include "elf32_getchdr.h" -ElfW2(LIBELFBITS,Chdr) * -elfw2(LIBELFBITS,getchdr) (Elf_Scn *scn) -{ - ElfW2(LIBELFBITS,Shdr) *shdr = elfw2(LIBELFBITS,getshdr) (scn); - if (shdr == NULL) - return NULL; - - /* Must have SHF_COMPRESSED flag set. Allocated or no bits sections - can never be compressed. */ - if ((shdr->sh_flags & SHF_ALLOC) != 0) - { - __libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS); - return NULL; - } - - if (shdr->sh_type == SHT_NULL - || shdr->sh_type == SHT_NOBITS) - { - __libelf_seterrno (ELF_E_INVALID_SECTION_TYPE); - return NULL; - } - - if ((shdr->sh_flags & SHF_COMPRESSED) == 0) - { - __libelf_seterrno (ELF_E_NOT_COMPRESSED); - return NULL; - } - - /* This makes sure the data is in the correct format, so we don't - need to swap fields. */ - Elf_Data *d = elf_getdata (scn, NULL); - if (d == NULL) - return NULL; - - if (d->d_size < sizeof (ElfW2(LIBELFBITS,Chdr)) || d->d_buf == NULL) - { - __libelf_seterrno (ELF_E_INVALID_DATA); - return NULL; - } - - return (ElfW2(LIBELFBITS,Chdr) *) d->d_buf; -} +#define ELF_WRLOCK_HELD 0 +#include "elf32_getchdr.h" \ No newline at end of file diff --git a/libelf/elf32_getchdr.h b/libelf/elf32_getchdr.h new file mode 100644 index 00000000..04d47e7a --- /dev/null +++ b/libelf/elf32_getchdr.h @@ -0,0 +1,61 @@ +#undef ADD_ROUTINE_PREFIX +#undef ADD_ROUTINE_SUFFIX + +#if ELF_WRLOCK_HELD +#define CONCAT(x,y) x##y +#define ADD_ROUTINE_PREFIX(y) CONCAT(__,y) +#define ADD_ROUTINE_SUFFIX(x) x ## _wrlock +#define INTERNAL internal_function +#else +#define ADD_ROUTINE_PREFIX(y) y +#define ADD_ROUTINE_SUFFIX(x) x +#define INTERNAL +#endif + +ElfW2(LIBELFBITS,Chdr) * +INTERNAL +ADD_ROUTINE_PREFIX(elfw2(LIBELFBITS, ADD_ROUTINE_SUFFIX(getchdr))) (Elf_Scn *scn) +{ + + ElfW2(LIBELFBITS,Shdr) *shdr = ADD_ROUTINE_PREFIX(elfw2(LIBELFBITS, ADD_ROUTINE_SUFFIX(getshdr)))(scn); + + if (shdr == NULL) + return NULL; + + /* Must have SHF_COMPRESSED flag set. Allocated or no bits sections + can never be compressed. */ + if ((shdr->sh_flags & SHF_ALLOC) != 0) + { + __libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS); + return NULL; + } + + if (shdr->sh_type == SHT_NULL + || shdr->sh_type == SHT_NOBITS) + { + __libelf_seterrno (ELF_E_INVALID_SECTION_TYPE); + return NULL; + } + + if ((shdr->sh_flags & SHF_COMPRESSED) == 0) + { + __libelf_seterrno (ELF_E_NOT_COMPRESSED); + return NULL; + } + + /* This makes sure the data is in the correct format, so we don't + need to swap fields. */ + Elf_Data *d = ADD_ROUTINE_PREFIX(ADD_ROUTINE_SUFFIX(elf_getdata)) (scn, NULL); + if (d == NULL) + return NULL; + + if (d->d_size < sizeof (ElfW2(LIBELFBITS,Chdr)) || d->d_buf == NULL) + { + __libelf_seterrno (ELF_E_INVALID_DATA); + return NULL; + } + + return (ElfW2(LIBELFBITS,Chdr) *) d->d_buf; +} +#undef INTERNAL +#undef ELF_WRLOCK_HELD \ No newline at end of file diff --git a/libelf/elf32_updatenull.c b/libelf/elf32_updatenull.c index c5d26b00..3594e8ba 100644 --- a/libelf/elf32_updatenull.c +++ b/libelf/elf32_updatenull.c @@ -407,7 +407,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum) else { ElfW2(LIBELFBITS,Chdr) *chdr; - chdr = elfw2(LIBELFBITS,getchdr) (scn); + chdr = __elfw2(LIBELFBITS,getchdr_wrlock) (scn); if (unlikely (chdr == NULL)) return -1; sh_size = chdr->ch_size; diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c index 5ebd270f..7c3ac043 100644 --- a/libelf/elf_getdata.c +++ b/libelf/elf_getdata.c @@ -582,4 +582,18 @@ elf_getdata (Elf_Scn *scn, Elf_Data *data) return result; } + +Elf_Data * +internal_function +__elf_getdata_wrlock (Elf_Scn *scn, Elf_Data *data) +{ + Elf_Data *result; + + if (scn == NULL) + return NULL; + + result = __elf_getdata_rdlock (scn, data); + + return result; +} INTDEF(elf_getdata) diff --git a/libelf/libelfP.h b/libelf/libelfP.h index 96476064..ed061abb 100644 --- a/libelf/libelfP.h +++ b/libelf/libelfP.h @@ -514,6 +514,8 @@ extern Elf32_Shdr *__elf32_getshdr_rdlock (Elf_Scn *__scn) internal_function; extern Elf64_Shdr *__elf64_getshdr_rdlock (Elf_Scn *__scn) internal_function; extern Elf32_Shdr *__elf32_getshdr_wrlock (Elf_Scn *__scn) internal_function; extern Elf64_Shdr *__elf64_getshdr_wrlock (Elf_Scn *__scn) internal_function; +extern Elf32_Chdr *__elf32_getchdr_wrlock (Elf_Scn *__scn) internal_function; +extern Elf64_Chdr *__elf64_getchdr_wrlock (Elf_Scn *__scn) internal_function; extern Elf_Scn *__elf_getscn_internal (Elf *__elf, size_t __index) attribute_hidden; extern Elf_Scn *__elf_nextscn_internal (Elf *__elf, Elf_Scn *__scn) @@ -523,6 +525,8 @@ extern Elf_Data *__elf_getdata_internal (Elf_Scn *__scn, Elf_Data *__data) attribute_hidden; extern Elf_Data *__elf_getdata_rdlock (Elf_Scn *__scn, Elf_Data *__data) internal_function; +extern Elf_Data *__elf_getdata_wrlock (Elf_Scn *__scn, Elf_Data *__data) + internal_function; extern Elf_Data *__elf_rawdata_internal (Elf_Scn *__scn, Elf_Data *__data) attribute_hidden; /* Should be called to setup first section data element if -- 2.41.0