summaryrefslogtreecommitdiff
path: root/libexec/ld.so/boot.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2017-01-09 22:51:05 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2017-01-09 22:51:05 +0000
commit91602f733fc8f36bc58a964d8d49479b01293aeb (patch)
tree4a8a0721223a481bea0b743b9ca2e37191945265 /libexec/ld.so/boot.c
parent78cdd75ca94c869a8296979fb9d2d95913aafa3e (diff)
Remove dependency on __got_{start,end} symbols and look at PT_GNU_RELRO
instead. Result in a few more pages that aren't writable on some platforms (such as hppa). Based on an initial diff from guenther@. Thanks to deraadt@ for testing. ok guenther@
Diffstat (limited to 'libexec/ld.so/boot.c')
-rw-r--r--libexec/ld.so/boot.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/libexec/ld.so/boot.c b/libexec/ld.so/boot.c
index 52a460fa6ce..a4ed06ea062 100644
--- a/libexec/ld.so/boot.c
+++ b/libexec/ld.so/boot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: boot.c,v 1.14 2016/08/13 20:57:04 guenther Exp $ */
+/* $OpenBSD: boot.c,v 1.15 2017/01/09 22:51:04 kettenis Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -87,6 +87,8 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynp)
long loff;
Elf_Addr i;
RELOC_TYPE *rp;
+ Elf_Ehdr *ehdp;
+ Elf_Phdr *phdp;
/*
* Scan argument and environment vectors. Find dynamic
@@ -189,4 +191,30 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynp)
* we have been fully relocated here, so most things no longer
* need the loff adjustment
*/
+
+ /*
+ * No further changes to the PLT and/or GOT are needed so make
+ * them read-only.
+ */
+
+ /* do any RWX -> RX fixups for executable PLTs and apply GNU_RELRO */
+ ehdp = (Elf_Ehdr *)loff;
+ phdp = (Elf_Phdr *)(loff + ehdp->e_phoff);
+ for (i = 0; i < ehdp->e_phnum; i++, phdp++) {
+ switch (phdp->p_type) {
+#if defined(__alpha__) || defined(__hppa__) || defined(__powerpc__) || \
+ defined(__sparc64__)
+ case PT_LOAD:
+ if ((phdp->p_flags & (PF_X | PF_W)) != (PF_X | PF_W))
+ break;
+ _dl_mprotect((void *)(phdp->p_vaddr + loff),
+ phdp->p_memsz, PROT_READ);
+ break;
+#endif
+ case PT_GNU_RELRO:
+ _dl_mprotect((void *)(phdp->p_vaddr + loff),
+ phdp->p_memsz, PROT_READ);
+ break;
+ }
+ }
}