Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern - Add support for fexecve



details:   https://anonhg.NetBSD.org/src/rev/1a2ac0d4d10b
branches:  trunk
changeset: 454391:1a2ac0d4d10b
user:      christos <christos%NetBSD.org@localhost>
date:      Sun Sep 15 20:23:50 2019 +0000

description:
- Add support for fexecve
        - get the vnode from the fd passed instead of calling namei() on the
          path
        - try to reverse resolve the vnode to extract the pathname
        - deal with not having a resolved path available
- rename variable that was not a pathbuf

diffstat:

 sys/kern/kern_exec.c |  146 +++++++++++++++++++++++++++++++++++---------------
 1 files changed, 103 insertions(+), 43 deletions(-)

diffs (270 lines):

diff -r 59d47fafc891 -r 1a2ac0d4d10b sys/kern/kern_exec.c
--- a/sys/kern/kern_exec.c      Sun Sep 15 20:21:12 2019 +0000
+++ b/sys/kern/kern_exec.c      Sun Sep 15 20:23:50 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_exec.c,v 1.479 2019/09/07 15:34:44 christos Exp $ */
+/*     $NetBSD: kern_exec.c,v 1.480 2019/09/15 20:23:50 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.479 2019/09/07 15:34:44 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.480 2019/09/15 20:23:50 christos Exp $");
 
 #include "opt_exec.h"
 #include "opt_execfmt.h"
@@ -257,7 +257,7 @@
        struct ps_strings       ed_arginfo;
        char                    *ed_argp;
        const char              *ed_pathstring;
-       char                    *ed_resolvedpathbuf;
+       char                    *ed_resolvedname;
        size_t                  ed_ps_strings_sz;
        int                     ed_szsigcode;
        size_t                  ed_argslen;
@@ -309,9 +309,32 @@
 {              
        pathbuf_stringcopy_put(data->ed_pathbuf, data->ed_pathstring);
        pathbuf_destroy(data->ed_pathbuf);
-       PNBUF_PUT(data->ed_resolvedpathbuf);
+       if (data->ed_resolvedname)
+               PNBUF_PUT(data->ed_resolvedname);
 }
 
+static void
+exec_resolvename(struct lwp *l, struct exec_package *epp, struct vnode *vp,
+    char **rpath)
+{
+       int error;
+       char *p;
+
+       KASSERT(rpath != NULL);
+
+       *rpath = PNBUF_GET();
+       error = vnode_to_path(*rpath, MAXPATHLEN, vp, l, l->l_proc);
+       if (error) {
+               PNBUF_PUT(*rpath);
+               *rpath = NULL;
+               return;
+       }
+       epp->ep_resolvedname = *rpath;
+       if ((p = strrchr(*rpath, '/')) != NULL)
+               epp->ep_kname = p + 1;
+}
+
+
 /*
  * check exec:
  * given an "executable" described in the exec package's namei info,
@@ -339,26 +362,40 @@
  */
 int
 /*ARGSUSED*/
-check_exec(struct lwp *l, struct exec_package *epp, struct pathbuf *pb)
+check_exec(struct lwp *l, struct exec_package *epp, struct pathbuf *pb,
+    char **rpath)
 {
        int             error, i;
        struct vnode    *vp;
-       struct nameidata nd;
        size_t          resid;
 
-       // grab the absolute pathbuf here before namei() trashes it.
-       pathbuf_copystring(pb, epp->ep_resolvedname, PATH_MAX);
-       NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
-
-       /* first get the vnode */
-       if ((error = namei(&nd)) != 0)
-               return error;
-       epp->ep_vp = vp = nd.ni_vp;
-
+       if (epp->ep_resolvedname) {
+               struct nameidata nd;
+
+               // grab the absolute pathbuf here before namei() trashes it.
+               pathbuf_copystring(pb, epp->ep_resolvedname, PATH_MAX);
+               NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
+
+               /* first get the vnode */
+               if ((error = namei(&nd)) != 0)
+                       return error;
+
+               epp->ep_vp = vp = nd.ni_vp;
 #ifdef DIAGNOSTIC
-       /* paranoia (take this out once namei stuff stabilizes) */
-       memset(nd.ni_pnbuf, '~', PATH_MAX);
+               /* paranoia (take this out once namei stuff stabilizes) */
+               memset(nd.ni_pnbuf, '~', PATH_MAX);
 #endif
+       } else {
+               struct file *fp;
+
+               if ((error = fd_getvnode(epp->ep_xfd, &fp)) != 0)
+                       return error;
+               epp->ep_vp = vp = fp->f_vnode;
+               vref(vp);
+               fd_putfile(epp->ep_xfd);
+               exec_resolvename(l, epp, vp, rpath);
+               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+       }
 
        /* check access and type */
        if (vp->v_type != VREG) {
@@ -388,7 +425,8 @@
        VOP_UNLOCK(vp);
 
 #if NVERIEXEC > 0
-       error = veriexec_verify(l, vp, epp->ep_resolvedname,
+       error = veriexec_verify(l, vp,
+           epp->ep_resolvedname ? epp->ep_resolvedname : epp->ep_kname,
            epp->ep_flags & EXEC_INDIR ? VERIEXEC_INDIRECT : VERIEXEC_DIRECT,
            NULL);
        if (error)
@@ -545,7 +583,7 @@
                syscallarg(char * const *)      envp;
        } */
 
-       return execve1(l, SCARG(uap, path), SCARG(uap, argp),
+       return execve1(l, SCARG(uap, path), -1, SCARG(uap, argp),
            SCARG(uap, envp), execve_fetch_element);
 }
 
@@ -559,7 +597,8 @@
                syscallarg(char * const *)      envp;
        } */
 
-       return ENOSYS;
+       return execve1(l, NULL, SCARG(uap, fd), SCARG(uap, argp),
+           SCARG(uap, envp), execve_fetch_element);
 }
 
 /*
@@ -680,7 +719,7 @@
 }
 
 static int
-execve_loadvm(struct lwp *l, const char *path, char * const *args,
+execve_loadvm(struct lwp *l, const char *path, int fd, char * const *args,
        char * const *envs, execve_fetch_element_t fetch_element,
        struct execve_data * restrict data)
 {
@@ -689,7 +728,6 @@
        struct proc             *p;
        char                    *dp;
        u_int                   modgen;
-       size_t                  offs;
 
        KASSERT(data != NULL);
 
@@ -732,24 +770,36 @@
         */
        rw_enter(&p->p_reflock, RW_WRITER);
 
