From 45ae28e3c073931e77538a0babb458e29c066364 Mon Sep 17 00:00:00 2001 From: guenther Date: Mon, 8 Aug 2016 22:05:26 +0000 Subject: [PATCH] Look for a PT_GNU_RELRO section and, if present, mprotect that range instead of the [__got_start, __got_end) range. Also, instead of mprotecting the [__plt_start, __plt_end) range, just scan for sections which are both writable and executable and mprotect them to read-only. (This part was stolen from kettenis@) ok kettenis@ --- lib/csu/boot.h | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/csu/boot.h b/lib/csu/boot.h index c0a541f76e6..1e9fae0684e 100644 --- a/lib/csu/boot.h +++ b/lib/csu/boot.h @@ -1,4 +1,4 @@ -/* $OpenBSD: boot.h,v 1.21 2016/08/07 02:44:00 guenther Exp $ */ +/* $OpenBSD: boot.h,v 1.22 2016/08/08 22:05:26 guenther Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -86,8 +86,6 @@ struct boot_dyn { */ void _dl_boot_bind(const long, long *, Elf_Dyn *); -extern char __plt_start[]; -extern char __plt_end[]; extern char __got_start[]; extern char __got_end[]; @@ -106,6 +104,7 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp) long loff; int prot_exec = 0; RELOC_TYPE *rp; + Elf_Phdr *phdp; Elf_Addr i; /* @@ -220,12 +219,29 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp) else pagesize = 4096; -#if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || \ - defined(__sparc64__) - start = ELF_TRUNC((Elf_Addr)__plt_start, pagesize); - size = ELF_ROUND((Elf_Addr)__plt_end - start, pagesize); - mprotect((void *)start, size, PROT_READ); + /* do any RWX -> RX fixups for executable PLTs and apply GNU_RELRO */ + phdp = (Elf_Phdr *)dl_data[AUX_phdr]; + for (i = 0; i < dl_data[AUX_phnum]; i++, phdp++) { + switch (phdp->p_type) { +#if defined(__alpha__) || defined(__hppa__) || defined(__powerpc__) || \ + defined(__sparc__) || defined(__sparc64__) + case PT_LOAD: + if ((phdp->p_flags & (PF_X | PF_W)) != (PF_X | PF_W)) + break; + mprotect((void *)(phdp->p_vaddr + loff), phdp->p_memsz, + PROT_READ); + break; #endif + case PT_GNU_RELRO: + mprotect((void *)(phdp->p_vaddr + loff), phdp->p_memsz, + PROT_READ); + /* + * GNU_RELRO (a) covers the GOT, and (b) comes after + * all LOAD sections, so if we found it then we're done + */ + return; + } + } #if defined(__powerpc__) if (dynld.dt_proc[DT_PROC(DT_PPC_GOT)] == 0) -- 2.20.1