This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] mprotect segments with extra PROT_WRITE bit when DT_TEXTREL bit is set
- From: Fangrui Song <maskray at google dot com>
- To: libc-alpha at sourceware dot org
- Date: Wed, 22 Aug 2018 22:52:16 -0700
- Subject: [PATCH] mprotect segments with extra PROT_WRITE bit when DT_TEXTREL bit is set
Currently, DT_TEXTREL is incompatible with IFUNC. When DT_TEXTREL or
DF_TEXTREL is seen, the dynamic linker calls __mprotect on the segments
with PROT_READ|PROT_WRITE before applying dynamic relocations. It leads
to segfault when performing IFUNC resolution.
This patch makes it call __mprotect with extra PROT_WRITE bit, which
will keep the PROT_EXEC bit if exists, and thus fixes the segfault.
FreeBSD rtld libexec/rtld-elf/rtld.c (reloc_textrel_prot) does the same.
2018-08-22 Fangrui Song <maskray@google.com>
* elf/dl-reloc.c (_dl_relocate_object): __mprotect with extra
PROT_WRITE bit.
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 053916eeae..bd7d1ae84f 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -199,14 +199,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
- ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize));
newp->start = PTR_ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize))
+ (caddr_t) l->l_addr;
-
- if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)
- {
- errstring = N_("cannot make segment writable for relocation");
- call_error:
- _dl_signal_error (errno, l->l_name, NULL, errstring);
- }
-
#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
newp->prot = (PF_TO_PROT
>> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
@@ -220,6 +212,14 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
newp->prot |= PROT_EXEC;
#endif
newp->next = textrels;
+
+ if (__mprotect (newp->start, newp->len, newp->prot|PROT_WRITE) < 0)
+ {
+ errstring = N_("cannot make segment writable for relocation");
+ call_error:
+ _dl_signal_error (errno, l->l_name, NULL, errstring);
+ }
+
textrels = newp;
}
}
--
宋方睿