svn commit: r341084 - in head: sys/kern sys/sys usr.sbin/jail

Jamie Gritton jamie at FreeBSD.org
Tue Nov 27 17:51:52 UTC 2018


Author: jamie
Date: Tue Nov 27 17:51:50 2018
New Revision: 341084
URL: https://svnweb.freebsd.org/changeset/base/341084

Log:
  In hardened systems, where the security.bsd.unprivileged_proc_debug sysctl
  node is set, allow setting security.bsd.unprivileged_proc_debug per-jail.
  In part, this is needed to create jails in which the Address Sanitizer
  (ASAN) fully works as ASAN utilizes libkvm to inspect the virtual address
  space. Instead of having to allow unprivileged process debugging for the
  entire system, allow setting it on a per-jail basis.
  
  The sysctl node is still security.bsd.unprivileged_proc_debug and the
  jail(8) param is allow.unprivileged_proc_debug. The sysctl code is now a
  sysctl proc rather than a sysctl int. This allows us to determine setting
  the flag for the corresponding jail (or prison0).
  
  As part of the change, the dynamic allow.* API needed to be modified to
  take into account pr_allow flags which may now be disabled in prison0.
  This prevents conflicts with new pr_allow flags (like that of vmm(4)) that
  are added (and removed) dynamically.
  
  Also teach the jail creation KPI to allow differences for certain pr_allow
  flags between the parent and child jail. This can happen when unprivileged
  process debugging is disabled in the parent prison, but enabled in the
  child.
  
  Submitted by:	Shawn Webb <lattera at gmail.com>
  Obtained from:	HardenedBSD (45b3625edba0f73b3e3890b1ec3d0d1e95fd47e1, deba0b5078cef0faae43cbdafed3035b16587afc, ab21eeb3b4c72f2500987c96ff603ccf3b6e7de8)
  Relnotes:	yes
  Sponsored by:	HardenedBSD and G2, Inc
  Differential Revision:	https://reviews.freebsd.org/D18319

Modified:
  head/sys/kern/kern_jail.c
  head/sys/kern/kern_priv.c
  head/sys/kern/kern_prot.c
  head/sys/sys/jail.h
  head/usr.sbin/jail/jail.8

Modified: head/sys/kern/kern_jail.c
==============================================================================
--- head/sys/kern/kern_jail.c	Tue Nov 27 17:10:00 2018	(r341083)
+++ head/sys/kern/kern_jail.c	Tue Nov 27 17:51:50 2018	(r341084)
@@ -194,10 +194,14 @@ static struct bool_flags pr_flag_allow[NBBY * NBPW] = 
 	{"allow.reserved_ports", "allow.noreserved_ports",
 	 PR_ALLOW_RESERVED_PORTS},
 	{"allow.read_msgbuf", "allow.noread_msgbuf", PR_ALLOW_READ_MSGBUF},
+	{"allow.unprivileged_proc_debug", "allow.nounprivileged_proc_debug",
+	 PR_ALLOW_UNPRIV_DEBUG},
 };
 const size_t pr_flag_allow_size = sizeof(pr_flag_allow);
 
-#define	JAIL_DEFAULT_ALLOW		(PR_ALLOW_SET_HOSTNAME | PR_ALLOW_RESERVED_PORTS)
+#define	JAIL_DEFAULT_ALLOW		(PR_ALLOW_SET_HOSTNAME | \
+					 PR_ALLOW_RESERVED_PORTS | \
+					 PR_ALLOW_UNPRIV_DEBUG)
 #define	JAIL_DEFAULT_ENFORCE_STATFS	2
 #define	JAIL_DEFAULT_DEVFS_RSNUM	0
 static unsigned jail_default_allow = JAIL_DEFAULT_ALLOW;
@@ -498,6 +502,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, i
 	int ip6s, redo_ip6;
 #endif
 	uint64_t pr_allow, ch_allow, pr_flags, ch_flags;
