Index: kern/exec_elf32.c =================================================================== RCS file: /cvsroot/src/sys/kern/exec_elf32.c,v retrieving revision 1.136 diff -u -p -r1.136 exec_elf32.c --- kern/exec_elf32.c 15 Sep 2008 18:12:56 -0000 1.136 +++ kern/exec_elf32.c 11 Jan 2009 13:20:57 -0000 @@ -1,7 +1,7 @@ /* $NetBSD: exec_elf32.c,v 1.136 2008/09/15 18:12:56 rmind Exp $ */ /*- - * Copyright (c) 1994, 2000, 2005 The NetBSD Foundation, Inc. + * Copyright (c) 1994, 2000, 2005, 2009 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -401,7 +401,6 @@ elf_load_file(struct lwp *l, struct exec { int error, i; struct vnode *vp; - struct vattr attr; Elf_Ehdr eh; Elf_Phdr *ph = NULL; const Elf_Phdr *ph0; @@ -412,6 +411,8 @@ elf_load_file(struct lwp *l, struct exec struct proc *p; p = l->l_proc; + ph = NULL; + phsize = 0; /* XXXgcc */ /* * 1. open file @@ -440,10 +441,6 @@ elf_load_file(struct lwp *l, struct exec if ((error = VOP_ACCESS(vp, VEXEC, l->l_cred)) != 0) goto badunlock; - /* get attributes */ - if ((error = VOP_GETATTR(vp, &attr, l->l_cred)) != 0) - goto badunlock; - /* * Check mount point. Though we're not trying to exec this binary, * we will be executing code from it, so if the mount point @@ -464,24 +461,24 @@ elf_load_file(struct lwp *l, struct exec if (error) goto badunlock; - VOP_UNLOCK(vp, 0); - - if ((error = exec_read_from(l, vp, 0, &eh, sizeof(eh))) != 0) - goto bad; + if ((error = exec_read_locked(vp, 0, &eh, sizeof(eh))) != 0) + goto badunlock; if ((error = elf_check_header(&eh, ET_DYN)) != 0) - goto bad; + goto badunlock; if (eh.e_phnum > MAXPHNUM || eh.e_phnum == 0) { error = ENOEXEC; - goto bad; + goto badunlock; } phsize = eh.e_phnum * sizeof(Elf_Phdr); ph = kmem_alloc(phsize, KM_SLEEP); - if ((error = exec_read_from(l, vp, eh.e_phoff, ph, phsize)) != 0) - goto bad; + if ((error = exec_read_locked(vp, eh.e_phoff, ph, phsize)) != 0) + goto badunlock; + + VOP_UNLOCK(vp, 0); #ifdef ELF_INTERP_NON_RELOCATABLE /* @@ -673,8 +670,7 @@ exec_elf_makecmds(struct lwp *l, struct phsize = eh->e_phnum * sizeof(Elf_Phdr); ph = kmem_alloc(phsize, KM_SLEEP); - if ((error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize)) != - 0) + if ((error = exec_read(epp, eh->e_phoff, ph, phsize)) != 0) goto bad; epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR); @@ -689,8 +685,8 @@ exec_elf_makecmds(struct lwp *l, struct } interp = PNBUF_GET(); interp[0] = '\0'; - if ((error = exec_read_from(l, epp->ep_vp, - pp->p_offset, interp, pp->p_filesz)) != 0) + if ((error = exec_read(epp, pp->p_offset, interp, + pp->p_filesz)) != 0) goto bad; break; } @@ -849,7 +845,7 @@ netbsd_elf_signature(struct lwp *l, stru phsize = eh->e_phnum * sizeof(Elf_Phdr); ph = kmem_alloc(phsize, KM_SLEEP); - error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize); + error = exec_read(epp, eh->e_phoff, ph, phsize); if (error) goto out; @@ -863,8 +859,7 @@ netbsd_elf_signature(struct lwp *l, stru continue; np = kmem_alloc(ephp->p_filesz, KM_SLEEP); - error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np, - ephp->p_filesz); + error = exec_read(epp, ephp->p_offset, np, ephp->p_filesz); if (error) goto next; Index: kern/exec_subr.c =================================================================== RCS file: /cvsroot/src/sys/kern/exec_subr.c,v retrieving revision 1.61 diff -u -p -r1.61 exec_subr.c --- kern/exec_subr.c 2 Jun 2008 16:16:27 -0000 1.61 +++ kern/exec_subr.c 11 Jan 2009 13:20:57 -0000 @@ -45,10 +45,8 @@ __KERNEL_RCSID(0, "$NetBSD: exec_subr.c, #include #include #include - -#ifdef PAX_MPROTECT +#include #include -#endif /* PAX_MPROTECT */ #include @@ -354,6 +352,44 @@ exec_read_from(struct lwp *l, struct vno } /* + * exec_read_locked(): + * + * As exec_read_from(), but with vnode already locked. + */ +int +exec_read_locked(struct vnode *vp, u_long off, void *bf, size_t size) +{ + int error; + size_t resid; + + if ((error = vn_rdwr(UIO_READ, vp, bf, size, off, UIO_SYSSPACE, + IO_NODELOCKED, kauth_cred_get(), &resid, NULL)) != 0) + return error; + /* + * See if we got all of it + */ + if (resid != 0) + return ENOEXEC; + return 0; +} + +/* + * exec_read(): + * + * Read from executable into buffer at offset. + */ +int +exec_read(struct exec_package *epp, u_long off, void *bf, size_t size) +{ + + if (off + size < epp->ep_hdrvalid) { + memcpy(bf, (uint8_t *)epp->ep_hdr + off, size); + return 0; + } + return exec_read_from(curlwp, epp->ep_vp, off, bf, size); +} + +/* * exec_setup_stack(): Set up the stack segment for an elf * executable. * Index: kern/kern_exec.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_exec.c,v retrieving revision 1.280.4.1 diff -u -p -r1.280.4.1 kern_exec.c --- kern/kern_exec.c 18 Nov 2008 17:11:52 -0000 1.280.4.1 +++ kern/kern_exec.c 11 Jan 2009 13:20:58 -0000 @@ -97,6 +97,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_exec.c, #include #include #include +#include #if NVERIEXEC > 0 #include #endif /* NVERIEXEC > 0 */ @@ -337,8 +338,16 @@ check_exec(struct lwp *l, struct exec_pa if ((error = VOP_OPEN(vp, FREAD, l->l_cred)) != 0) goto bad1; - /* unlock vp, since we need it unlocked from here on out. */ + /* + * now we have the file, get the exec header. + * unlock vp, since we need it unlocked from here on out. + */ + error = vn_rdwr(UIO_READ, vp, epp->ep_hdr, epp->ep_hdrlen, 0, + UIO_SYSSPACE, IO_NODELOCKED, l->l_cred, &resid, NULL); VOP_UNLOCK(vp, 0); + if (error) + goto bad2; + epp->ep_hdrvalid = epp->ep_hdrlen - resid; #if NVERIEXEC > 0 error = veriexec_verify(l, vp, ndp->ni_cnd.cn_pnbuf, @@ -354,13 +363,6 @@ check_exec(struct lwp *l, struct exec_pa goto bad2; #endif /* PAX_SEGVGUARD */ - /* now we have the file, get the exec header */ - error = vn_rdwr(UIO_READ, vp, epp->ep_hdr, epp->ep_hdrlen, 0, - UIO_SYSSPACE, 0, l->l_cred, &resid, NULL); - if (error) - goto bad2; - epp->ep_hdrvalid = epp->ep_hdrlen - resid; - /* * Set up default address space limits. Can be overridden * by individual exec packages. Index: sys/exec.h =================================================================== RCS file: /cvsroot/src/sys/sys/exec.h,v retrieving revision 1.124 diff -u -p -r1.124 exec.h --- sys/exec.h 2 Jul 2008 17:28:57 -0000 1.124 +++ sys/exec.h 11 Jan 2009 13:20:58 -0000 @@ -247,6 +247,9 @@ int check_exec (struct lwp *, struct ex int exec_init (int); int exec_read_from (struct lwp *, struct vnode *, u_long off, void *, size_t); +int exec_read_locked (struct vnode *, u_long off, void *, size_t); +int exec_read (struct exec_package *, u_long off, + void *, size_t); int exec_setup_stack (struct lwp *, struct exec_package *); int coredump_write (void *, enum uio_seg, const void *, size_t);