aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_proc.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-10-23 19:01:37 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-10-28 17:50:02 +0000
commitee92c8a842d61ffda8d111e1b0e398085c5bfb3a (patch)
treea8bba6b29fd29abda2776ebc9ad4e4f6448fd7f8 /sys/kern/kern_proc.c
parent351d5f7fc5161ededeaa226ee3f21a438ee4a632 (diff)
downloadsrc-ee92c8a842d61ffda8d111e1b0e398085c5bfb3a.tar.gz
src-ee92c8a842d61ffda8d111e1b0e398085c5bfb3a.zip
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
Diffstat (limited to 'sys/kern/kern_proc.c')
-rw-r--r--sys/kern/kern_proc.c54
1 files 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);