rtld-elf - Allow dynamic (late) relocations to relro section
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 11 Feb 2019 21:47:22 +0000 (13:47 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 11 Feb 2019 21:47:22 +0000 (13:47 -0800)
* Normally the relro section is mprotect()ed to read-only after normal
  load relocations.

* It appears that some programs can issue dynamic relocations at
  run-time to such sections.

* If the relro mprotect has been done on an object, temporarily mprotect
  the object back to RW to execute the relocation, then mprotect it back
  to RO.

Reported-by: marino
libexec/rtld-elf/rtld.c
libexec/rtld-elf/x86_64/reloc.c

index 1680ab1..9d59961 100644 (file)
@@ -2676,6 +2676,7 @@ relocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj,
                  obj->path, rtld_strerror(errno));
                return (-1);
            }
+           obj->relro_protected = true;
        }
        return (0);
 }
index 0356dff..7fb9131 100644 (file)
@@ -63,9 +63,13 @@ do_copy_relocations(Obj_Entry *dstobj)
 {
     const Elf_Rela *relalim;
     const Elf_Rela *rela;
+    int error = 0;
 
     assert(dstobj->mainprog);  /* COPY relocations are invalid elsewhere */
 
+    if (dstobj->relro_protected)
+       mprotect(dstobj->relro_page, dstobj->relro_size, PROT_READ | PROT_WRITE);
+
     relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + dstobj->relasize);
     for (rela = dstobj->rela;  rela < relalim;  rela++) {
        if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) {
@@ -99,7 +103,8 @@ do_copy_relocations(Obj_Entry *dstobj)
            if (srcobj == NULL) {
                _rtld_error("Undefined symbol \"%s\" referenced from COPY"
                  " relocation in %s", name, dstobj->path);
-               return -1;
+               error = -1;
+               break;
            }
 
            srcaddr = (const void *) (defobj->relocbase + srcsym->st_value);
@@ -107,7 +112,10 @@ do_copy_relocations(Obj_Entry *dstobj)
        }
     }
 
-    return 0;
+    if (dstobj->relro_protected)
+       mprotect(dstobj->relro_page, dstobj->relro_size, PROT_READ);
+
+    return error;
 }
 
 /* Initialize the special GOT entries. */