The branch main has been updated by kib:

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

commit ee92c8a842d61ffda8d111e1b0e398085c5bfb3a
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2021-10-23 19:01:37 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2021-10-28 17:50:02 +0000

    sysctl kern.proc.procname: report right hardlink name
    
    PR:     248184
    Reviewed by:    markj
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D32611
---
 sys/kern/kern_proc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 5 deletions(-)

diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 2649d1d3a58f..c4c01da1faea 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/elf.h>
 #include <sys/eventhandler.h>
 #include <sys/exec.h>
+#include <sys/fcntl.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/limits.h>
@@ -54,6 +55,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/mman.h>
 #include <sys/mount.h>
 #include <sys/mutex.h>
+#include <sys/namei.h>
 #include <sys/proc.h>
 #include <sys/ptrace.h>
 #include <sys/refcount.h>
@@ -2233,32 +2235,74 @@ sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS)
        pid_t *pidp = (pid_t *)arg1;
        unsigned int arglen = arg2;
        struct proc *p;
-       struct vnode *vp;
-       char *retbuf, *freebuf;
+       struct vnode *vp, *dvp;
+       char *retbuf, *freebuf, *binname;
+       struct nameidata nd;
+       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)
+               if (error != 0) {
+                       free(binname, M_TEMP);
                        return (error);
+               }
        }
 
        vp = p->p_textvp;
        if (vp == NULL) {
                if (*pidp != -1)
                        PROC_UNLOCK(p);
+               free(binname, M_TEMP);
                return (0);
        }
        vref(vp);
+       dvp = p->p_textdvp;
+       if (dvp != NULL)
+               vref(dvp);
+       if (p->p_binname != NULL)
+               strlcpy(binname, p->p_binname, MAXPATHLEN);
        if (*pidp != -1)
                PROC_UNLOCK(p);
-       error = vn_fullpath(vp, &retbuf, &freebuf);
+       do_fullpath = true;
+       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) {
+                       /*
+                        * 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,
+                           req->td);
+                       error = namei(&nd);
+                       if (error == 0) {
+                               if (nd.ni_vp == vp)
+                                       do_fullpath = false;
+                               vrele(nd.ni_vp);
+                               NDFREE(&nd, NDF_ONLY_PNBUF);
+                       }
+               }
+       }
+       if (do_fullpath) {
+               free(freebuf, M_TEMP);
+               freebuf = NULL;
+               error = vn_fullpath(vp, &retbuf, &freebuf);
+       }
        vrele(vp);
-       if (error)
+       if (dvp != NULL)
+               vrele(dvp);
+       free(binname, M_TEMP);
+       if (error != 0)
                return (error);
        error = SYSCTL_OUT(req, retbuf, strlen(retbuf) + 1);
        free(freebuf, M_TEMP);

Reply via email to