+	uint64_t pr_allow_diff;
 	unsigned tallow;
 	char numbuf[12];
 
@@ -1530,7 +1535,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, i
 			}
 		}
 	}
-	if (pr_allow & ~ppr->pr_allow) {
+	pr_allow_diff = pr_allow & ~ppr->pr_allow;
+	if (pr_allow_diff & ~PR_ALLOW_DIFFERENCES) {
 		error = EPERM;
 		goto done_deref_locked;
 	}
@@ -3783,6 +3789,8 @@ SYSCTL_JAIL_PARAM(_allow, reserved_ports, CTLTYPE_INT 
     "B", "Jail may bind sockets to reserved ports");
 SYSCTL_JAIL_PARAM(_allow, read_msgbuf, CTLTYPE_INT | CTLFLAG_RW,
     "B", "Jail may read the kernel message buffer");
+SYSCTL_JAIL_PARAM(_allow, unprivileged_proc_debug, CTLTYPE_INT | CTLFLAG_RW,
+    "B", "Unprivileged processes may use process debugging facilities");
 
 SYSCTL_JAIL_PARAM_SUBNODE(allow, mount, "Jail mount/unmount permission flags");
 SYSCTL_JAIL_PARAM(_allow_mount, , CTLTYPE_INT | CTLFLAG_RW,
@@ -3834,10 +3842,16 @@ prison_add_allow(const char *prefix, const char *name,
 	 * Find a free bit in prison0's pr_allow, failing if there are none
 	 * (which shouldn't happen as long as we keep track of how many
 	 * potential dynamic flags exist).
+	 *
+	 * Due to per-jail unprivileged process debugging support
+	 * using pr_allow, also verify against PR_ALLOW_ALL_STATIC.
+	 * prison0 may have unprivileged process debugging unset.
 	 */
 	for (allow_flag = 1;; allow_flag <<= 1) {
 		if (allow_flag == 0)
 			goto no_add;
+		if (allow_flag & PR_ALLOW_ALL_STATIC)
+			continue;
 		if ((prison0.pr_allow & allow_flag) == 0)
 			break;
 	}

Modified: head/sys/kern/kern_priv.c
==============================================================================
--- head/sys/kern/kern_priv.c	Tue Nov 27 17:10:00 2018	(r341083)
+++ head/sys/kern/kern_priv.c	Tue Nov 27 17:51:50 2018	(r341084)
@@ -166,6 +166,18 @@ priv_check_cred(struct ucred *cred, int priv, int flag
 	}
 
 	/*
+	 * Allow unprivileged process debugging on a per-jail basis.
+	 * Do this here instead of prison_priv_check(), so it can also
+	 * apply to prison0.
+	 */
+	if (priv == PRIV_DEBUG_UNPRIV) {
+		if (prison_allow(cred, PR_ALLOW_UNPRIV_DEBUG)) {
+			error = 0;
+			goto out;
+		}
+	}
+
+	/*
 	 * Now check with MAC, if enabled, to see if a policy module grants
 	 * privilege.
 	 */

Modified: head/sys/kern/kern_prot.c
==============================================================================
--- head/sys/kern/kern_prot.c	Tue Nov 27 17:10:00 2018	(r341083)
+++ head/sys/kern/kern_prot.c	Tue Nov 27 17:51:50 2018	(r341084)
@@ -1630,19 +1630,47 @@ p_cansched(struct thread *td, struct proc *p)
 }
 
 /*
+ * Handle getting or setting the prison's unprivileged_proc_debug
+ * value.
+ */
+static int
+sysctl_unprivileged_proc_debug(SYSCTL_HANDLER_ARGS)
+{
+	struct prison *pr;
+	int error, val;
+
+	val = prison_allow(req->td->td_ucred, PR_ALLOW_UNPRIV_DEBUG) != 0;
+	error = sysctl_handle_int(oidp, &val, 0, req);
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+	pr = req->td->td_ucred->cr_prison;
+	mtx_lock(&pr->pr_mtx);
+	switch (val) {
+	case 0:
+		pr->pr_allow &= ~(PR_ALLOW_UNPRIV_DEBUG);
+		break;
+	case 1:
+		pr->pr_allow |= PR_ALLOW_UNPRIV_DEBUG;
+		break;
+	default:
+		error = EINVAL;
+	}
+	mtx_unlock(&pr->pr_mtx);
+
+	return (error);
+}
+
+/*
  * The 'unprivileged_proc_debug' flag may be used to disable a variety of
  * unprivileged inter-process debugging services, including some procfs
  * functionality, ptrace(), and ktrace().  In the past, inter-process
  * debugging has been involved in a variety of security problems, and sites
  * not requiring the service might choose to disable it when hardening
  * systems.
- *
- * XXX: Should modifying and reading this variable require locking?
- * XXX: data declarations should be together near the beginning of the file.
  */
-static int	unprivileged_proc_debug = 1;
-SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW,
-    &unprivileged_proc_debug, 0,
+SYSCTL_PROC(_security_bsd, OID_AUTO, unprivileged_proc_debug,
+    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_SECURE, 0, 0,
+    sysctl_unprivileged_proc_debug, "I",
     "Unprivileged processes may use process debugging facilities");
 
 /*-
@@ -1660,11 +1688,8 @@ p_candebug(struct thread *td, struct proc *p)
 
 	KASSERT(td == curthread, ("%s: td not curthread", __func__));
 	PROC_LOCK_ASSERT(p, MA_OWNED);
-	if (!unprivileged_proc_debug) {
-		error = priv_check(td, PRIV_DEBUG_UNPRIV);
-		if (error)
-			return (error);
-	}
+	if ((error = priv_check(td, PRIV_DEBUG_UNPRIV)))
+		return (error);
 	if (td->td_proc == p)
 		return (0);
 	if ((error = prison_check(td->td_ucred, p->p_ucred)))

Modified: head/sys/sys/jail.h
==============================================================================
--- head/sys/sys/jail.h	Tue Nov 27 17:10:00 2018	(r341083)
+++ head/sys/sys/jail.h	Tue Nov 27 17:51:50 2018	(r341084)
@@ -229,9 +229,16 @@ struct prison_racct {
 #define	PR_ALLOW_SOCKET_AF		0x00000040
 #define	PR_ALLOW_MLOCK			0x00000080
 #define	PR_ALLOW_READ_MSGBUF		0x00000100
+#define	PR_ALLOW_UNPRIV_DEBUG		0x00000200
 #define	PR_ALLOW_RESERVED_PORTS		0x00008000
 #define	PR_ALLOW_KMEM_ACCESS		0x00010000	/* reserved, not used yet */
-#define	PR_ALLOW_ALL_STATIC		0x000181ff
+#define	PR_ALLOW_ALL_STATIC		0x000183ff
+
+/*
+ * PR_ALLOW_DIFFERENCES determines which flags are able to be
+ * different between the parent and child jail upon creation.
+ */
+#define	PR_ALLOW_DIFFERENCES		(PR_ALLOW_UNPRIV_DEBUG)
 
 /*
  * OSD methods

Modified: head/usr.sbin/jail/jail.8
==============================================================================
--- head/usr.sbin/jail/jail.8	Tue Nov 27 17:10:00 2018	(r341083)
+++ head/usr.sbin/jail/jail.8	Tue Nov 27 17:51:50 2018	(r341084)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 10, 2018
+.Dd November 27, 2018
 .Dt JAIL 8
 .Os
 .Sh NAME
@@ -582,6 +582,8 @@ memory subject to
 and resource limits.
 .It Va allow.reserved_ports
 The jail root may bind to ports lower than 1024.
+.It Va allow.unprivileged_proc_debug
+Unprivileged processes in the jail may use debugging facilities.
 .El
 .El
 .Pp


More information about the svn-src-all mailing list