Index: kern_exec.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_exec.c,v retrieving revision 1.413 diff -u -u -r1.413 kern_exec.c --- kern_exec.c 31 Jul 2015 07:37:17 -0000 1.413 +++ kern_exec.c 11 Sep 2015 00:03:27 -0000 @@ -79,6 +79,7 @@ #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 @@ #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; + memcpy(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; + + memcpy(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 @@ * 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 @@ (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 @@ * In the future perhaps we could canonicalize it? */ if (pathstring[0] == '/') { - (void)strlcpy(path, pathstring, - MAXPATHLEN); + path = PNBUF_GET(); + (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 + } else epp->ep_path = NULL; - PNBUF_PUT(path); - } } /* XXX elsewhere */