diff options
| author | Florian Weimer <fweimer@redhat.com> | 2024-07-02 13:19:13 +0200 |
|---|---|---|
| committer | Florian Weimer <fweimer@redhat.com> | 2024-07-08 15:28:00 +0200 |
| commit | a2f53a77559b610c8bf762c5d22172d9d45800e0 (patch) | |
| tree | be4fbd7a144bcb5840be71d09ef117a55794f41a /elf/rtld.c | |
| parent | 9fc639f654dc004736836613be703e6bed0c36a8 (diff) | |
| download | glibc-fw/bug31943-with-test.tar.xz glibc-fw/bug31943-with-test.zip | |
elf: Handle ld.so with LOAD segment gaps in _dl_find_object (bug 31943)fw/bug31943-with-test
Diffstat (limited to 'elf/rtld.c')
| -rw-r--r-- | elf/rtld.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/elf/rtld.c b/elf/rtld.c index bfdf632e77..337901007d 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1766,6 +1766,30 @@ dl_main (const ElfW(Phdr) *phdr, GL(dl_rtld_map).l_phdr = rtld_phdr; GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum; + GL(dl_rtld_map).l_contiguous = 1; +#ifdef HAVE_LD_LOAD_GAPS + /* The linker may not have produced a contiguous object. The kernel + will load the object with actual gaps (unlike the glibc loader + for shared objects, which always produces a contiguous mapping). + See similar logic in rtld_setup_main_map. */ + { + ElfW(Addr) expected_load_address = 0; + for (const ElfW(Phdr) *ph = rtld_phdr; ph < &phdr[rtld_ehdr->e_phnum]; + ++ph) + if (ph->p_type == PT_LOAD) + { + ElfW(Addr) mapstart = ph->p_vaddr & ~(GLRO(dl_pagesize) - 1); + if (GL(dl_rtld_map).l_contiguous && expected_load_address != 0 + && expected_load_address != mapstart) + GL(dl_rtld_map).l_contiguous = 0; + ElfW(Addr) allocend = ph->p_vaddr + ph->p_memsz; + /* The next expected address is the page following this load + segment. */ + expected_load_address = ((allocend + GLRO(dl_pagesize) - 1) + & ~(GLRO(dl_pagesize) - 1)); + } + } +#endif /* PT_GNU_RELRO is usually the last phdr. */ |
