public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Stas Sergeev <stsp2@yandex.ru>
To: libc-alpha@sourceware.org
Cc: Stas Sergeev <stsp2@yandex.ru>
Subject: [PATCH 3/3] elf/dl-audit: add _dl_audit_premap fn [BZ #30007]
Date: Wed, 15 Feb 2023 21:55:41 +0500	[thread overview]
Message-ID: <20230215165541.1107137-4-stsp2@yandex.ru> (raw)
In-Reply-To: <20230215165541.1107137-1-stsp2@yandex.ru>

This patch adds _dl_audit_premap() function that calls la_premap
audit call-back. That call-back takes the preferred map address and
map length, and gives back the address to where the solib should
actually be mapped.

In tst-auditmod-dlmem.c add such call-back as an example and use
MAP_32BIT flag in it to force the mapping into the low 4G of address
space.
Also add it to tst-auditmod18.c as dummy and make sure it is called.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 elf/dl-audit.c             | 22 ++++++++++++++++++++++
 elf/dl-map-segments.h      | 22 ++++++++++++++++++----
 elf/link.h                 |  2 ++
 elf/rtld.c                 |  3 ++-
 elf/tst-audit-dlmem.c      | 23 +++++++++++++++++++++++
 elf/tst-audit18.c          |  1 +
 elf/tst-auditmod-dlmem.c   | 16 ++++++++++++++++
 elf/tst-auditmod18.c       |  8 ++++++++
 sysdeps/generic/ldsodefs.h |  6 ++++++
 9 files changed, 98 insertions(+), 5 deletions(-)

diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index 76bf365168..de3f6e8013 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -94,6 +94,28 @@ _dl_audit_premap_dlmem (struct link_map *l, size_t maplength)
    return -1;
 }
 
