aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorSzabolcs Nagy <szabolcs.nagy@arm.com>2020-06-22 10:56:38 +0100
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2020-07-08 14:28:53 +0100
commitc7aa8596de86fb667914ccb95c10495ad056ff96 (patch)
tree1d49bc2092f2cbb06b761f7f047626e45195082d /sysdeps
parentc1e63c7214aaef99039068da384a0ab3abc176f2 (diff)
downloadglibc-c7aa8596de86fb667914ccb95c10495ad056ff96.zip
glibc-c7aa8596de86fb667914ccb95c10495ad056ff96.tar.gz
glibc-c7aa8596de86fb667914ccb95c10495ad056ff96.tar.bz2
rtld: Clean up PT_NOTE and add PT_GNU_PROPERTY handling
Add generic code to handle PT_GNU_PROPERTY notes. Invalid content is ignored, _dl_process_pt_gnu_property is always called after PT_LOAD segments are mapped and it has no failure modes. Currently only one NT_GNU_PROPERTY_TYPE_0 note is handled, which contains target specific properties: the _dl_process_gnu_property hook is called for each property. The old _dl_process_pt_note and _rtld_process_pt_note differ in how the program header is read. The old _dl_process_pt_note is called before PT_LOAD segments are mapped and _rtld_process_pt_note is called after PT_LOAD segments are mapped. The old _rtld_process_pt_note is removed and _dl_process_pt_note is always called after PT_LOAD segments are mapped and now it has no failure modes. The program headers are scanned backwards so that PT_NOTE can be skipped if PT_GNU_PROPERTY exists. Co-Authored-By: H.J. Lu <hjl.tools@gmail.com> Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/dl-prop.h23
-rw-r--r--sysdeps/generic/ldsodefs.h4
-rw-r--r--sysdeps/x86/dl-prop.h47
3 files changed, 22 insertions, 52 deletions
diff --git a/sysdeps/generic/dl-prop.h b/sysdeps/generic/dl-prop.h
index 6b0f2aa..f1cf576 100644
--- a/sysdeps/generic/dl-prop.h
+++ b/sysdeps/generic/dl-prop.h
@@ -20,11 +20,11 @@
#define _DL_PROP_H
/* The following functions are used by the dynamic loader and the
- dlopen machinery to process PT_NOTE entries in the binary or
- shared object. The notes can be used to change the behaviour of
- the loader, and as such offer a flexible mechanism for hooking in
- various checks related to ABI tags or implementing "flag day" ABI
- transitions. */
+ dlopen machinery to process PT_NOTE and PT_GNU_PROPERTY entries in
+ the binary or shared object. The notes can be used to change the
+ behaviour of the loader, and as such offer a flexible mechanism
+ for hooking in various checks related to ABI tags or implementing
+ "flag day" ABI transitions. */
static inline void __attribute__ ((always_inline))
_rtld_main_check (struct link_map *m, const char *program)
@@ -36,17 +36,16 @@ _dl_open_check (struct link_map *m)
{
}
-#ifdef FILEBUF_SIZE
-static inline int __attribute__ ((always_inline))
-_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph,
- int fd, struct filebuf *fbp)
+static inline void __attribute__ ((always_inline))
+_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
{
- return 0;
}
-#endif
+/* Called for each property in the NT_GNU_PROPERTY_TYPE_0 note of L,
+ processing of the properties continues until this returns 0. */
static inline int __attribute__ ((always_inline))
-_rtld_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
+_dl_process_gnu_property (struct link_map *l, uint32_t type, uint32_t datasz,
+ void *data)
{
return 0;
}
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index d08b97a..c525ffa 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -910,6 +910,10 @@ extern void _dl_setup_hash (struct link_map *map) attribute_hidden;
extern void _dl_rtld_di_serinfo (struct link_map *loader,
Dl_serinfo *si, bool counting);
+/* Process PT_GNU_PROPERTY program header PH in module L after
+ PT_LOAD segments are mapped. */
+void _dl_process_pt_gnu_property (struct link_map *l, const ElfW(Phdr) *ph);
+
/* Search loaded objects' symbol tables for a definition of the symbol
referred to by UNDEF. *SYM is the symbol table entry containing the
diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
index 516f88e..89911e1 100644
--- a/sysdeps/x86/dl-prop.h
+++ b/sysdeps/x86/dl-prop.h
@@ -19,8 +19,6 @@
#ifndef _DL_PROP_H
#define _DL_PROP_H
-#include <not-cancel.h>
-
extern void _dl_cet_check (struct link_map *, const char *)
attribute_hidden;
extern void _dl_cet_open_check (struct link_map *)
@@ -146,48 +144,17 @@ _dl_process_cet_property_note (struct link_map *l,
#endif
}
-#ifdef FILEBUF_SIZE
-static inline int __attribute__ ((unused))
-_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph,
- int fd, struct filebuf *fbp)
+static inline void __attribute__ ((unused))
+_dl_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
{
-# if CET_ENABLED
- const ElfW(Nhdr) *note;
- ElfW(Nhdr) *note_malloced = NULL;
- ElfW(Addr) size = ph->p_filesz;
-
- if (ph->p_offset + size <= (size_t) fbp->len)
- note = (const void *) (fbp->buf + ph->p_offset);
- else
- {
- if (size < __MAX_ALLOCA_CUTOFF)
- note = alloca (size);
- else
- {
- note_malloced = malloc (size);
- note = note_malloced;
- }
- if (__pread64_nocancel (fd, (void *) note, size, ph->p_offset) != size)
- {
- if (note_malloced)
- free (note_malloced);
- return -1;
- }
- }
-
- _dl_process_cet_property_note (l, note, size, ph->p_align);
- if (note_malloced)
- free (note_malloced);
-# endif
- return 0;
+ const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr);
+ _dl_process_cet_property_note (l, note, ph->p_memsz, ph->p_align);
}
-#endif
-static inline int __attribute__ ((unused))
-_rtld_process_pt_note (struct link_map *l, const ElfW(Phdr) *ph)
+static inline int __attribute__ ((always_inline))
+_dl_process_gnu_property (struct link_map *l, uint32_t type, uint32_t datasz,
+ void *data)
{
- const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr);
- _dl_process_cet_property_note (l, note, ph->p_memsz, ph->p_align);
return 0;
}