summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_jail.c6
-rw-r--r--sys/kern/kern_priv.c70
-rw-r--r--sys/sys/jail.h3
-rw-r--r--usr.sbin/jail/jail.810
4 files changed, 77 insertions, 12 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index c4c8c0f4f2da..1bad2d7488c1 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -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 | 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(_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,
diff --git a/sys/kern/kern_priv.c b/sys/kern/kern_priv.c
index c793bbba5a8b..36e19170baad 100644
--- a/sys/kern/kern_priv.c
+++ b/sys/kern/kern_priv.c
@@ -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,9 +58,57 @@ __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,
@@ -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);
}
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
index 52051386bde9..2a6ee07ecc47 100644
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -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
diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8
index b43eb765292b..cc3561f03f6a 100644
--- a/usr.sbin/jail/jail.8
+++ b/usr.sbin/jail/jail.8
@@ -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 affect the host
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 ,