+void *
+_dl_audit_premap (struct link_map *l, void *pref_addr, size_t maplength)
+{
+  if (__glibc_likely (GLRO(dl_naudit) == 0))
+    return MAP_FAILED;
+
+  struct audit_ifaces *afct = GLRO(dl_audit);
+  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+    {
+      if (afct->premap != NULL)
+	{
+	  struct auditstate *state = link_map_audit_state (l, cnt);
+	  void *addr = afct->premap (pref_addr, maplength, &state->cookie);
+	  if (addr != MAP_FAILED)
+	    return addr;
+	}
+
+      afct = afct->next;
+   }
+   return MAP_FAILED;
+}
+
 void
 _dl_audit_objopen (struct link_map *l, Lmid_t nsid)
 {
diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
index 89c0833544..cb630720d5 100644
--- a/elf/dl-map-segments.h
+++ b/elf/dl-map-segments.h
@@ -90,6 +90,7 @@ _dl_map_segments (struct link_map *l, void *fd,
 
   if (__glibc_likely (type == ET_DYN))
     {
+      bool fixed_addr = false;
       /* This is a position-independent shared object.  We can let the
          kernel map it anywhere it likes, but we must have space for all
          the segments in their specified positions relative to the first.
@@ -105,10 +106,23 @@ _dl_map_segments (struct link_map *l, void *fd,
         = (ELF_PREFERRED_ADDRESS (loader, maplength, c->mapstart)
            - MAP_BASE_ADDR (l));
 
-      /* Remember which part of the address space this object uses.  */
-      l->l_map_start = _dl_map_segment (c, mappref, maplength);
-      if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
-        return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+#ifdef SHARED
+      /* Call audit to let it change the address if he wants. */
+      void *pref_addr = _dl_audit_premap (l, (void *) mappref, maplength);
+      if (pref_addr != MAP_FAILED)
+        {
+          l->l_map_start = (ElfW(Addr)) pref_addr;
+          fixed_addr = true;
+        }
+#endif
+
+      if (!fixed_addr)
+        {
+          /* Remember which part of the address space this object uses.  */
+          l->l_map_start = _dl_map_segment (c, mappref, maplength);
+          if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
+            return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+        }
 
       l->l_map_end = l->l_map_start + maplength;
       l->l_addr = l->l_map_start - c->mapstart;
diff --git a/elf/link.h b/elf/link.h
index b59038c680..462df5b0bf 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -194,6 +194,8 @@ extern void la_activity (uintptr_t *__cookie, unsigned int __flag);
 extern char *la_objsearch (const char *__name, uintptr_t *__cookie,
 			   unsigned int __flag);
 extern int la_premap_dlmem (size_t maplength, uintptr_t *__cookie);
+extern void *la_premap (void *pref_addr, size_t maplength,
+			uintptr_t *__cookie);
 extern unsigned int la_objopen (struct link_map *__map, Lmid_t __lmid,
 				uintptr_t *__cookie);
 extern void la_preinit (uintptr_t *__cookie);
diff --git a/elf/rtld.c b/elf/rtld.c
index ce35d0a28b..b63937c5b9 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -990,7 +990,7 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
       return;
     }
 
-  enum { naudit_ifaces = 9 };
+  enum { naudit_ifaces = 10 };
   union
   {
     struct audit_ifaces ifaces;
@@ -1005,6 +1005,7 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
     "la_activity\0"
     "la_objsearch\0"
     "la_premap_dlmem\0"
+    "la_premap\0"
     "la_objopen\0"
     "la_preinit\0"
     LA_SYMBIND "\0"
diff --git a/elf/tst-audit-dlmem.c b/elf/tst-audit-dlmem.c
index 87c6d3741e..18ae13bd68 100644
--- a/elf/tst-audit-dlmem.c
+++ b/elf/tst-audit-dlmem.c
@@ -80,10 +80,24 @@ static int
 handle_restart (void)
 {
   {
+    Dl_info info;
     void *h = dlmem_wrapper ("../" LIBC_SO, RTLD_NOW);
 
     pid_t (*s) (void) = xdlsym (h, "getpid");
     TEST_COMPARE (s (), getpid ());
+    if (!dladdr (s, &info))
+      {
+        printf ("dladdr failed\n");
+        exit (EXIT_FAILURE);
+      }
+#ifdef MAP_32BIT
+    /* Our test audit module maps everything to lower 32bit. */
+    if ((unsigned long)info.dli_fbase >= 0x100000000)
+      {
+        printf ("premap audit didn't work\n");
+        exit (EXIT_FAILURE);
+      }
+#endif
 
     xdlclose (h);
   }
@@ -103,6 +117,14 @@ handle_restart (void)
         printf ("dladdr failed\n");
         exit (EXIT_FAILURE);
       }
+#ifdef MAP_32BIT
+    /* Our test audit module maps everything to lower 32bit. */
+    if ((unsigned long)info.dli_fbase >= 0x100000000)
+      {
+        printf ("premap audit didn't work\n");
+        exit (EXIT_FAILURE);
+      }
+#endif
     fprintf (stderr, "offset bar %lx\n", info.dli_saddr - info.dli_fbase);
     /* write another value for parent to read */
     *bar = TEST_BAR_VAL;
@@ -148,6 +170,7 @@ do_test (int argc, char *argv[])
     { "la_objsearch", false },
     { "la_activity", false },
     { "la_premap_dlmem", false },
+    { "la_premap", false },
     { "la_objopen", false },
     { "la_objclose", false },
     { "la_preinit", false },
diff --git a/elf/tst-audit18.c b/elf/tst-audit18.c
index 5d13dd0a48..f7ac9d45c3 100644
--- a/elf/tst-audit18.c
+++ b/elf/tst-audit18.c
@@ -91,6 +91,7 @@ do_test (int argc, char *argv[])
     { "la_version", false },
     { "la_objsearch", false },
     { "la_activity", false },
+    { "la_premap", false },
     { "la_objopen", false },
     { "la_objclose", false },
     { "la_preinit", false },
diff --git a/elf/tst-auditmod-dlmem.c b/elf/tst-auditmod-dlmem.c
index bd413da436..2486bd8882 100644
--- a/elf/tst-auditmod-dlmem.c
+++ b/elf/tst-auditmod-dlmem.c
@@ -68,6 +68,22 @@ la_premap_dlmem (size_t maplength, uintptr_t *cookie)
   return fd;
 }
 
+void *
+la_premap (void *addr, size_t maplength, uintptr_t *cookie)
+{
+  void *ret = MAP_FAILED;
+  fprintf (stderr, "%s\n", __func__);
+  /* If addr already set by elf, don't change. */
+  if (addr)
+    return MAP_FAILED;
+#ifdef MAP_32BIT
+  /* This mapping will be overwritten so use PROT_NONE. */
+  ret = mmap(NULL, maplength, PROT_NONE,
+             MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1, 0);
+#endif
+  return ret;
+}
+
 unsigned int
 la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
 {
diff --git a/elf/tst-auditmod18.c b/elf/tst-auditmod18.c
index cacada8d95..c16e28e8cb 100644
--- a/elf/tst-auditmod18.c
+++ b/elf/tst-auditmod18.c
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 #include <link.h>
+#include <sys/mman.h>  // for MAP_FAILED
 
 unsigned int
 la_version (unsigned int version)
@@ -39,6 +40,13 @@ la_activity (uintptr_t *cookie, unsigned int flag)
   fprintf (stderr, "%s\n", __func__);
 }
 
+void *
+la_premap (void *addr, size_t mapsize, uintptr_t *cookie)
+{
+  fprintf (stderr, "%s\n", __func__);
+  return MAP_FAILED;
+}
+
 unsigned int
 la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
 {
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 26000e1e81..8d8ee00b95 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -240,6 +240,7 @@ struct audit_ifaces
   void (*activity) (uintptr_t *, unsigned int);
   char *(*objsearch) (const char *, uintptr_t *, unsigned int);
   int (*premap_dlmem) (size_t, uintptr_t *);
+  void *(*premap) (void *, size_t, uintptr_t *);
   unsigned int (*objopen) (struct link_map *, Lmid_t, uintptr_t *);
   void (*preinit) (uintptr_t *);
   union
@@ -1373,6 +1374,11 @@ void _dl_audit_activity_nsid (Lmid_t nsid, int action)
 int _dl_audit_premap_dlmem (struct link_map *l, size_t maplength)
   attribute_hidden;
 
+/* Call la_premap from the audit modules from the link map and
+   get back an address to which the solib will be mapped.  */
+void *_dl_audit_premap (struct link_map *l, void *pref_addr, size_t maplength)
+  attribute_hidden;
+
 /* Call the la_objopen from the audit modules for the link_map L on the
    namespace identification NSID.  */
 void _dl_audit_objopen (struct link_map *l, Lmid_t nsid)
-- 
2.37.2


      parent reply	other threads:[~2023-02-15 16:55 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-15 16:55 [PATCH v7 0/3] implement dlmem() with audit extensions Stas Sergeev
2023-02-15 16:55 ` [PATCH 1/3] elf: strdup() l_name if no realname [BZ #30100] Stas Sergeev
2023-02-15 16:55 ` [PATCH 2/3] dlfcn,elf: implement dlmem() and audit [BZ #11767] Stas Sergeev
2023-02-20 15:50   ` Carlos O'Donell
2023-02-20 16:35     ` stsp
2023-03-18 17:04     ` stsp
2023-02-15 16:55 ` Stas Sergeev [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230215165541.1107137-4-stsp2@yandex.ru \
    --to=stsp2@yandex.ru \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).