From c22b5e2a12878776f1b0003d0555df54d425719a Mon Sep 17 00:00:00 2001 From: maxv Date: Wed, 19 Feb 2014 15:23:20 +0000 Subject: [PATCH] We need VMCMDs for a binary and its interpreter, so make sure we have at least one VMCMD. This also prevents the kernel from using an uninitialized pointer as entry point for the execution. From me and Christos ok christos@ --- sys/kern/exec_elf.c | 23 +++++++++++++++++++---- sys/kern/kern_exec.c | 7 +++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/sys/kern/exec_elf.c b/sys/kern/exec_elf.c index 30622e4ab302..6248ec12672e 100644 --- a/sys/kern/exec_elf.c +++ b/sys/kern/exec_elf.c @@ -1,4 +1,4 @@ -/* $NetBSD: exec_elf.c,v 1.58 2014/02/16 17:46:36 maxv Exp $ */ +/* $NetBSD: exec_elf.c,v 1.59 2014/02/19 15:23:20 maxv Exp $ */ /*- * Copyright (c) 1994, 2000, 2005 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include -__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.58 2014/02/16 17:46:36 maxv Exp $"); +__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.59 2014/02/19 15:23:20 maxv Exp $"); #ifdef _KERNEL_OPT #include "opt_pax.h" @@ -796,6 +796,14 @@ exec_elf_makecmds(struct lwp *l, struct exec_package *epp) break; } } + + if (epp->ep_vmcmds.evs_cmds == NULL) { + /* No VMCMD; there was no PT_LOAD section, or those + * sections were empty */ + error = ENOEXEC; + goto bad; + } + if (interp || (epp->ep_flags & EXEC_FORCEAUX) != 0) { ap = kmem_alloc(sizeof(*ap), KM_SLEEP); ap->arg_interp = (vaddr_t)NULL; @@ -811,7 +819,7 @@ exec_elf_makecmds(struct lwp *l, struct exec_package *epp) * its interpreter */ if (interp) { - int j = epp->ep_vmcmds.evs_used; + int nused = epp->ep_vmcmds.evs_used; u_long interp_offset = 0; if ((error = elf_load_file(l, epp, interp, @@ -819,7 +827,14 @@ exec_elf_makecmds(struct lwp *l, struct exec_package *epp) kmem_free(ap, sizeof(*ap)); goto bad; } - ap->arg_interp = epp->ep_vmcmds.evs_cmds[j].ev_addr; + if (epp->ep_vmcmds.evs_used == nused) { + /* elf_load_file() has not set up any new VMCMD */ + kmem_free(ap, sizeof(*ap)); + error = ENOEXEC; + goto bad; + } + + ap->arg_interp = epp->ep_vmcmds.evs_cmds[nused].ev_addr; epp->ep_entry = ap->arg_interp + interp_offset; PNBUF_PUT(interp); } else diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 51c7adebcd6b..e0d3cd18fe5e 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exec.c,v 1.376 2014/02/17 19:29:46 maxv Exp $ */ +/* $NetBSD: kern_exec.c,v 1.377 2014/02/19 15:23:20 maxv Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -59,7 +59,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.376 2014/02/17 19:29:46 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.377 2014/02/19 15:23:20 maxv Exp $"); #include "opt_exec.h" #include "opt_execfmt.h" @@ -658,8 +658,7 @@ execve_loadvm(struct lwp *l, const char *path, char * const *args, data->ed_pack.ep_hdrvalid = 0; data->ed_pack.ep_emul_arg = NULL; data->ed_pack.ep_emul_arg_free = NULL; - data->ed_pack.ep_vmcmds.evs_cnt = 0; - data->ed_pack.ep_vmcmds.evs_used = 0; + memset(&data->ed_pack.ep_vmcmds, 0, sizeof(data->ed_pack.ep_vmcmds)); data->ed_pack.ep_vap = &data->ed_attr; data->ed_pack.ep_flags = 0; MD_TOPDOWN_INIT(&data->ed_pack);