diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-01-09 22:51:05 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-01-09 22:51:05 +0000 |
commit | 91602f733fc8f36bc58a964d8d49479b01293aeb (patch) | |
tree | 4a8a0721223a481bea0b743b9ca2e37191945265 /libexec/ld.so/boot.c | |
parent | 78cdd75ca94c869a8296979fb9d2d95913aafa3e (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.c | 30 |
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; + } + } } |