-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 I'm proposing a new sysctl(7) entry: proc.PID.realpath.
It's modeled after FreeBSD's kern.proc.pathname [1]. $ sysctl proc.201.realpath proc.201.realpath = /usr/pkg/bin/cscope $ sysctl proc.1.realpath sysctl: proc.1.realpath: Operation not permitted $ sysctl proc.curproc.realpath proc.curproc.realpath = /sbin/sysctl This sysctl interface makes its use in debuggers, namely gdb(1) [2], lldb(1) [3] and virtual machine runtimes (like dart-language). The original NetBSD (and formerly FreeBSD) way of handling was to readlink(2) of /proc/%d/exe (perhaps a Linux-like style): char * nbsd_pid_to_exec_file (struct target_ops *self, int pid) { ssize_t len; static char buf[PATH_MAX]; char name[PATH_MAX]; xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid); len = readlink (name, buf, PATH_MAX - 1); if (len != -1) { buf[len] = '\0'; return buf; } return NULL; } I'm suggesting procfs independence here, because of a safer access (/proc/%d/exe is world readlink(1)able) and not hardcoding of paths & depending upon available /proc. The kernel patch is attached to this mail. [1] https://www.freebsd.org/cgi/man.cgi?sysctl%283%29 [2] src/external/gpl3/gdb/dist/gdb/nbsd-nat.c [3] https://github.com/llvm-mirror/lldb/blob/master/source/Host/freebsd/Host InfoFreeBSD.cpp#L75 [4] https://github.com/dart-lang/sdk/issues/24302 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJV7O1aAAoJEEuzCOmwLnZsEOMP/imnjxm6itJC0GffGn+5ogdg iNujdlK+WkcHyb/wq4WXXmidJbgGe2qV6HFstUjnev8NoGIFzAE7z8lnw16Xbjs1 gIh8IhjfrqGJpjN/72OYkMxjpPVRDmBpR/wP1ZZsODmTw4yAX6VtzV82BBUDcON2 YQrnacHhtUVMTKOpoP7XKVlfOGPHzT4XPlre5SzWH0lmsy2+TfC27m8hBasr69bq lOMmvlernT7dVKmdR0KFm9NTiLe/R7R6lhSrfPs1YuguqI0jmPALvPYCICaYHdqP sTDHVhqVOy35Py6h/NafGQDlMY+xX2Hgw/GebDHp9OcSMaiynkeUml9XNz4xeNpT csnxbajtkabUsycYBvc6ekXENaokXC0rw+Pia9qMqCZm7JJJwYgIA5EeelFRLjyR AvKk/sN1RCzFfO+a9FNSwIP0Oxf7N2w/3RVnHXfIkAGDmeTQ9VVGzrNLlofNp9JO xgFL1DOoaYmmjjjNa+c+GSmAuzXNipAZdN8Nsq3if5KjK/KeJLXw4AYGPMl/n2ss SJAYsK83mwxpzJToFo5EoQ8NEaw6qWPXtu9IAYFjGH1HIXwc/14PlNH/0Aeo/LIW xKIh5qp4Dnki7NdbkHrSS8YalxkmCurAWpxPrcwFwKKveDy/Gzv3Ry9/ogC1Rbko vj1zS7KxpyVtmP8UBBMA =PrYO -----END PGP SIGNATURE-----
Index: kern/kern_proc.c =================================================================== RCS file: /public/netbsd-rsync/src/sys/kern/kern_proc.c,v retrieving revision 1.193 diff -u -r1.193 kern_proc.c --- kern/kern_proc.c 12 Jul 2014 09:57:25 -0000 1.193 +++ kern/kern_proc.c 6 Sep 2015 19:26:59 -0000 @@ -294,6 +294,7 @@ case KAUTH_PROCESS_CORENAME: case KAUTH_PROCESS_STOPFLAG: + case KAUTH_PROCESS_REALPATH: if (proc_uidmatch(cred, p->p_cred) == 0) result = KAUTH_RESULT_ALLOW; Index: kern/kern_resource.c =================================================================== RCS file: /public/netbsd-rsync/src/sys/kern/kern_resource.c,v retrieving revision 1.174 diff -u -r1.174 kern_resource.c --- kern/kern_resource.c 18 Oct 2014 08:33:29 -0000 1.174 +++ kern/kern_resource.c 6 Sep 2015 21:22:52 -0000 @@ -55,6 +55,7 @@ #include <sys/mount.h> #include <sys/syscallargs.h> #include <sys/atomic.h> +#include <sys/filedesc.h> #include <uvm/uvm_extern.h> @@ -898,6 +899,65 @@ } /* + * sysctl_proc_realpath: helper routine to get or set the absolute pathname + * for a process specified by PID. + */ +static int +sysctl_proc_realpath(SYSCTLFN_ARGS) +{ + struct proc *p; + struct sysctlnode node; + int error; + struct vnode *vp; + char path[MAXPATHLEN]; + + /* First, validate the request. */ + if (namelen != 0 || name[-1] != PROC_PID_REALPATH) { + return EINVAL; + } + + /* Find the process. Hold a reference (p_reflock), if found. */ + error = sysctl_proc_findproc(l, (pid_t)name[-2], &p); + if (error) { + return error; + } + + /* XXX-elad */ + error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, p, + KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL); + if (error) { + goto done; + } + + error = kauth_authorize_process(l->l_cred, + KAUTH_PROCESS_REALPATH, p, + KAUTH_ARG(KAUTH_REQ_PROCESS_REALPATH_GET), NULL, NULL); + if (error) { + goto done; + } + + vp = p->p_textvp; + if (vp == NULL) { + error = EINVAL; + goto done; + } + + error = vnode_to_path(path, MAXPATHLEN,vp, l, p); + if (error) { + goto done; + } + + node = *rnode; + node.sysctl_data = path; + node.sysctl_size = strlen(path) + 1; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + +done: + rw_exit(&p->p_reflock); + return error; +} + +/* * sysctl_proc_stop: helper routine for checking/setting the stop flags. */ static int @@ -1116,4 +1176,10 @@ SYSCTL_DESCR("Stop process before completing exit"), sysctl_proc_stop, 0, NULL, 0, CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXIT, CTL_EOL); + sysctl_createv(&proc_sysctllog, 0, NULL, NULL, + CTLFLAG_PERMANENT, + CTLTYPE_STRING, "realpath", + SYSCTL_DESCR("Canonicalized absolute pathname of the executable"), + sysctl_proc_realpath, 0, NULL, MAXPATHLEN, + CTL_PROC, PROC_CURPROC, PROC_PID_REALPATH, CTL_EOL); } Index: secmodel/keylock/secmodel_keylock.c =================================================================== RCS file: /public/netbsd-rsync/src/sys/secmodel/keylock/secmodel_keylock.c,v retrieving revision 1.8 diff -u -r1.8 secmodel_keylock.c --- secmodel/keylock/secmodel_keylock.c 25 Feb 2014 18:30:13 -0000 1.8 +++ secmodel/keylock/secmodel_keylock.c 6 Sep 2015 21:14:27 -0000 @@ -318,6 +318,11 @@ if (kstate == KEYLOCK_CLOSE) result = KAUTH_RESULT_DENY; break; + + case KAUTH_PROCESS_REALPATH: + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + break; } return result; } Index: secmodel/securelevel/secmodel_securelevel.c =================================================================== RCS file: /public/netbsd-rsync/src/sys/secmodel/securelevel/secmodel_securelevel.c,v retrieving revision 1.30 diff -u -r1.30 secmodel_securelevel.c --- secmodel/securelevel/secmodel_securelevel.c 25 Feb 2014 18:30:13 -0000 1.30 +++ secmodel/securelevel/secmodel_securelevel.c 6 Sep 2015 20:44:19 -0000 @@ -417,6 +417,11 @@ result = KAUTH_RESULT_DENY; break; + case KAUTH_PROCESS_REALPATH: + if (securelevel > 1) + result = KAUTH_RESULT_DENY; + break; + default: break; } @@ -629,4 +634,3 @@ return (result); } - Index: secmodel/suser/secmodel_suser.c =================================================================== RCS file: /public/netbsd-rsync/src/sys/secmodel/suser/secmodel_suser.c,v retrieving revision 1.42 diff -u -r1.42 secmodel_suser.c --- secmodel/suser/secmodel_suser.c 17 Aug 2015 06:16:03 -0000 1.42 +++ secmodel/suser/secmodel_suser.c 6 Sep 2015 20:42:15 -0000 @@ -496,6 +496,7 @@ case KAUTH_PROCESS_FORK: case KAUTH_PROCESS_CORENAME: case KAUTH_PROCESS_STOPFLAG: + case KAUTH_PROCESS_REALPATH: if (isroot) result = KAUTH_RESULT_ALLOW; @@ -953,4 +954,3 @@ return (result); } - Index: sys/kauth.h =================================================================== RCS file: /public/netbsd-rsync/src/sys/sys/kauth.h,v retrieving revision 1.72 diff -u -r1.72 kauth.h --- sys/kauth.h 17 Aug 2015 06:16:03 -0000 1.72 +++ sys/kauth.h 6 Sep 2015 19:25:09 -0000 @@ -179,7 +179,8 @@ KAUTH_PROCESS_SCHEDULER_SETPARAM, KAUTH_PROCESS_SETID, KAUTH_PROCESS_SIGNAL, - KAUTH_PROCESS_STOPFLAG + KAUTH_PROCESS_STOPFLAG, + KAUTH_PROCESS_REALPATH }; /* @@ -200,6 +201,7 @@ KAUTH_REQ_PROCESS_RLIMIT_GET, KAUTH_REQ_PROCESS_RLIMIT_SET, KAUTH_REQ_PROCESS_RLIMIT_BYPASS, + KAUTH_REQ_PROCESS_REALPATH_GET }; /* Index: sys/sysctl.h =================================================================== RCS file: /public/netbsd-rsync/src/sys/sys/sysctl.h,v retrieving revision 1.215 diff -u -r1.215 sysctl.h --- sys/sysctl.h 4 Jan 2015 22:11:40 -0000 1.215 +++ sys/sysctl.h 6 Sep 2015 12:26:18 -0000 @@ -958,8 +958,8 @@ #define PROC_CURPROC (~((u_int)1 << 31)) /* - * CTL_PROC tree: either corename (string), or a limit - * (rlimit.<type>.{hard,soft}, int). + * CTL_PROC tree: either corename (string), a limit + * (rlimit.<type>.{hard,soft}, int) or realpath. */ #define PROC_PID_CORENAME 1 #define PROC_PID_LIMIT 2 @@ -967,6 +967,7 @@ #define PROC_PID_STOPEXEC 4 #define PROC_PID_STOPEXIT 5 #define PROC_PID_MAXID 6 +#define PROC_PID_REALPATH 7 #define PROC_PID_NAMES { \ { 0, 0 }, \