tech-kern archive

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

New sysctl entry: proc.PID.realpath



-----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 }, \


Home | Main Index | Thread Index | Old Index