The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=fda0403eb0839b29b0b271c69c5cb6bfc874a3b5

commit fda0403eb0839b29b0b271c69c5cb6bfc874a3b5
Author:     John Baldwin <j...@freebsd.org>
AuthorDate: 2024-12-06 22:37:50 +0000
Commit:     John Baldwin <j...@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 */

Reply via email to