Store full executable path in p->p_path as discussed in tech-kern.
This means that the full executable path is always available. - exec_elf.c: use p->path to set AT_SUN_EXECNAME, and since this is always set, do so unconditionally. - kern_exec.c: simplify pathexec, use kmem_strfree where appropriate and set p->p_path - kern_exit.c: free p->p_path - kern_fork.c: set p->p_path for the child. - kern_proc.c: use p->p_path to return the executable pathname; the NULL check for p->p_path, should be a KASSERT? - exec.h: gc ep_path, it is not used anymore - param.h: bump version, 'struct proc' size change TODO: 1. reference count the path string, to save copy at fork and free just before exec? 2. canonicalize the pathname by changing namei() to LOCKPARENT vnode and then using getcwd() on the parent directory?
This commit is contained in:
parent
20ed2e94d2
commit
0011aa658c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exec_elf.c,v 1.92 2017/10/16 01:50:55 christos Exp $ */
|
||||
/* $NetBSD: exec_elf.c,v 1.93 2017/11/07 19:44:04 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1994, 2000, 2005, 2015 The NetBSD Foundation, Inc.
|
||||
|
@ -57,7 +57,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.92 2017/10/16 01:50:55 christos Exp $");
|
||||
__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.93 2017/11/07 19:44:04 christos Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_pax.h"
|
||||
|
@ -226,11 +226,9 @@ elf_copyargs(struct lwp *l, struct exec_package *pack,
|
|||
a->a_v = l->l_proc->p_stackbase;
|
||||
a++;
|
||||
|
||||
if (pack->ep_path) {
|
||||
execname = a;
|
||||
a->a_type = AT_SUN_EXECNAME;
|
||||
a++;
|
||||
}
|
||||
execname = a;
|
||||
a->a_type = AT_SUN_EXECNAME;
|
||||
a++;
|
||||
|
||||
exec_free_emul_arg(pack);
|
||||
}
|
||||
|
@ -243,15 +241,12 @@ elf_copyargs(struct lwp *l, struct exec_package *pack,
|
|||
|
||||
KASSERT(vlen <= sizeof(ai));
|
||||
|
||||
if (execname) {
|
||||
char *path = pack->ep_path;
|
||||
execname->a_v = (uintptr_t)(*stackp + vlen);
|
||||
len = strlen(path) + 1;
|
||||
if ((error = copyout(path, (*stackp + vlen), len)) != 0)
|
||||
return error;
|
||||
len = ALIGN(len);
|
||||
} else
|
||||
len = 0;
|
||||
char *path = l->l_proc->p_path;
|
||||
execname->a_v = (uintptr_t)(*stackp + vlen);
|
||||
len = strlen(path) + 1;
|
||||
if ((error = copyout(path, (*stackp + vlen), len)) != 0)
|
||||
return error;
|
||||
len = ALIGN(len);
|
||||
|
||||
if ((error = copyout(ai, *stackp, vlen)) != 0)
|
||||
return error;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_exec.c,v 1.449 2017/10/20 19:06:46 riastradh Exp $ */
|
||||
/* $NetBSD: kern_exec.c,v 1.450 2017/11/07 19:44:04 christos 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.449 2017/10/20 19:06:46 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.450 2017/11/07 19:44:04 christos Exp $");
|
||||
|
||||
#include "opt_exec.h"
|
||||
#include "opt_execfmt.h"
|
||||
|
@ -925,55 +925,15 @@ execve_free_data(struct execve_data *data)
|
|||
}
|
||||
|
||||
static void
|
||||
pathexec(struct exec_package *epp, struct lwp *l, const char *pathstring)
|
||||
pathexec(struct proc *p, const char *resolvedname)
|
||||
{
|
||||
const char *commandname;
|
||||
size_t commandlen;
|
||||
char *path;
|
||||
struct proc *p = l->l_proc;
|
||||
KASSERT(resolvedname[0] == '/');
|
||||
|
||||
/* set command name & other accounting info */
|
||||
commandname = strrchr(epp->ep_resolvedname, '/');
|
||||
if (commandname != NULL) {
|
||||
commandname++;
|
||||
} else {
|
||||
commandname = epp->ep_resolvedname;
|
||||
}
|
||||
commandlen = min(strlen(commandname), MAXCOMLEN);
|
||||
(void)memcpy(p->p_comm, commandname, commandlen);
|
||||
p->p_comm[commandlen] = '\0';
|
||||
strlcpy(p->p_comm, strrchr(resolvedname, '/') + 1, sizeof(p->p_comm));
|
||||
|
||||
|
||||
/*
|
||||
* If the path starts with /, we don't need to do any work.
|
||||
* This handles the majority of the cases.
|
||||
* In the future perhaps we could canonicalize it?
|
||||
*/
|
||||
path = PNBUF_GET();
|
||||
if (pathstring[0] == '/') {
|
||||
(void)strlcpy(path, pathstring, MAXPATHLEN);
|
||||
epp->ep_path = path;
|
||||
}
|
||||
#ifdef notyet
|
||||
/*
|
||||
* Although this works most of the time [since the entry was just
|
||||
* entered in the cache] we don't use it because it will fail for
|
||||
* entries that are not placed in the cache because their name is
|
||||
* longer than NCHNAMLEN and it is not the cleanest interface,
|
||||
* because there could be races. When the namei cache is re-written,
|
||||
* this can be changed to use the appropriate function.
|
||||
*/
|
||||
else if (!(error = vnode_to_path(path, MAXPATHLEN, p->p_textvp, l, p)))
|
||||
epp->ep_path = path;
|
||||
#endif
|
||||
else {
|
||||
#ifdef notyet
|
||||
printf("Cannot get path for pid %d [%s] (error %d)\n",
|
||||
(int)p->p_pid, p->p_comm, error);
|
||||
#endif
|
||||
PNBUF_PUT(path);
|
||||
epp->ep_path = NULL;
|
||||
}
|
||||
kmem_strfree(p->p_path);
|
||||
p->p_path = kmem_strdupsize(resolvedname, NULL, KM_SLEEP);
|
||||
}
|
||||
|
||||
/* XXX elsewhere */
|
||||
|
@ -1194,7 +1154,7 @@ execve_runproc(struct lwp *l, struct execve_data * restrict data,
|
|||
if (error != 0)
|
||||
goto exec_abort;
|
||||
|
||||
pathexec(epp, l, data->ed_pathstring);
|
||||
pathexec(p, epp->ep_resolvedname);
|
||||
|
||||
char * const newstack = STACK_GROW(vm->vm_minsaddr, epp->ep_ssize);
|
||||
|
||||
|
@ -1463,10 +1423,6 @@ copyoutargs(struct execve_data * restrict data, struct lwp *l,
|
|||
error = (*epp->ep_esch->es_copyargs)(l, epp,
|
||||
&data->ed_arginfo, &newargs, data->ed_argp);
|
||||
|
||||
if (epp->ep_path) {
|
||||
PNBUF_PUT(epp->ep_path);
|
||||
epp->ep_path = NULL;
|
||||
}
|
||||
if (error) {
|
||||
DPRINTF(("%s: copyargs failed %d\n", __func__, error));
|
||||
return error;
|
||||
|
@ -2258,7 +2214,7 @@ posix_spawn_fa_free(struct posix_spawn_file_actions *fa, size_t len)
|
|||
struct posix_spawn_file_actions_entry *fae = &fa->fae[i];
|
||||
if (fae->fae_action != FAE_OPEN)
|
||||
continue;
|
||||
kmem_free(fae->fae_path, strlen(fae->fae_path) + 1);
|
||||
kmem_strfree(fae->fae_path);
|
||||
}
|
||||
if (fa->len > 0)
|
||||
kmem_free(fa->fae, sizeof(*fa->fae) * fa->len);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_exit.c,v 1.269 2017/08/28 00:46:07 kamil Exp $ */
|
||||
/* $NetBSD: kern_exit.c,v 1.270 2017/11/07 19:44:04 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -67,7 +67,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.269 2017/08/28 00:46:07 kamil Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.270 2017/11/07 19:44:04 christos Exp $");
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_dtrace.h"
|
||||
|
@ -1250,6 +1250,7 @@ proc_free(struct proc *p, struct wrusage *wru)
|
|||
*/
|
||||
if (p->p_textvp)
|
||||
vrele(p->p_textvp);
|
||||
kmem_strfree(p->p_path);
|
||||
|
||||
mutex_destroy(&p->p_auxlock);
|
||||
mutex_obj_free(p->p_lock);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_fork.c,v 1.202 2017/04/21 15:10:34 christos Exp $ */
|
||||
/* $NetBSD: kern_fork.c,v 1.203 2017/11/07 19:44:04 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2001, 2004, 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -67,7 +67,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.202 2017/04/21 15:10:34 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.203 2017/11/07 19:44:04 christos Exp $");
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_dtrace.h"
|
||||
|
@ -346,6 +346,10 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize,
|
|||
p2->p_textvp = p1->p_textvp;
|
||||
if (p2->p_textvp)
|
||||
vref(p2->p_textvp);
|
||||
if (p1->p_path)
|
||||
p2->p_path = kmem_strdupsize(p1->p_path, NULL, KM_SLEEP);
|
||||
else
|
||||
p2->p_path = NULL;
|
||||
|
||||
if (flags & FORK_SHAREFILES)
|
||||
fd_share(p2);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_proc.c,v 1.207 2017/08/28 00:46:07 kamil Exp $ */
|
||||
/* $NetBSD: kern_proc.c,v 1.208 2017/11/07 19:44:04 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.207 2017/08/28 00:46:07 kamil Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.208 2017/11/07 19:44:04 christos Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_kstack.h"
|
||||
|
@ -2433,41 +2433,28 @@ proc_find_locked(struct lwp *l, struct proc **p, pid_t pid)
|
|||
static int
|
||||
fill_pathname(struct lwp *l, pid_t pid, void *oldp, size_t *oldlenp)
|
||||
{
|
||||
#ifndef _RUMPKERNEL
|
||||
int error;
|
||||
struct proc *p;
|
||||
char *path;
|
||||
size_t len;
|
||||
|
||||
if ((error = proc_find_locked(l, &p, pid)) != 0)
|
||||
return error;
|
||||
|
||||
if (p->p_textvp == NULL) {
|
||||
if (p->p_path == NULL) {
|
||||
if (pid != -1)
|
||||
mutex_exit(p->p_lock);
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
path = PNBUF_GET();
|
||||
error = vnode_to_path(path, MAXPATHLEN / 2, p->p_textvp, l, p);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
len = strlen(path) + 1;
|
||||
size_t len = strlen(p->p_path) + 1;
|
||||
if (oldp != NULL) {
|
||||
error = sysctl_copyout(l, path, oldp, *oldlenp);
|
||||
error = sysctl_copyout(l, p->p_path, oldp, *oldlenp);
|
||||
if (error == 0 && *oldlenp < len)
|
||||
error = ENOSPC;
|
||||
}
|
||||
*oldlenp = len;
|
||||
out:
|
||||
PNBUF_PUT(path);
|
||||
if (pid != -1)
|
||||
mutex_exit(p->p_lock);
|
||||
return error;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: exec.h,v 1.151 2016/08/06 15:13:14 maxv Exp $ */
|
||||
/* $NetBSD: exec.h,v 1.152 2017/11/07 19:44:05 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -215,7 +215,6 @@ struct exec_package {
|
|||
struct vnode *ep_emul_root; /* base of emulation filesystem */
|
||||
struct vnode *ep_interp; /* vnode of (elf) interpeter */
|
||||
uint32_t ep_pax_flags; /* pax flags */
|
||||
char *ep_path; /* absolute path of executable */
|
||||
void (*ep_emul_arg_free)(void *);
|
||||
/* free ep_emul_arg */
|
||||
uint32_t ep_osversion; /* OS version */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: param.h,v 1.549 2017/10/23 11:21:56 martin Exp $ */
|
||||
/* $NetBSD: param.h,v 1.550 2017/11/07 19:44:05 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
|
@ -67,7 +67,7 @@
|
|||
* 2.99.9 (299000900)
|
||||
*/
|
||||
|
||||
#define __NetBSD_Version__ 899000500 /* NetBSD 8.99.5 */
|
||||
#define __NetBSD_Version__ 899000600 /* NetBSD 8.99.6 */
|
||||
|
||||
#define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
|
||||
(m) * 1000000) + (p) * 100) <= __NetBSD_Version__)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: proc.h,v 1.342 2017/08/28 00:46:07 kamil Exp $ */
|
||||
/* $NetBSD: proc.h,v 1.343 2017/11/07 19:44:05 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -315,6 +315,7 @@ struct proc {
|
|||
lwpid_t p_lwp_created; /* :: lwp created */
|
||||
lwpid_t p_lwp_exited; /* :: lwp exited */
|
||||
u_int p_nsems; /* Count of semaphores */
|
||||
char *p_path; /* :: full pathname of executable */
|
||||
|
||||
/*
|
||||
* End area that is zeroed on creation
|
||||
|
|
Loading…
Reference in New Issue