Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Nov 2020 21:07:08 +0000 (UTC)
From:      Mariusz Zaborski <oshogbo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r367819 - in head: sys/kern sys/sys usr.sbin/jail
Message-ID:  <202011182107.0AIL78pi053574@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: oshogbo
Date: Wed Nov 18 21:07:08 2020
New Revision: 367819
URL: https://svnweb.freebsd.org/changeset/base/367819

Log:
  jail: introduce per jail suser_enabled setting
  
  The suser_enable sysctl allows to remove a privileged rights from uid 0.
  This change introduce per jail setting which allow to make root a
  normal user.
  
  Reviewed by:	jamie
  Previous version reviewed by:	kevans, emaste, markj, me_igalic.co
  Discussed with:	pjd
  Differential Revision:	https://reviews.freebsd.org/D27128

Modified:
  head/sys/kern/kern_jail.c
  head/sys/kern/kern_priv.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	Wed Nov 18 20:59:58 2020	(r367818)
+++ head/sys/kern/kern_jail.c	Wed Nov 18 21:07:08 2020	(r367819)
@@ -199,12 +199,14 @@ static struct bool_flags pr_flag_allow[NBBY * NBPW] = 
 	{"allow.read_msgbuf", "allow.noread_msgbuf", PR_ALLOW_READ_MSGBUF},
 	{"allow.unprivileged_proc_debug", "allow.nounprivileged_proc_debug",
 	 PR_ALLOW_UNPRIV_DEBUG},
+	{"allow.suser", "allow.nosuser", PR_ALLOW_SUSER},
 };
 const size_t pr_flag_allow_size = sizeof(pr_flag_allow);
 
 #define	JAIL_DEFAULT_ALLOW		(PR_ALLOW_SET_HOSTNAME | \
 					 PR_ALLOW_RESERVED_PORTS | \
-					 PR_ALLOW_UNPRIV_DEBUG)
+					 PR_ALLOW_UNPRIV_DEBUG | \
+					 PR_ALLOW_SUSER)
 #define	JAIL_DEFAULT_ENFORCE_STATFS	2
 #define	JAIL_DEFAULT_DEVFS_RSNUM	0
 static unsigned jail_default_allow = JAIL_DEFAULT_ALLOW;
@@ -3815,6 +3817,8 @@ SYSCTL_JAIL_PARAM(_allow, read_msgbuf, CTLTYPE_INT | C
     "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(_allow, suser, CTLTYPE_INT | CTLFLAG_RW,
+    "B", "Processes in jail with uid 0 have privilege");
 
 SYSCTL_JAIL_PARAM_SUBNODE(allow, mount, "Jail mount/unmount permission flags");
 SYSCTL_JAIL_PARAM(_allow_mount, , CTLTYPE_INT | CTLFLAG_RW,

Modified: head/sys/kern/kern_priv.c
==============================================================================
--- head/sys/kern/kern_priv.c	Wed Nov 18 20:59:58 2020	(r367818)
+++ head/sys/kern/kern_priv.c	Wed Nov 18 21:07:08 2020	(r367819)
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2006 nCircle Network Security, Inc.
  * Copyright (c) 2009 Robert N. M. Watson
+ * Copyright (c) 2020 Mariusz Zaborski <oshogbo@FreeBSD.org>
  * All rights reserved.
  *
  * This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -36,6 +37,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/sdt.h>
@@ -54,10 +58,58 @@ __FBSDID("$FreeBSD$");
  * userland programs, and should not be done without careful consideration of
  * the consequences.
  */
-static int __read_mostly	suser_enabled = 1;
-SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RWTUN,
-    &suser_enabled, 0, "processes with uid 0 have privilege");
 
+static bool
+suser_enabled(struct ucred *cred)
+{
+
+	return (prison_allow(cred, PR_ALLOW_SUSER) ? true : false);
+}
+
+static void inline
+prison_suser_set(struct prison *pr, int enabled)
+{
+
+	if (enabled) {
+		pr->pr_allow |= PR_ALLOW_SUSER;
+	} else {
+		pr->pr_allow &= ~PR_ALLOW_SUSER;
+	}
+}
+
+static int
+sysctl_kern_suser_enabled(SYSCTL_HANDLER_ARGS)
+{
+	struct prison *pr, *cpr;
+	struct ucred *cred;
+	int descend, error, enabled;
+
+	cred = req->td->td_ucred;
+	enabled = suser_enabled(cred);
+
+	error = sysctl_handle_int(oidp, &enabled, 0, req);
+	if (error || !req->newptr)
+		return (error);
+
+	pr = cred->cr_prison;
+	sx_slock(&allprison_lock);
+	mtx_lock(&pr->pr_mtx);
+
+	prison_suser_set(pr, enabled);
+	if (!enabled) {
+		FOREACH_PRISON_DESCENDANT_LOCKED(pr, cpr, descend) {
+			prison_suser_set(cpr, 0);
+		}
+	}
+	mtx_unlock(&pr->pr_mtx);
+	sx_sunlock(&allprison_lock);
+	return (0);
+}
+
+SYSCTL_PROC(_security_bsd, OID_AUTO, suser_enabled, CTLTYPE_INT |
+    CTLFLAG_RWTUN | CTLFLAG_PRISON, 0, 0, &sysctl_kern_suser_enabled, "I",
+    "Processes with uid 0 have privilege");
+
 static int	unprivileged_mlock = 1;
 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_mlock, CTLFLAG_RWTUN,
     &unprivileged_mlock, 0, "Allow non-root users to call mlock(2)");
