Handle textrels like other architectures do.
authorderaadt <deraadt@openbsd.org>
Tue, 21 Jun 2016 15:21:42 +0000 (15:21 +0000)
committerderaadt <deraadt@openbsd.org>
Tue, 21 Jun 2016 15:21:42 +0000 (15:21 +0000)
ok kettenis guenther

libexec/ld.so/hppa/rtld_machine.c

index 5074534..6279a56 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rtld_machine.c,v 1.32 2015/11/02 07:02:53 guenther Exp $      */
+/*     $OpenBSD: rtld_machine.c,v 1.33 2016/06/21 15:21:42 deraadt Exp $       */
 
 /*
  * Copyright (c) 2004 Michael Shalayeff
@@ -107,6 +107,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
        Elf_Addr        loff;
        int     i, numrela, fails = 0;
        size_t  size;
+       struct load_list *llist;
 
        loff = object->obj_base;
        numrela = object->Dyn.info[relasz] / sizeof(Elf_RelA);
@@ -146,6 +147,17 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
                object->dyn.fini = (void *)addr;
        }
 
+       /*
+        * unprotect some segments if we need it.
+        */
+       if ((object->dyn.textrel == 1) && (rel == DT_REL || rel == DT_RELA)) {
+               for (llist = object->load_list; llist != NULL; llist = llist->next) {
+                       if (!(llist->prot & PROT_WRITE))
+                               _dl_mprotect(llist->start, llist->size,
+                                   PROT_READ|PROT_WRITE);
+               }
+       }
+
        /*
         * this is normally done by the crt0 code but we have to make
         * sure it's set here to allow constructors to call functions
@@ -289,6 +301,15 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
                }
        }
 
+       /* reprotect the unprotected segments */
+       if ((object->dyn.textrel == 1) && (rel == DT_REL || rel == DT_RELA)) {
+               for (llist = object->load_list; llist != NULL; llist = llist->next) {
+                       if (!(llist->prot & PROT_WRITE))
+                               _dl_mprotect(llist->start, llist->size,
+                                   llist->prot);
+               }
+       }
+
        return (fails);
 }