From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19800 invoked by alias); 27 Jan 2004 18:59:27 -0000 Mailing-List: contact libc-hacker-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sources.redhat.com Received: (qmail 19779 invoked from network); 27 Jan 2004 18:59:26 -0000 Received: from unknown (HELO sunsite.ms.mff.cuni.cz) (195.113.19.66) by sources.redhat.com with SMTP; 27 Jan 2004 18:59:26 -0000 Received: from sunsite.ms.mff.cuni.cz (sunsite.mff.cuni.cz [127.0.0.1]) by sunsite.ms.mff.cuni.cz (8.12.8/8.12.8) with ESMTP id i0RGpbs6019118; Tue, 27 Jan 2004 17:51:37 +0100 Received: (from jakub@localhost) by sunsite.ms.mff.cuni.cz (8.12.8/8.12.8/Submit) id i0RGpb3l019116; Tue, 27 Jan 2004 17:51:37 +0100 Date: Tue, 27 Jan 2004 18:59:00 -0000 From: Jakub Jelinek To: Ulrich Drepper Cc: Glibc hackers Subject: [PATCH] One more RELRO fix Message-ID: <20040127165137.GU6811@sunsite.ms.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2004-01/txt/msg00107.txt.bz2 Hi! On !DONT_USE_BOOTSTRAP_MAP platforms, prelink stopped working. The problem is that ehdr = (ElfW(Ehdr) *) bootstrap_map.l_addr; of course doesn't work with prelinked ld.so. Setting GL(dl_rtld_map).l_relro_{addr,size} can very well be done later, after ld.so itself has been relocated for the first time but before second time relocation and it should be even faster (_dl_start used to cycle through all program headers, while the code in patch as PT_GNU_RELRO check is the sole thing in the loop can go from the last Phdr down till it finds it (ATM it is always the last one)). Also, ld.so apparently did not handle PT_GNU_RELRO program header in the executable, which this patch adds as well. Although in most executables PT_GNU_RELRO would be really small (essentially small .got, .dynamic, .ctors/.dtors/.jcr and that's about it), there are cases where it can be bigger and IMHO ld.so should handle it. 2004-01-27 Jakub Jelinek * elf/rtld.c (_dl_start_final): Don't set l_relro_* here. (_dl_start): And neither here. (dl_main): Set GL(dl_loaded)->l_relro_* and GL(dl_rtld_map)->l_relro_*. --- libc/elf/rtld.c.jj 2004-01-27 15:17:27.000000000 +0100 +++ libc/elf/rtld.c 2004-01-27 15:33:34.043449517 +0100 @@ -224,8 +224,6 @@ _dl_start_final (void *arg, struct dl_st memcpy (GL(dl_rtld_map).l_info, info->l.l_info, sizeof GL(dl_rtld_map).l_info); GL(dl_rtld_map).l_mach = info->l.l_mach; - GL(dl_rtld_map).l_relro_addr = info->l.l_relro_addr; - GL(dl_rtld_map).l_relro_size = info->l.l_relro_size; #endif _dl_setup_hash (&GL(dl_rtld_map)); GL(dl_rtld_map).l_opencount = 1; @@ -351,17 +349,16 @@ _dl_start (void *arg) on the `l_addr' value, which is not the value we want when prelinked. */ #if USE___THREAD dtv_t initdtv[3]; -#endif /* USE___THREAD */ ElfW(Ehdr) *ehdr # ifdef DONT_USE_BOOTSTRAP_MAP = (ElfW(Ehdr) *) &_begin; # else +# error This will not work with prelink. = (ElfW(Ehdr) *) bootstrap_map.l_addr; # endif ElfW(Phdr) *phdr = (ElfW(Phdr) *) ((void *) ehdr + ehdr->e_phoff); size_t cnt = ehdr->e_phnum; /* PT_TLS is usually the last phdr. */ while (cnt-- > 0) -#if USE___THREAD if (phdr[cnt].p_type == PT_TLS) { void *tlsblock; @@ -457,13 +454,7 @@ _dl_start (void *arg) /* So far this is module number one. */ bootstrap_map.l_tls_modid = 1; } - else #endif /* USE___THREAD */ - if (phdr[cnt].p_type == PT_GNU_RELRO) - { - bootstrap_map.l_relro_addr = phdr[cnt].p_vaddr; - bootstrap_map.l_relro_size = phdr[cnt].p_memsz; - } #ifdef ELF_MACHINE_BEFORE_RTLD_RELOC ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info); @@ -958,6 +949,11 @@ of this helper program; chances are you case PT_GNU_STACK: GL(dl_stack_flags) = ph->p_flags; break; + + case PT_GNU_RELRO: + GL(dl_loaded)->l_relro_addr = ph->p_vaddr; + GL(dl_loaded)->l_relro_size = ph->p_memsz; + break; } #ifdef USE_TLS /* Adjust the address of the TLS initialization image in case @@ -1030,10 +1026,21 @@ of this helper program; chances are you /* Set up the program header information for the dynamic linker itself. It is needed in the dl_iterate_phdr() callbacks. */ ElfW(Ehdr) *rtld_ehdr = (ElfW(Ehdr) *) GL(dl_rtld_map).l_map_start; - GL(dl_rtld_map).l_phdr = (ElfW(Phdr) *) (GL(dl_rtld_map).l_map_start - + rtld_ehdr->e_phoff); + ElfW(Phdr) *rtld_phdr = (ElfW(Phdr) *) (GL(dl_rtld_map).l_map_start + + rtld_ehdr->e_phoff); + GL(dl_rtld_map).l_phdr = rtld_phdr; GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum; + /* PT_GNU_RELRO is usually the last phdr. */ + size_t cnt = rtld_ehdr->e_phnum; + while (cnt-- > 0) + if (rtld_phdr[cnt].p_type == PT_GNU_RELRO) + { + GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr; + GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz; + break; + } + /* We have two ways to specify objects to preload: via environment variable and via the file /etc/ld.so.preload. The latter can also be used when security is enabled. */ Jakub