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
prev 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).