diff options
author | Kurt Miller <kurt@cvs.openbsd.org> | 2015-01-27 00:33:22 +0000 |
---|---|---|
committer | Kurt Miller <kurt@cvs.openbsd.org> | 2015-01-27 00:33:22 +0000 |
commit | 5d6219f03f61558879947e7df7b421a86cffdd6a (patch) | |
tree | aab9507c0592783f26ee96e5ad9d3bcfd766a37b | |
parent | 9f3935eea3833737ce1128b568dda34e5c4ab8ce (diff) |
Require EFT shared objects have a PT_PHDR entry to be considered
a pie binary. The kernel will now reject executing a typical shared
library with EINVAL. This breaks compatibility with initial static pie
binaries and requires a recent user-land prior to upgrading. In
addition, more fine grained errors can be returned from execve(2)
when errors occur while attempting to execute ELF objects.
okay guenther@, kettenis@, deraadt@
-rw-r--r-- | sys/kern/exec_elf.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/sys/kern/exec_elf.c b/sys/kern/exec_elf.c index 8954eabca0e..36882bdf65f 100644 --- a/sys/kern/exec_elf.c +++ b/sys/kern/exec_elf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_elf.c,v 1.109 2015/01/20 19:43:21 kettenis Exp $ */ +/* $OpenBSD: exec_elf.c,v 1.110 2015/01/27 00:33:21 kurt Exp $ */ /* * Copyright (c) 1996 Per Fogelstrom @@ -514,7 +514,7 @@ ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp) Elf_Ehdr *eh = epp->ep_hdr; Elf_Phdr *ph, *pp, *base_ph = NULL; Elf_Addr phdr = 0, exe_base = 0; - int error, i; + int error, i, has_phdr = 0; char *interp = NULL; u_long pos = 0, phsize; size_t randomizequota = ELF_RANDOMIZE_LIMIT; @@ -563,13 +563,17 @@ ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp) } else if (pp->p_type == PT_LOAD) { if (base_ph == NULL) base_ph = pp; + } else if (pp->p_type == PT_PHDR) { + has_phdr = 1; } } if (eh->e_type == ET_DYN) { - /* need load sections for PIE */ - if (base_ph == NULL) + /* need phdr and load sections for PIE */ + if (!has_phdr || base_ph == NULL) { + error = EINVAL; goto bad; + } /* randomize exe_base for PIE */ exe_base = uvm_map_pie(base_ph->p_align); } @@ -762,7 +766,9 @@ bad: pool_put(&namei_pool, interp); free(ph, M_TEMP, phsize); kill_vmcmds(&epp->ep_vmcmds); - return (ENOEXEC); + if (error == 0) + return (ENOEXEC); + return (error); } /* |