Module Name: src Committed By: christos Date: Fri Sep 11 01:23:37 UTC 2015
Modified Files: src/sys/kern: kern_exec.c Log Message: On non absolute exec pathnames, prepend the working directory if possible so that we can provide in most situations the absolute pathname in the AUX vector so that $ORIGIN works. The following are implementation issues: 1. deep path execs still don't work (can't provide path to the AUX vector) 2. the returned path is not normalized (cosmetic) To generate a diff of this commit: cvs rdiff -u -r1.413 -r1.414 src/sys/kern/kern_exec.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_exec.c diff -u src/sys/kern/kern_exec.c:1.413 src/sys/kern/kern_exec.c:1.414 --- src/sys/kern/kern_exec.c:1.413 Fri Jul 31 03:37:17 2015 +++ src/sys/kern/kern_exec.c Thu Sep 10 21:23:37 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exec.c,v 1.413 2015/07/31 07:37:17 maxv Exp $ */ +/* $NetBSD: kern_exec.c,v 1.414 2015/09/11 01:23:37 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.413 2015/07/31 07:37:17 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.414 2015/09/11 01:23:37 christos Exp $"); #include "opt_exec.h" #include "opt_execfmt.h" @@ -79,6 +79,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_exec.c, #include <sys/namei.h> #include <sys/vnode.h> #include <sys/file.h> +#include <sys/filedesc.h> #include <sys/acct.h> #include <sys/atomic.h> #include <sys/exec.h> @@ -592,6 +593,51 @@ exec_autoload(void) #endif } +static struct pathbuf * +makepathbuf(struct lwp *l, const char *upath) +{ + char *path, *bp; + size_t len; + int error; + struct cwdinfo *cwdi; + + path = PNBUF_GET(); + error = copyinstr(upath, path, MAXPATHLEN, &len); + if (error) { + PNBUF_PUT(path); + DPRINTF(("%s: copyin path @%p %d\n", __func__, upath, error)); + return NULL; + } + + if (path[0] == '/') + goto out; + + len++; + if (len + 1 >= MAXPATHLEN) + goto out; + bp = path + MAXPATHLEN - len; + memmove(bp, path, len); + *(--bp) = '/'; + + cwdi = l->l_proc->p_cwdi; + rw_enter(&cwdi->cwdi_lock, RW_READER); + error = getcwd_common(cwdi->cwdi_cdir, NULL, &bp, path, MAXPATHLEN / 2, + GETCWD_CHECK_ACCESS, l); + rw_exit(&cwdi->cwdi_lock); + + if (error) { + DPRINTF(("%s: getcwd_common path %s %d\n", __func__, path, + error)); + goto out; + } + len = path + MAXPATHLEN - bp; + + memmove(path, bp, len); + path[len] = '\0'; +out: + return pathbuf_assimilate(path); +} + static int execve_loadvm(struct lwp *l, const char *path, char * const *args, char * const *envs, execve_fetch_element_t fetch_element, @@ -651,12 +697,9 @@ execve_loadvm(struct lwp *l, const char * functions call check_exec() recursively - for example, * see exec_script_makecmds(). */ - error = pathbuf_copyin(path, &data->ed_pathbuf); - if (error) { - DPRINTF(("%s: pathbuf_copyin path @%p %d\n", __func__, - path, error)); + data->ed_pathbuf = makepathbuf(l, path); + if (data->ed_pathbuf == NULL) goto clrflg; - } data->ed_pathstring = pathbuf_stringcopy_get(data->ed_pathbuf); data->ed_resolvedpathbuf = PNBUF_GET(); @@ -880,7 +923,6 @@ pathexec(struct exec_package *epp, struc (void)memcpy(p->p_comm, commandname, commandlen); p->p_comm[commandlen] = '\0'; - path = PNBUF_GET(); /* * If the path starts with /, we don't need to do any work. @@ -888,30 +930,11 @@ pathexec(struct exec_package *epp, struc * In the future perhaps we could canonicalize it? */ 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))) + path = PNBUF_GET(); + (void)strlcpy(path, pathstring, MAXPATHLEN); 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 + } else epp->ep_path = NULL; - PNBUF_PUT(path); - } } /* XXX elsewhere */