The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f34fc6ba06a10e0f2a505ec0dd2f2fab2a79e53d

commit f34fc6ba06a10e0f2a505ec0dd2f2fab2a79e53d
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2021-10-29 01:42:59 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2021-10-31 01:05:14 +0000

    Extract proc_get_binpath() from sysctl_kern_proc_pathname()
    
    Reviewed by:    emaste, markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D32738
---
 sys/kern/kern_proc.c | 89 +++++++++++++++++++++++++++++++++-------------------
 sys/sys/proc.h       |  2 ++
 2 files changed, 58 insertions(+), 33 deletions(-)

diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index c4c01da1faea..2156c5c465ba 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -2226,41 +2226,34 @@ sysctl_kern_proc_auxv(SYSCTL_HANDLER_ARGS)
 }
 
 /*
- * This sysctl allows a process to retrieve the path of the executable for
- * itself or another process.
+ * Look up the canonical executable path running in the specified process.
+ * It tries to return the same hardlink name as was used for execve(2).
+ * This allows the programs that modify their behavior based on their progname,
+ * to operate correctly.
+ *
+ * Result is returned in retbuf, it must not be freed, similar to vn_fullpath()
+ *   calling conventions.
+ * binname is a pointer to temporary string buffer of length MAXPATHLEN,
+ *   allocated and freed by caller.
+ * freebuf should be freed by caller, from the M_TEMP malloc type.
  */
-static int
-sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS)
+int
+proc_get_binpath(struct proc *p, char *binname, char **retbuf,
+    char **freebuf)
 {
-       pid_t *pidp = (pid_t *)arg1;
-       unsigned int arglen = arg2;
-       struct proc *p;
-       struct vnode *vp, *dvp;
-       char *retbuf, *freebuf, *binname;
        struct nameidata nd;
+       struct vnode *vp, *dvp;
        size_t freepath_size;
        int error;
        bool do_fullpath;
 
-       if (arglen != 1)
-               return (EINVAL);
-       binname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
-       binname[0] = '\0';
-       if (*pidp == -1) {      /* -1 means this process */
-               p = req->td->td_proc;
-       } else {
-               error = pget(*pidp, PGET_CANSEE, &p);
-               if (error != 0) {
-                       free(binname, M_TEMP);
-                       return (error);
-               }
-       }
+       PROC_LOCK_ASSERT(p, MA_OWNED);
 
        vp = p->p_textvp;
        if (vp == NULL) {
-               if (*pidp != -1)
-                       PROC_UNLOCK(p);
-               free(binname, M_TEMP);
+               PROC_UNLOCK(p);
+               *retbuf = NULL;
+               *freebuf = NULL;
                return (0);
        }
        vref(vp);
@@ -2269,20 +2262,20 @@ sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS)
                vref(dvp);
        if (p->p_binname != NULL)
                strlcpy(binname, p->p_binname, MAXPATHLEN);
-       if (*pidp != -1)
-               PROC_UNLOCK(p);
+       PROC_UNLOCK(p);
+
        do_fullpath = true;
-       freebuf = NULL;
+       *freebuf = NULL;
        if (dvp != NULL && binname[0] != '\0') {
                freepath_size = MAXPATHLEN;
                if (vn_fullpath_hardlink(vp, dvp, binname, strlen(binname),
-                   &retbuf, &freebuf, &freepath_size) == 0) {
+                   retbuf, freebuf, &freepath_size) == 0) {
                        /*
                         * Recheck the looked up path.  The binary
                         * might have been renamed or replaced, in
                         * which case we should not report old name.
                         */
-                       NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, retbuf,
+                       NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, *retbuf,
                            req->td);
                        error = namei(&nd);
                        if (error == 0) {
@@ -2294,13 +2287,43 @@ sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS)
                }
        }
        if (do_fullpath) {
-               free(freebuf, M_TEMP);
-               freebuf = NULL;
-               error = vn_fullpath(vp, &retbuf, &freebuf);
+               free(*freebuf, M_TEMP);
+               *freebuf = NULL;
+               error = vn_fullpath(vp, retbuf, freebuf);
        }
        vrele(vp);
        if (dvp != NULL)
                vrele(dvp);
+       return (error);
+}
+
+/*
+ * This sysctl allows a process to retrieve the path of the executable for
+ * itself or another process.
+ */
+static int
+sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS)
+{
+       pid_t *pidp = (pid_t *)arg1;
+       unsigned int arglen = arg2;
+       struct proc *p;
+       char *retbuf, *freebuf, *binname;
+       int error;
+
+       if (arglen != 1)
+               return (EINVAL);
+       binname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+       binname[0] = '\0';
+       if (*pidp == -1) {      /* -1 means this process */
+               error = 0;
+               p = req->td->td_proc;
+               PROC_LOCK(p);
+       } else {
+               error = pget(*pidp, PGET_CANSEE, &p);
+       }
+
+       if (error == 0)
+               error = proc_get_binpath(p, binname, &retbuf, &freebuf);
        free(binname, M_TEMP);
        if (error != 0)
                return (error);
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 6bc9c82bb698..de19bfc9cc3b 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1128,6 +1128,8 @@ struct    pargs *pargs_alloc(int len);
 void   pargs_drop(struct pargs *pa);
 void   pargs_hold(struct pargs *pa);
 void   proc_add_orphan(struct proc *child, struct proc *parent);
+int    proc_get_binpath(struct proc *p, char *binname, char **fullpath,
+           char **freepath);
 int    proc_getargv(struct thread *td, struct proc *p, struct sbuf *sb);
 int    proc_getauxv(struct thread *td, struct proc *p, struct sbuf *sb);
 int    proc_getenvv(struct thread *td, struct proc *p, struct sbuf *sb);

Reply via email to