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