From: Heather McIntyre Date: Tue, 10 Oct 2023 11:20:59 +0000 (+0200) Subject: libelf: Make elf32_getchdr and elf64_getchdr thread-safe X-Git-Tag: elfutils-0.190~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3ba8e91a8b1d8d5a6551f9afd84eff880ac17984;p=thirdparty%2Felfutils.git libelf: Make elf32_getchdr and elf64_getchdr thread-safe * 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. * libelf/Makefile.am (noinst_HEADERS): Add elf32_getchdr.h. Signed-off-by: Heather S. McIntyre Signed-off-by: Mark Wielaard --- diff --git a/libelf/Makefile.am b/libelf/Makefile.am index aabce43ec..3402863ef 100644 --- a/libelf/Makefile.am +++ b/libelf/Makefile.am @@ -41,7 +41,7 @@ include_HEADERS = libelf.h gelf.h nlist.h noinst_HEADERS = abstract.h common.h exttypes.h gelf_xlate.h libelfP.h \ version_xlate.h gnuhash_xlate.h note_xlate.h dl-hash.h \ - chdr_xlate.h + chdr_xlate.h elf32_getchdr.h if INSTALL_ELFH include_HEADERS += elf.h diff --git a/libelf/elf32_getchdr.c b/libelf/elf32_getchdr.c index 982a614c6..415913002 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 000000000..04d47e7ac --- /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 c5d26b009..3594e8bad 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 5ebd270f8..7c3ac0432 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 964760649..ed061abb0 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