]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libelf: Make elf32_getchdr and elf64_getchdr thread-safe
authorHeather McIntyre <hsm2@rice.edu>
Tue, 10 Oct 2023 11:20:59 +0000 (13:20 +0200)
committerMark Wielaard <mark@klomp.org>
Sat, 14 Oct 2023 15:01:34 +0000 (17:01 +0200)
* 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 <hsm2@rice.edu>
Signed-off-by: Mark Wielaard <mark@klomp.org>
libelf/Makefile.am
libelf/elf32_getchdr.c
libelf/elf32_getchdr.h [new file with mode: 0644]
libelf/elf32_updatenull.c
libelf/elf_getdata.c
libelf/libelfP.h

index aabce43ec82dcabad61ffea46b923d4b69b474b3..3402863ef17466bd422cc0510c89c73410d25bab 100644 (file)
@@ -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
index 982a614c6c3a490cd9ef615f7e246e2189f65823..415913002a2de6b3e627a12a374ba5fa0ace551c 100644 (file)
 # 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 (file)
index 0000000..04d47e7
--- /dev/null
@@ -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
index c5d26b0093c737b0624888313a65f3c1ad4b5e98..3594e8bad6c0fc87dafba5302b00ab691910b515 100644 (file)
@@ -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;
index 5ebd270f80820b2350140f10d804970938e498c2..7c3ac0432f995a8915d8753272e617ed3f907865 100644 (file)
@@ -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)
index 964760649f53ad825d038b3a3352a0d212df1ffc..ed061abb0066e2351eacf270c3bb2eae406dc450 100644 (file)
@@ -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