mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
rtld: Support multiple PT_GNU_RELRO program headers
Iterate over all the program headers in obj_remap_relro and remove the relro fields from Obj_Entry. Skip the call to obj_enforce_relro() in relocate_object() for the rtld object as well as the main program object. obj_enforce_relro() is called later when it safe to reference globals such as page_size. Reviewed by: kib Obtained from: CheriBSD Sponsored by: AFRL, DARPA Differential Revision: https://reviews.freebsd.org/D47884
This commit is contained in:
parent
34f5de82e8
commit
fda0403eb0
3 changed files with 20 additions and 32 deletions
|
|
@ -93,8 +93,6 @@ map_object(int fd, const char *path, const struct stat *sb)
|
|||
Elf_Addr bss_vlimit;
|
||||
caddr_t bss_addr;
|
||||
Elf_Word stack_flags;
|
||||
Elf_Addr relro_page;
|
||||
size_t relro_size;
|
||||
Elf_Addr note_start;
|
||||
Elf_Addr note_end;
|
||||
char *note_map;
|
||||
|
|
@ -114,8 +112,6 @@ map_object(int fd, const char *path, const struct stat *sb)
|
|||
nsegs = -1;
|
||||
phdyn = phinterp = phtls = NULL;
|
||||
phdr_vaddr = 0;
|
||||
relro_page = 0;
|
||||
relro_size = 0;
|
||||
note_start = 0;
|
||||
note_end = 0;
|
||||
note_map = NULL;
|
||||
|
|
@ -161,11 +157,6 @@ map_object(int fd, const char *path, const struct stat *sb)
|
|||
stack_flags = phdr->p_flags;
|
||||
break;
|
||||
|
||||
case PT_GNU_RELRO:
|
||||
relro_page = phdr->p_vaddr;
|
||||
relro_size = phdr->p_memsz;
|
||||
break;
|
||||
|
||||
case PT_NOTE:
|
||||
if (phdr->p_offset > page_size ||
|
||||
phdr->p_offset + phdr->p_filesz > page_size) {
|
||||
|
|
@ -323,9 +314,6 @@ map_object(int fd, const char *path, const struct stat *sb)
|
|||
obj->tlsinit = mapbase + phtls->p_vaddr;
|
||||
}
|
||||
obj->stack_flags = stack_flags;
|
||||
obj->relro_page = obj->relocbase + rtld_trunc_page(relro_page);
|
||||
obj->relro_size = rtld_trunc_page(relro_page + relro_size) -
|
||||
rtld_trunc_page(relro_page);
|
||||
if (note_start < note_end)
|
||||
digest_notes(obj, note_start, note_end);
|
||||
if (note_map != NULL)
|
||||
|
|
|
|||
|
|
@ -1672,12 +1672,6 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path)
|
|||
obj->stack_flags = ph->p_flags;
|
||||
break;
|
||||
|
||||
case PT_GNU_RELRO:
|
||||
obj->relro_page = obj->relocbase + rtld_trunc_page(ph->p_vaddr);
|
||||
obj->relro_size = rtld_trunc_page(ph->p_vaddr + ph->p_memsz) -
|
||||
rtld_trunc_page(ph->p_vaddr);
|
||||
break;
|
||||
|
||||
case PT_NOTE:
|
||||
note_start = (Elf_Addr)obj->relocbase + ph->p_vaddr;
|
||||
note_end = note_start + ph->p_filesz;
|
||||
|
|
@ -2369,11 +2363,6 @@ parse_rtld_phdr(Obj_Entry *obj)
|
|||
case PT_GNU_STACK:
|
||||
obj->stack_flags = ph->p_flags;
|
||||
break;
|
||||
case PT_GNU_RELRO:
|
||||
obj->relro_page = obj->relocbase +
|
||||
rtld_trunc_page(ph->p_vaddr);
|
||||
obj->relro_size = rtld_round_page(ph->p_memsz);
|
||||
break;
|
||||
case PT_NOTE:
|
||||
note_start = (Elf_Addr)obj->relocbase + ph->p_vaddr;
|
||||
note_end = note_start + ph->p_filesz;
|
||||
|
|
@ -3328,7 +3317,7 @@ relocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj,
|
|||
lockstate) == -1)
|
||||
return (-1);
|
||||
|
||||
if (!obj->mainprog && obj_enforce_relro(obj) == -1)
|
||||
if (obj != rtldobj && !obj->mainprog && obj_enforce_relro(obj) == -1)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
|
|
@ -5909,12 +5898,26 @@ _rtld_is_dlopened(void *arg)
|
|||
static int
|
||||
obj_remap_relro(Obj_Entry *obj, int prot)
|
||||
{
|
||||
const Elf_Phdr *ph;
|
||||
caddr_t relro_page;
|
||||
size_t relro_size;
|
||||
|
||||
if (obj->relro_size > 0 && mprotect(obj->relro_page, obj->relro_size,
|
||||
prot) == -1) {
|
||||
_rtld_error("%s: Cannot set relro protection to %#x: %s",
|
||||
obj->path, prot, rtld_strerror(errno));
|
||||
return (-1);
|
||||
for (ph = obj->phdr; (const char *)ph < (const char *)obj->phdr +
|
||||
obj->phsize; ph++) {
|
||||
switch (ph->p_type) {
|
||||
case PT_GNU_RELRO:
|
||||
relro_page = obj->relocbase +
|
||||
rtld_trunc_page(ph->p_vaddr);
|
||||
relro_size =
|
||||
rtld_round_page(ph->p_vaddr + ph->p_memsz) -
|
||||
rtld_trunc_page(ph->p_vaddr);
|
||||
if (mprotect(relro_page, relro_size, prot) == -1) {
|
||||
_rtld_error("%s: Cannot set relro protection to %#x: %s",
|
||||
obj->path, prot, rtld_strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,9 +165,6 @@ typedef struct Struct_Obj_Entry {
|
|||
size_t tlsalign; /* Alignment of static TLS block */
|
||||
size_t tlspoffset; /* p_offset of the static TLS block */
|
||||
|
||||
caddr_t relro_page;
|
||||
size_t relro_size;
|
||||
|
||||
/* Items from the dynamic section. */
|
||||
Elf_Addr *pltgot; /* PLT or GOT, depending on architecture */
|
||||
const Elf_Rel *rel; /* Relocation entries */
|
||||
|
|
|
|||
Loading…
Reference in a new issue