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.)
This commit is contained in:
parent
ecc4179d07
commit
54f6c52ba9
|
@ -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 <sys/cdefs.h>
|
||||
__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 <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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;
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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) {
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue