git: fda0403eb083 - main - rtld: Support multiple PT_GNU_RELRO program headers
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 06 Dec 2024 22:39:31 UTC
The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=fda0403eb0839b29b0b271c69c5cb6bfc874a3b5 commit fda0403eb0839b29b0b271c69c5cb6bfc874a3b5 Author: John Baldwin <jhb@FreeBSD.org> AuthorDate: 2024-12-06 22:37:50 +0000 Commit: John Baldwin <jhb@FreeBSD.org> CommitDate: 2024-12-06 22:37:50 +0000 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 --- libexec/rtld-elf/map_object.c | 12 ------------ libexec/rtld-elf/rtld.c | 37 ++++++++++++++++++++----------------- libexec/rtld-elf/rtld.h | 3 --- 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c index 0b1500a15183..7dbab26f2c63 100644 --- a/libexec/rtld-elf/map_object.c +++ b/libexec/rtld-elf/map_object.c @@ -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) diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index c585c47ce4da..7dc9d93dac26 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -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); } diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 5527671d647e..383b8db2114c 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -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 */