From 54f6c52ba94bf9f3e943a39d536c8d69bdabee1b Mon Sep 17 00:00:00 2001 From: dholland Date: Sun, 2 May 2010 05:30:20 +0000 Subject: [PATCH] Remove the nameidata from struct exec_package. It was used only for two things: passing an argument to check_exec, which is better done explicitly, and handing back the resolved pathname generated by namei, which we can make an explicit slot for in struct exec_package instead. While here, perform some related tidyup, and store the kernel-side copy of the path to the executable as well as the pointer into userspace. (But the latter should probably be removed in the future.) --- sys/compat/osf1/osf1_exec_ecoff.c | 16 ++---- sys/compat/svr4_32/svr4_32_exec_elf32.c | 14 +++-- sys/kern/exec_script.c | 41 ++++++--------- sys/kern/kern_exec.c | 68 +++++++++++++++---------- sys/sys/exec.h | 8 +-- 5 files changed, 73 insertions(+), 74 deletions(-) diff --git a/sys/compat/osf1/osf1_exec_ecoff.c b/sys/compat/osf1/osf1_exec_ecoff.c index 613d87cd9817..59f4147c13eb 100644 --- a/sys/compat/osf1/osf1_exec_ecoff.c +++ b/sys/compat/osf1/osf1_exec_ecoff.c @@ -1,4 +1,4 @@ -/* $NetBSD: osf1_exec_ecoff.c,v 1.21 2008/11/15 00:49:53 njoly Exp $ */ +/* $NetBSD: osf1_exec_ecoff.c,v 1.22 2010/05/02 05:30:20 dholland Exp $ */ /* * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved. @@ -31,7 +31,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: osf1_exec_ecoff.c,v 1.21 2008/11/15 00:49:53 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: osf1_exec_ecoff.c,v 1.22 2010/05/02 05:30:20 dholland Exp $"); #include #include @@ -73,16 +73,8 @@ osf1_exec_ecoff_probe(struct lwp *l, struct exec_package *epp) epp->ep_emul_arg = emul_arg; emul_arg->flags = 0; - if (epp->ep_ndp->ni_segflg == UIO_SYSSPACE) - error = copystr(epp->ep_ndp->ni_dirp, emul_arg->exec_name, - MAXPATHLEN + 1, NULL); - else - error = copyinstr(epp->ep_ndp->ni_dirp, emul_arg->exec_name, - MAXPATHLEN + 1, NULL); -#ifdef DIAGNOSTIC - if (error != 0) - panic("osf1_exec_ecoff_probe: copyinstr failed"); -#endif + /* this cannot overflow because both are size PATH_MAX */ + strcpy(emul_arg->exec_name, epp->ep_kname); /* do any special object file handling */ switch (execp->f.f_flags & ECOFF_FLAG_OBJECT_TYPE_MASK) { diff --git a/sys/compat/svr4_32/svr4_32_exec_elf32.c b/sys/compat/svr4_32/svr4_32_exec_elf32.c index 8765907e6ea5..b1b2a7f4d2e9 100644 --- a/sys/compat/svr4_32/svr4_32_exec_elf32.c +++ b/sys/compat/svr4_32/svr4_32_exec_elf32.c @@ -1,4 +1,4 @@ -/* $NetBSD: svr4_32_exec_elf32.c,v 1.20 2008/04/28 20:23:46 martin Exp $ */ +/* $NetBSD: svr4_32_exec_elf32.c,v 1.21 2010/05/02 05:30:20 dholland Exp $ */ /*- * Copyright (c) 1994 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: svr4_32_exec_elf32.c,v 1.20 2008/04/28 20:23:46 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: svr4_32_exec_elf32.c,v 1.21 2010/05/02 05:30:20 dholland Exp $"); #define ELFSIZE 32 /* XXX should die */ @@ -93,11 +93,9 @@ svr4_32_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *ar platform = a; /* Patch this later. */ a++; - if (pack->ep_ndp->ni_cnd.cn_flags & HASBUF) { - a->a_type = AT_SUN_EXECNAME; - exec = a; /* Patch this later. */ - a++; - } + a->a_type = AT_SUN_EXECNAME; + exec = a; /* Patch this later. */ + a++; a->a_type = AT_PHDR; a->a_v = ap->arg_phaddr; @@ -173,7 +171,7 @@ svr4_32_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *ar len += strlen(machine_model) + 1; if (exec) { - path = pack->ep_ndp->ni_cnd.cn_pnbuf; + path = pack->ep_resolvedname; /* Copy out the file we're executing. */ exec->a_v = (u_long)(*stackp) + len; diff --git a/sys/kern/exec_script.c b/sys/kern/exec_script.c index bd70de67bdbf..65a73f64b6f8 100644 --- a/sys/kern/exec_script.c +++ b/sys/kern/exec_script.c @@ -1,4 +1,4 @@ -/* $NetBSD: exec_script.c,v 1.63 2008/11/19 18:36:06 ad Exp $ */ +/* $NetBSD: exec_script.c,v 1.64 2010/05/02 05:30:20 dholland Exp $ */ /* * Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou @@ -31,7 +31,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: exec_script.c,v 1.63 2008/11/19 18:36:06 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: exec_script.c,v 1.64 2010/05/02 05:30:20 dholland Exp $"); #if defined(SETUIDSCRIPTS) && !defined(FDSCRIPTS) #define FDSCRIPTS /* Need this for safe set-id scripts. */ @@ -115,7 +115,7 @@ exec_script_makecmds(struct lwp *l, struct exec_package *epp) { int error, hdrlinelen, shellnamelen, shellarglen; char *hdrstr = epp->ep_hdr; - char *cp, *shellname, *shellarg, *oldpnbuf; + char *cp, *shellname, *shellarg; size_t shellargp_len; struct exec_fakearg *shellargp; struct exec_fakearg *tmpsap; @@ -247,12 +247,7 @@ check_shell: } #endif - /* set up the parameters for the recursive check_exec() call */ - epp->ep_ndp->ni_dirp = shellname; - epp->ep_ndp->ni_segflg = UIO_SYSSPACE; - epp->ep_flags |= EXEC_INDIR; - - /* and set up the fake args list, for later */ + /* set up the fake args list */ shellargp_len = 4 * sizeof(*shellargp); shellargp = kmem_alloc(shellargp_len, KM_SLEEP); tmpsap = shellargp; @@ -272,12 +267,12 @@ check_shell: if ((epp->ep_flags & EXEC_HASFD) == 0) { #endif /* normally can't fail, but check for it if diagnostic */ - error = copyinstr(epp->ep_name, tmpsap->fa_arg, MAXPATHLEN, + error = copystr(epp->ep_kname, tmpsap->fa_arg, MAXPATHLEN, (size_t *)0); tmpsap++; #ifdef DIAGNOSTIC if (error != 0) - panic("exec_script: copyinstr couldn't fail"); + panic("exec_script: copystr couldn't fail"); #endif #ifdef FDSCRIPTS } else { @@ -287,22 +282,25 @@ check_shell: #endif tmpsap->fa_arg = NULL; + /* Save the old vnode so we can clean it up later. */ + scriptvp = epp->ep_vp; + epp->ep_vp = NULL; + + /* Note that we're trying recursively. */ + epp->ep_flags |= EXEC_INDIR; + /* * mark the header we have as invalid; check_exec will read * the header from the new executable */ epp->ep_hdrvalid = 0; - /* - * remember the old vp and pnbuf for later, so we can restore - * them if check_exec() fails. - */ - scriptvp = epp->ep_vp; - oldpnbuf = epp->ep_ndp->ni_cnd.cn_pnbuf; + /* try loading the interpreter */ + error = check_exec(l, epp, shellname); - error = check_exec(l, epp); /* note that we've clobbered the header */ epp->ep_flags |= EXEC_DESTR; + if (error == 0) { /* * It succeeded. Unlock the script and @@ -316,9 +314,6 @@ check_shell: vput(scriptvp); } - /* free the old pathname buffer */ - PNBUF_PUT(oldpnbuf); - epp->ep_flags |= (EXEC_HASARGL | EXEC_SKIPARG); epp->ep_fa = shellargp; epp->ep_fa_len = shellargp_len; @@ -338,8 +333,6 @@ check_shell: return (0); } - /* XXX oldpnbuf not set for "goto fail" path */ - epp->ep_ndp->ni_cnd.cn_pnbuf = oldpnbuf; #ifdef FDSCRIPTS fail: #endif @@ -354,8 +347,6 @@ fail: vput(scriptvp); } - PNBUF_PUT(epp->ep_ndp->ni_cnd.cn_pnbuf); - /* free the fake arg list, because we're not returning it */ if ((tmpsap = shellargp) != NULL) { while (tmpsap->fa_arg != NULL) { diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 2248ee5bf296..4b0760c2a4b0 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exec.c,v 1.294 2010/03/01 21:10:15 darran Exp $ */ +/* $NetBSD: kern_exec.c,v 1.295 2010/05/02 05:30:20 dholland Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -59,7 +59,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.294 2010/03/01 21:10:15 darran Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.295 2010/05/02 05:30:20 dholland Exp $"); #include "opt_ktrace.h" #include "opt_modular.h" @@ -278,20 +278,29 @@ static struct pool_allocator exec_palloc = { */ int /*ARGSUSED*/ -check_exec(struct lwp *l, struct exec_package *epp) +check_exec(struct lwp *l, struct exec_package *epp, const char *kpath) { int error, i; struct vnode *vp; - struct nameidata *ndp; + struct nameidata nd; size_t resid; - ndp = epp->ep_ndp; - ndp->ni_cnd.cn_nameiop = LOOKUP; - ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | SAVENAME | TRYEMULROOT; + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME | TRYEMULROOT, + UIO_SYSSPACE, kpath); + /* first get the vnode */ - if ((error = namei(ndp)) != 0) + if ((error = namei(&nd)) != 0) return error; - epp->ep_vp = vp = ndp->ni_vp; + epp->ep_vp = vp = nd.ni_vp; + /* this cannot overflow as both are size PATH_MAX */ + strcpy(epp->ep_resolvedname, nd.ni_cnd.cn_pnbuf); + + /* dump this right away */ +#if 1 /*def DIAGNOSTIC*/ + /* paranoia (XXX: take this out once things are working) */ + memset(nd.ni_cnd.cn_pnbuf, '~', PATH_MAX); +#endif + PNBUF_PUT(nd.ni_cnd.cn_pnbuf); /* check access and type */ if (vp->v_type != VREG) { @@ -321,7 +330,7 @@ check_exec(struct lwp *l, struct exec_package *epp) VOP_UNLOCK(vp, 0); #if NVERIEXEC > 0 - error = veriexec_verify(l, vp, ndp->ni_cnd.cn_pnbuf, + error = veriexec_verify(l, vp, epp->ep_resolvedname, epp->ep_flags & EXEC_INDIR ? VERIEXEC_INDIRECT : VERIEXEC_DIRECT, NULL); if (error) @@ -329,7 +338,7 @@ check_exec(struct lwp *l, struct exec_package *epp) #endif /* NVERIEXEC > 0 */ #ifdef PAX_SEGVGUARD - error = pax_segvguard(l, vp, ndp->ni_cnd.cn_pnbuf, false); + error = pax_segvguard(l, vp, epp->ep_resolvedname, false); if (error) goto bad2; #endif /* PAX_SEGVGUARD */ @@ -411,7 +420,6 @@ bad2: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); VOP_CLOSE(vp, FREAD, l->l_cred); vput(vp); - PNBUF_PUT(ndp->ni_cnd.cn_pnbuf); return error; bad1: @@ -420,7 +428,6 @@ bad1: * (which we don't yet have open). */ vput(vp); /* was still locked */ - PNBUF_PUT(ndp->ni_cnd.cn_pnbuf); return error; } @@ -513,7 +520,6 @@ execve1(struct lwp *l, const char *path, char * const *args, { int error; struct exec_package pack; - struct nameidata nid; struct vattr attr; struct proc *p; char *argp; @@ -531,7 +537,8 @@ execve1(struct lwp *l, const char *path, char * const *args, ksiginfo_t ksi; ksiginfoq_t kq; char *pathbuf; - size_t pathbuflen; + char *resolvedpathbuf; + const char *commandname; u_int modgen; p = l->l_proc; @@ -584,22 +591,25 @@ execve1(struct lwp *l, const char *path, char * const *args, * see exec_script_makecmds(). */ pathbuf = PNBUF_GET(); - error = copyinstr(path, pathbuf, MAXPATHLEN, &pathbuflen); + error = copyinstr(path, pathbuf, MAXPATHLEN, NULL); if (error) { DPRINTF(("execve: copyinstr path %d", error)); goto clrflg; } - - NDINIT(&nid, LOOKUP, NOFOLLOW | TRYEMULROOT, UIO_SYSSPACE, pathbuf); + resolvedpathbuf = PNBUF_GET(); +#ifdef DIAGNOSTIC + strcpy(resolvedpathbuf, "/wrong"); +#endif /* * initialize the fields of the exec package. */ pack.ep_name = path; + pack.ep_kname = pathbuf; + pack.ep_resolvedname = resolvedpathbuf; pack.ep_hdr = kmem_alloc(exec_maxhdrsz, KM_SLEEP); pack.ep_hdrlen = exec_maxhdrsz; pack.ep_hdrvalid = 0; - pack.ep_ndp = &nid; pack.ep_emul_arg = NULL; pack.ep_vmcmds.evs_cnt = 0; pack.ep_vmcmds.evs_used = 0; @@ -613,7 +623,7 @@ execve1(struct lwp *l, const char *path, char * const *args, rw_enter(&exec_lock, RW_READER); /* see if we can run it. */ - if ((error = check_exec(l, &pack)) != 0) { + if ((error = check_exec(l, &pack, pathbuf)) != 0) { if (error != ENOENT) { DPRINTF(("execve: check exec failed %d\n", error)); } @@ -853,8 +863,14 @@ execve1(struct lwp *l, const char *path, char * const *args, arginfo.ps_nenvstr = envc; /* set command name & other accounting info */ - i = min(nid.ni_cnd.cn_namelen, MAXCOMLEN); - (void)memcpy(p->p_comm, nid.ni_cnd.cn_nameptr, i); + commandname = strrchr(pack.ep_resolvedname, '/'); + if (commandname != NULL) { + commandname++; + } else { + commandname = pack.ep_resolvedname; + } + i = min(strlen(commandname), MAXCOMLEN); + (void)memcpy(p->p_comm, commandname, i); p->p_comm[i] = '\0'; dp = PNBUF_GET(); @@ -1075,8 +1091,6 @@ execve1(struct lwp *l, const char *path, char * const *args, pool_put(&exec_pool, argp); - PNBUF_PUT(nid.ni_cnd.cn_pnbuf); - /* notify others that we exec'd */ KNOTE(&p->p_klist, NOTE_EXEC); @@ -1163,6 +1177,7 @@ execve1(struct lwp *l, const char *path, char * const *args, } PNBUF_PUT(pathbuf); + PNBUF_PUT(resolvedpathbuf); return (EJUSTRETURN); bad: @@ -1177,7 +1192,6 @@ execve1(struct lwp *l, const char *path, char * const *args, vn_lock(pack.ep_vp, LK_EXCLUSIVE | LK_RETRY); VOP_CLOSE(pack.ep_vp, FREAD, l->l_cred); vput(pack.ep_vp); - PNBUF_PUT(nid.ni_cnd.cn_pnbuf); pool_put(&exec_pool, argp); freehdr: @@ -1189,6 +1203,8 @@ execve1(struct lwp *l, const char *path, char * const *args, rw_exit(&exec_lock); + PNBUF_PUT(resolvedpathbuf); + clrflg: lwp_lock(l); l->l_flag |= oldlwpflags; @@ -1208,6 +1224,7 @@ execve1(struct lwp *l, const char *path, char * const *args, exec_abort: SDT_PROBE(proc,,,exec_failure, error, 0, 0, 0, 0); PNBUF_PUT(pathbuf); + PNBUF_PUT(resolvedpathbuf); rw_exit(&p->p_reflock); rw_exit(&exec_lock); @@ -1220,7 +1237,6 @@ execve1(struct lwp *l, const char *path, char * const *args, VM_MAXUSER_ADDRESS - VM_MIN_ADDRESS); if (pack.ep_emul_arg) free(pack.ep_emul_arg, M_TEMP); - PNBUF_PUT(nid.ni_cnd.cn_pnbuf); pool_put(&exec_pool, argp); kmem_free(pack.ep_hdr, pack.ep_hdrlen); if (pack.ep_emul_root != NULL) diff --git a/sys/sys/exec.h b/sys/sys/exec.h index bd0df7f3f463..51ea6e4625a1 100644 --- a/sys/sys/exec.h +++ b/sys/sys/exec.h @@ -1,4 +1,4 @@ -/* $NetBSD: exec.h,v 1.129 2009/12/14 00:48:35 matt Exp $ */ +/* $NetBSD: exec.h,v 1.130 2010/05/02 05:30:20 dholland Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -171,10 +171,11 @@ struct exec_vmcmd_set { struct exec_package { const char *ep_name; /* file's name */ + const char *ep_kname; /* kernel-side copy of file's name */ + char *ep_resolvedname; /* fully resolved path from namei */ void *ep_hdr; /* file's exec header */ u_int ep_hdrlen; /* length of ep_hdr */ u_int ep_hdrvalid; /* bytes of ep_hdr that are valid */ - struct nameidata *ep_ndp; /* namei data pointer for lookups */ struct exec_vmcmd_set ep_vmcmds; /* vmcmds used to build vmspace */ struct vnode *ep_vp; /* executable's vnode */ struct vattr *ep_vap; /* executable's attributes */ @@ -243,7 +244,8 @@ int copyargs (struct lwp *, struct exec_package *, void setregs (struct lwp *, struct exec_package *, vaddr_t); int check_veriexec (struct lwp *, struct vnode *, struct exec_package *, int); -int check_exec (struct lwp *, struct exec_package *); +int check_exec (struct lwp *, struct exec_package *, + const char *kpath); int exec_init (int); int exec_read_from (struct lwp *, struct vnode *, u_long off, void *, size_t);