diff mbox series

[v3,17/32] elf: Allocate auditor state after read-write link map

Message ID 2135e6ae1fe527d3aa74666e6d609972a147f587.1701944612.git.fweimer@redhat.com
State New
Headers show
Series RELRO linkmaps | expand

Commit Message

Florian Weimer Dec. 7, 2023, 10:32 a.m. UTC
Auditors can write to the cookie member, so it has to remain
read-write even if other parts of the link map are write-protected.
---
 elf/dl-object.c            |  6 +++---
 elf/rtld.c                 |  9 +++++++--
 include/link.h             |  9 +++++----
 sysdeps/generic/ldsodefs.h | 17 +++--------------
 4 files changed, 18 insertions(+), 23 deletions(-)

Comments

Joseph Myers Feb. 26, 2024, 10:01 p.m. UTC | #1
On Thu, 7 Dec 2023, Florian Weimer wrote:

> Auditors can write to the cookie member, so it has to remain
> read-write even if other parts of the link map are write-protected.

OK.
diff mbox series

Patch

diff --git a/elf/dl-object.c b/elf/dl-object.c
index 1a9b04dd3c..0741371b80 100644
--- a/elf/dl-object.c
+++ b/elf/dl-object.c
@@ -89,12 +89,12 @@  _dl_new_object (char *realname, const char *libname, int type,
 # define audit_space 0
 #endif
 
-  new = calloc (sizeof (*new) + audit_space
+  new = calloc (sizeof (*new)
 		+ sizeof (struct link_map_private *)
 		+ sizeof (*newname) + libname_len, 1);
   if (new == NULL)
     return NULL;
-  new->l_rw = calloc (1, sizeof (*new->l_rw));
+  new->l_rw = calloc (1, sizeof (*new->l_rw) + audit_space);
   if (new->l_rw == NULL)
     {
       free (new);
@@ -103,7 +103,7 @@  _dl_new_object (char *realname, const char *libname, int type,
 
   new->l_real = new;
   new->l_symbolic_searchlist.r_list
-    = (struct link_map_private **) ((char *) (new + 1) + audit_space);
+    = (struct link_map_private **) ((char *) (new + 1));
 
   new->l_libname = newname
     = (struct libname_list *) (new->l_symbolic_searchlist.r_list + 1);
diff --git a/elf/rtld.c b/elf/rtld.c
index 25a9c8aa58..b2f0b478bb 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -458,8 +458,13 @@  _dl_start_final (void *arg, struct dl_start_final_info *info)
      interfere with __rtld_static_init.  */
   GLRO (dl_find_object) = &_dl_find_object;
 
-  static struct link_map_rw rtld_map_rw;
-  GL (dl_rtld_map).l_rw = &rtld_map_rw;
+  /* Pre-allocated read-write status of the ld.so link map.  */
+  static struct
+  {
+    struct link_map_rw l;
+    struct auditstate _dl_rtld_auditstate[DL_NNS];
+  } rtld_map_rw;
+  GL (dl_rtld_map).l_rw = &rtld_map_rw.l;
 #if NO_TLS_OFFSET != 0
   GL (dl_rtld_map).l_rw->l_tls_offset = NO_TLS_OFFSET;
 #endif
diff --git a/include/link.h b/include/link.h
index 220926248c..c752bc2cb7 100644
--- a/include/link.h
+++ b/include/link.h
@@ -372,15 +372,16 @@  l_next (struct link_map_private *l)
 
 #include <dl-relocate-ld.h>
 
-/* Information used by audit modules.  For most link maps, this data
-   immediate follows the link map in memory.  For the dynamic linker,
-   it is allocated separately.  See link_map_audit_state in
-   <ldsodefs.h>.  */
+/* Information used by audit modules.  An array of size GLRO (naudit)
+   elements follows the l_rw link map data in memory (in some cases
+   conservatively extended to to DL_NNS).  */
 struct auditstate
 {
   uintptr_t cookie;
   unsigned int bindflags;
 };
+_Static_assert (__alignof (struct auditstate) <= __alignof (struct link_map_rw),
+		"auditstate alignment compatible with link_map_rw alignment");
 
 
 /* This is the hidden instance of struct r_debug_extended used by the
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 53cc428421..d6d45f8c69 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -396,11 +396,6 @@  struct rtld_global
 
   /* Structure describing the dynamic linker itself.  */
   EXTERN struct link_map_private _dl_rtld_map;
-#ifdef SHARED
-  /* Used to store the audit information for the link map of the
-     dynamic loader.  */
-  struct auditstate _dl_rtld_auditstate[DL_NNS];
-#endif
 
 #if !PTHREAD_IN_LIBC && defined SHARED \
     && defined __rtld_lock_default_lock_recursive
@@ -1323,15 +1318,9 @@  rtld_active (void)
 static inline struct auditstate *
 link_map_audit_state (struct link_map_private *l, size_t index)
 {
-  if (l == &GL (dl_rtld_map))
-    /* The auditstate array is stored separately.  */
-    return &GL (dl_rtld_auditstate) [index];
-  else
-    {
-      /* The auditstate array follows the link map in memory.  */
-      struct auditstate *base = (struct auditstate *) (l + 1);
-      return &base[index];
-    }
+  /* The auditstate array follows the read-write link map part in memory.  */
+  struct auditstate *base = (struct auditstate *) (l->l_rw + 1);
+  return &base[index];
 }
 
 /* Call the la_objsearch from the audit modules from the link map L.  If