From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from forward105p.mail.yandex.net (forward105p.mail.yandex.net [IPv6:2a02:6b8:0:1472:2741:0:8b7:108]) by sourceware.org (Postfix) with ESMTPS id E66313858296 for ; Wed, 15 Feb 2023 16:55:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E66313858296 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=yandex.ru Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=yandex.ru Received: from sas8-d2832c3b6ed7.qloud-c.yandex.net (sas8-d2832c3b6ed7.qloud-c.yandex.net [IPv6:2a02:6b8:c1b:2a09:0:640:d283:2c3b]) by forward105p.mail.yandex.net (Yandex) with ESMTP id D315C2FD8BD5 for ; Wed, 15 Feb 2023 19:55:55 +0300 (MSK) Received: by sas8-d2832c3b6ed7.qloud-c.yandex.net (smtp/Yandex) with ESMTPSA id ltnGKJ2eY0U1-Q4PGZXRO; Wed, 15 Feb 2023 19:55:55 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1676480155; bh=1pgC5dENeE9lhDsMG+ztq/l2JhkJOBWS0hTBomVhwCw=; h=Message-Id:Date:In-Reply-To:Cc:Subject:References:To:From; b=SKJ54ov1Vsnh8g+GwJfYppT1iFeoc3aACbXZ6gI3wtttHGEwzeCodl/EDTHiBe2Z1 7wSQWIsWxwjAe1SU9Nx+anvRseIok0zh8oGNPFfkVIEU9lDdFl9Nxk4IfTMpeJFz4Q Bob2JHvLCQXa8WdKd5ZrrHOkUtOrfkRDTFPDIr24= Authentication-Results: sas8-d2832c3b6ed7.qloud-c.yandex.net; dkim=pass header.i=@yandex.ru From: Stas Sergeev To: libc-alpha@sourceware.org Cc: Stas Sergeev Subject: [PATCH 3/3] elf/dl-audit: add _dl_audit_premap fn [BZ #30007] Date: Wed, 15 Feb 2023 21:55:41 +0500 Message-Id: <20230215165541.1107137-4-stsp2@yandex.ru> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230215165541.1107137-1-stsp2@yandex.ru> References: <20230215165541.1107137-1-stsp2@yandex.ru> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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 --- 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 #include +#include // 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