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:
christos 2017-11-07 19:44:04 +00:00
parent 20ed2e94d2
commit 0011aa658c
8 changed files with 39 additions and 96 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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 */

View File

@ -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__)

View File

@ -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