@@ -186,7 +238,7 @@ priv_check_cred(struct ucred *cred, int priv)
 	 * superuser policy to be globally disabled, although this is
 	 * currenty of limited utility.
 	 */
-	if (suser_enabled) {
+	if (suser_enabled(cred)) {
 		switch (priv) {
 		case PRIV_MAXFILES:
 		case PRIV_MAXPROC:
@@ -258,7 +310,7 @@ priv_check_cred_vfs_lookup_slow(struct ucred *cred)
 	if (error)
 		goto out;
 
-	if (cred->cr_uid == 0 && suser_enabled) {
+	if (cred->cr_uid == 0 && suser_enabled(cred)) {
 		error = 0;
 		goto out;
 	}
@@ -279,7 +331,7 @@ priv_check_cred_vfs_lookup(struct ucred *cred)
 		return (priv_check_cred_vfs_lookup_slow(cred));
 
 	error = EPERM;
-	if (cred->cr_uid == 0 && suser_enabled)
+	if (cred->cr_uid == 0 && suser_enabled(cred))
 		error = 0;
 	return (error);
 }
@@ -294,7 +346,7 @@ priv_check_cred_vfs_lookup_nomac(struct ucred *cred)
 		return (EAGAIN);
 
 	error = EPERM;
-	if (cred->cr_uid == 0 && suser_enabled)
+	if (cred->cr_uid == 0 && suser_enabled(cred))
 		error = 0;
 	return (error);
 }
@@ -313,7 +365,7 @@ priv_check_cred_vfs_generation_slow(struct ucred *cred
 		goto out;
 	}
 
-	if (cred->cr_uid == 0 && suser_enabled) {
+	if (cred->cr_uid == 0 && suser_enabled(cred)) {
 		error = 0;
 		goto out;
 	}
@@ -334,7 +386,7 @@ priv_check_cred_vfs_generation(struct ucred *cred)
 		return (priv_check_cred_vfs_generation_slow(cred));
 
 	error = EPERM;
-	if (!jailed(cred) && cred->cr_uid == 0 && suser_enabled)
+	if (!jailed(cred) && cred->cr_uid == 0 && suser_enabled(cred))
 		error = 0;
 	return (error);
 }

Modified: head/sys/sys/jail.h
==============================================================================
--- head/sys/sys/jail.h	Wed Nov 18 20:59:58 2020	(r367818)
+++ head/sys/sys/jail.h	Wed Nov 18 21:07:08 2020	(r367819)
@@ -232,9 +232,10 @@ struct prison_racct {
 #define	PR_ALLOW_MLOCK			0x00000080
 #define	PR_ALLOW_READ_MSGBUF		0x00000100
 #define	PR_ALLOW_UNPRIV_DEBUG		0x00000200
+#define	PR_ALLOW_SUSER			0x00000400
 #define	PR_ALLOW_RESERVED_PORTS		0x00008000
 #define	PR_ALLOW_KMEM_ACCESS		0x00010000	/* reserved, not used yet */
-#define	PR_ALLOW_ALL_STATIC		0x000183ff
+#define	PR_ALLOW_ALL_STATIC		0x000187ff
 
 /*
  * PR_ALLOW_DIFFERENCES determines which flags are able to be

Modified: head/usr.sbin/jail/jail.8
==============================================================================
--- head/usr.sbin/jail/jail.8	Wed Nov 18 20:59:58 2020	(r367818)
+++ head/usr.sbin/jail/jail.8	Wed Nov 18 21:07:08 2020	(r367819)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 14, 2020
+.Dd November 18, 2020
 .Dt JAIL 8
 .Os
 .Sh NAME
@@ -587,6 +587,13 @@ and resource limits.
 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.
+.It Va allow.suser
+The value of the jail's
+.Va security.bsd.suser_enabled
+sysctl.
+The super-user will be disabled automatically if its parent system has it
+disabled.
+The super-user is enabled by default.
 .El
 .El
 .Pp
@@ -1267,6 +1274,7 @@ Changes to these variables by a jailed process do not 
 environment, only the jail environment.
 These variables are
 .Va kern.securelevel ,
+.Va security.bsd.suser_enabled ,
 .Va kern.hostname ,
 .Va kern.domainname ,
 .Va kern.hostid ,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202011182107.0AIL78pi053574>