-       /*
-        * Init the namei data to point the file user's program name.
-        * This is done here rather than in check_exec(), so that it's
-        * possible to override this settings if any of makecmd/probe
-        * functions call check_exec() recursively - for example,
-        * see exec_script_makecmds().
-        */
-       if ((error = exec_makepathbuf(l, path, UIO_USERSPACE,
-           &data->ed_pathbuf, &offs)) != 0)
-               goto clrflg;
-       data->ed_pathstring = pathbuf_stringcopy_get(data->ed_pathbuf);
-       data->ed_resolvedpathbuf = PNBUF_GET();
+       if (path == NULL) {
+               data->ed_pathbuf = pathbuf_assimilate(strcpy(PNBUF_GET(), "/"));
+               data->ed_pathstring = pathbuf_stringcopy_get(data->ed_pathbuf);
+               epp->ep_kname = "*fexecve*";
+               data->ed_resolvedname = NULL;
+               epp->ep_resolvedname = NULL;
+               epp->ep_xfd = fd;
+       } else {
+               size_t  offs;
+               /*
+                * Init the namei data to point the file user's program name.
+                * This is done here rather than in check_exec(), so that it's
+                * possible to override this settings if any of makecmd/probe
+                * functions call check_exec() recursively - for example,
+                * see exec_script_makecmds().
+                */
+               if ((error = exec_makepathbuf(l, path, UIO_USERSPACE,
+                   &data->ed_pathbuf, &offs)) != 0)
+                       goto clrflg;
+               data->ed_pathstring = pathbuf_stringcopy_get(data->ed_pathbuf);
+               epp->ep_kname = data->ed_pathstring + offs;
+               data->ed_resolvedname = PNBUF_GET();
+               epp->ep_resolvedname = data->ed_resolvedname;
+               epp->ep_xfd = -1;
+       }
+
 
        /*
         * initialize the fields of the exec package.
         */
-       epp->ep_kname = data->ed_pathstring + offs;
-       epp->ep_resolvedname = data->ed_resolvedpathbuf;
        epp->ep_hdr = kmem_alloc(exec_maxhdrsz, KM_SLEEP);
        epp->ep_hdrlen = exec_maxhdrsz;
        epp->ep_hdrvalid = 0;
@@ -768,7 +818,8 @@
        rw_enter(&exec_lock, RW_READER);
 
        /* see if we can run it. */
-       if ((error = check_exec(l, epp, data->ed_pathbuf)) != 0) {
+       if ((error = check_exec(l, epp, data->ed_pathbuf,
+           &data->ed_resolvedname)) != 0) {
                if (error != ENOENT && error != EACCES && error != ENOEXEC) {
                        DPRINTF(("%s: check exec failed for %s, error %d\n",
                            __func__, epp->ep_kname, error));
@@ -942,10 +993,19 @@
 static void
 pathexec(struct proc *p, const char *resolvedname)
 {
-       KASSERT(resolvedname[0] == '/');
-
        /* set command name & other accounting info */
-       strlcpy(p->p_comm, strrchr(resolvedname, '/') + 1, sizeof(p->p_comm));
+       const char *cmdname;
+
+       if (resolvedname == NULL) {
+               cmdname = "*fexecve*";
+               resolvedname = "/";
+       } else {
+               cmdname = strrchr(resolvedname, '/') + 1;
+       }
+       KASSERTMSG(resolvedname[0] == '/', "bad resolvedname `%s'",
+           resolvedname);
+
+       strlcpy(p->p_comm, cmdname, sizeof(p->p_comm));
 
        kmem_strfree(p->p_path);
        p->p_path = kmem_strdupsize(resolvedname, NULL, KM_SLEEP);
@@ -1346,13 +1406,13 @@
 }
 
 int
-execve1(struct lwp *l, const char *path, char * const *args,
+execve1(struct lwp *l, const char *path, int fd, char * const *args,
     char * const *envs, execve_fetch_element_t fetch_element)
 {
        struct execve_data data;
        int error;
 
-       error = execve_loadvm(l, path, args, envs, fetch_element, &data);
+       error = execve_loadvm(l, path, fd, args, envs, fetch_element, &data);
        if (error)
                return error;
        error = execve_runproc(l, &data, false, false);
@@ -2376,7 +2436,7 @@
         * Do the first part of the exec now, collect state
         * in spawn_data.
         */
-       error = execve_loadvm(l1, path, argv,
+       error = execve_loadvm(l1, path, -1, argv,
            envp, fetch, &spawn_data->sed_exec);
        if (error == EJUSTRETURN)
                error = 0;



Home | Main Index | Thread Index | Old Index