Page MenuHomeFreeBSD

D51645.id159516.diff
No OneTemporary

D51645.id159516.diff

diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -235,6 +235,9 @@
{"allow.adjtime", "allow.noadjtime", PR_ALLOW_ADJTIME},
{"allow.settime", "allow.nosettime", PR_ALLOW_SETTIME},
{"allow.routing", "allow.norouting", PR_ALLOW_ROUTING},
+ {"allow.unprivileged_subjail_tampering",
+ "allow.nounprivileged_subjail_tampering",
+ PR_ALLOW_UNPRIV_SUBJAIL_TAMPER},
};
static unsigned pr_allow_all = PR_ALLOW_ALL_STATIC;
const size_t pr_flag_allow_size = sizeof(pr_flag_allow);
@@ -4012,6 +4015,7 @@
case PRIV_DEBUG_DIFFCRED:
case PRIV_DEBUG_SUGID:
case PRIV_DEBUG_UNPRIV:
+ case PRIV_DEBUG_DIFFJAIL:
/*
* Allow jail to set various resource limits and login
@@ -4049,8 +4053,10 @@
*/
case PRIV_SCHED_DIFFCRED:
case PRIV_SCHED_CPUSET:
+ case PRIV_SCHED_DIFFJAIL:
case PRIV_SIGNAL_DIFFCRED:
case PRIV_SIGNAL_SUGID:
+ case PRIV_SIGNAL_DIFFJAIL:
/*
* Allow jailed processes to write to sysctls marked as jail
@@ -4694,6 +4700,10 @@
"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, unprivileged_subjail_tampering,
+ CTLTYPE_INT | CTLFLAG_RW, "B",
+ "Unprivileged processes may use tamper with same-uid processes in subjails"
+ " (signal/debug/cpuset)");
SYSCTL_JAIL_PARAM(_allow, suser, CTLTYPE_INT | CTLFLAG_RW,
"B", "Processes in jail with uid 0 have privilege");
#ifdef VIMAGE
diff --git a/sys/kern/kern_priv.c b/sys/kern/kern_priv.c
--- a/sys/kern/kern_priv.c
+++ b/sys/kern/kern_priv.c
@@ -250,15 +250,29 @@
}
/*
- * Allow unprivileged process debugging on a per-jail basis.
- * Do this here instead of prison_priv_check(), so it can also
- * apply to prison0.
+ * Allow unprivileged process debugging and tampering on a per-jail
+ * basis. Do this here instead of prison_priv_check(), so these can
+ * also apply to prison0.
*/
- if (priv == PRIV_DEBUG_UNPRIV) {
+ switch (priv) {
+ case PRIV_DEBUG_UNPRIV:
if (prison_allow(cred, PR_ALLOW_UNPRIV_DEBUG)) {
error = 0;
goto out;
}
+ break;
+
+ case PRIV_DEBUG_DIFFJAIL:
+ case PRIV_SCHED_DIFFJAIL:
+ case PRIV_SIGNAL_DIFFJAIL:
+ if (prison_allow(cred, PR_ALLOW_UNPRIV_SUBJAIL_TAMPER)) {
+ error = 0;
+ goto out;
+ }
+ break;
+
+ default:
+ break;
}
return (priv_check_cred_post(cred, priv, error, false));
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -1890,6 +1890,25 @@
return (ESRCH);
}
+/*
+ * Determine if u1 can tamper with the subject specified by u2, if they are in
+ * different jails and 'unprivileged_subjail_tampering' jail policy allows it.
+ *
+ * May be called if u1 and u2 are in the same jail, but it is expected that the
+ * caller has already done a prison_check() prior to calling it.
+ *
+ * Returns: 0 for permitted, EPERM otherwise
+ */
+static int
+cr_can_tamper_with_subjail(struct ucred *u1, struct ucred *u2, int priv)
+{
+ MPASS(prison_check(u1, u2) == 0);
+ if (u1->cr_prison == u2->cr_prison)
+ return (0);
+
+ return (priv_check_cred(u1, priv));
+}
+
/*
* Helper for cr_cansee*() functions to abide by system-wide security.bsd.see_*
* policies. Determines if u1 "can see" u2 according to these policies.
@@ -2039,6 +2058,19 @@
return (error);
}
+ /*
+ * At this point, the target may be in a different jail than the
+ * subject -- the subject must be in a parent jail to the target,
+ * whether it is prison0 or a subordinate of prison0 that has
+ * children. Additional privileges are required to allow this, as
+ * whether the creds are truly equivalent or not must be determined on
+ * a case-by-case basis.
+ */
+ error = cr_can_tamper_with_subjail(cred, proc->p_ucred,
+ PRIV_SIGNAL_DIFFJAIL);
+ if (error)
+ return (error);
+
return (0);
}
@@ -2115,6 +2147,12 @@
if (error)
return (error);
}
+
+ error = cr_can_tamper_with_subjail(td->td_ucred, p->p_ucred,
+ PRIV_SCHED_DIFFJAIL);
+ if (error)
+ return (error);
+
return (0);
}
@@ -2150,6 +2188,34 @@
CTLFLAG_MPSAFE, 0, 0, sysctl_unprivileged_proc_debug, "I",
"Unprivileged processes may use process debugging facilities");
+/*
+ * By default, we do not allow unprivileged processes to tamper with processes
+ * in subjails, even those run with the same uid. There are valid setups in
+ * which this might be useful, so we offer a knob to enable it in the security
+ * namespace to be clear that this has security implications.
+ */
+static int
+sysctl_unprivileged_subjail_tampering(SYSCTL_HANDLER_ARGS)
+{
+ int error, val;
+
+ val = prison_allow(req->td->td_ucred, PR_ALLOW_UNPRIV_SUBJAIL_TAMPER);
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ if (val != 0 && val != 1)
+ return (EINVAL);
+ prison_set_allow(req->td->td_ucred, PR_ALLOW_UNPRIV_SUBJAIL_TAMPER,
+ val);
+ return (0);
+}
+
+SYSCTL_PROC(_security_bsd, OID_AUTO, unprivileged_subjail_tampering,
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_SECURE |
+ CTLFLAG_MPSAFE, 0, 0, sysctl_unprivileged_subjail_tampering, "I",
+ "Unprivileged processes may tamper with same-uid processes in subjails"
+ " (signal/debug/cpuset)");
+
/*
* Return true if the object owner/group ids are subset of the active
* credentials.
@@ -2235,6 +2301,11 @@
return (error);
}
+ error = cr_can_tamper_with_subjail(td->td_ucred, p->p_ucred,
+ PRIV_DEBUG_DIFFJAIL);
+ if (error)
+ return (error);
+
/* Can't trace init when securelevel > 0. */
if (p == initproc) {
error = securelevel_gt(td->td_ucred, 0);
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -260,6 +260,7 @@
#define PR_ALLOW_ADJTIME 0x00080000
#define PR_ALLOW_SETTIME 0x00100000
#define PR_ALLOW_ROUTING 0x00200000
+#define PR_ALLOW_UNPRIV_SUBJAIL_TAMPER 0x00400000
/*
* PR_ALLOW_PRISON0 are the allow flags that we apply by default to prison0,
@@ -267,14 +268,16 @@
* build time. PR_ALLOW_ALL_STATIC should contain any bit above that we expect
* to be used on the system, while PR_ALLOW_PRISON0 will be some subset of that.
*/
-#define PR_ALLOW_ALL_STATIC 0x003f87ff
-#define PR_ALLOW_PRISON0 (PR_ALLOW_ALL_STATIC)
+#define PR_ALLOW_ALL_STATIC 0x007f87ff
+#define PR_ALLOW_PRISON0 \
+ (PR_ALLOW_ALL_STATIC & ~PR_ALLOW_UNPRIV_SUBJAIL_TAMPER)
/*
* 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)
+#define PR_ALLOW_DIFFERENCES \
+ (PR_ALLOW_UNPRIV_DEBUG | PR_ALLOW_UNPRIV_SUBJAIL_TAMPER)
/*
* OSD methods
diff --git a/sys/sys/priv.h b/sys/sys/priv.h
--- a/sys/sys/priv.h
+++ b/sys/sys/priv.h
@@ -115,6 +115,7 @@
#define PRIV_DEBUG_SUGID 81 /* Exempt debugging setuid proc. */
#define PRIV_DEBUG_UNPRIV 82 /* Exempt unprivileged debug limit. */
#define PRIV_DEBUG_DENIED 83 /* Exempt P2_NOTRACE. */
+#define PRIV_DEBUG_DIFFJAIL 84 /* Exempt debugging other jails. */
/*
* Dtrace privileges.
@@ -193,6 +194,7 @@
#define PRIV_SCHED_CPUSET 206 /* Can manipulate cpusets. */
#define PRIV_SCHED_CPUSET_INTR 207 /* Can adjust IRQ to CPU binding. */
#define PRIV_SCHED_IDPRIO 208 /* Can set idle time scheduling. */
+#define PRIV_SCHED_DIFFJAIL 209 /* Exempt scheduling other jails. */
/*
* POSIX semaphore privileges.
@@ -204,6 +206,7 @@
*/
#define PRIV_SIGNAL_DIFFCRED 230 /* Exempt signalling other users. */
#define PRIV_SIGNAL_SUGID 231 /* Non-conserv signal setuid proc. */
+#define PRIV_SIGNAL_DIFFJAIL 232 /* Exempt signalling other jails. */
/*
* Sysctl privileges.

File Metadata

Mime Type
text/plain
Expires
Sat, Jul 25, 9:17 PM (15 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35498234
Default Alt Text
D51645.id159516.diff (7 KB)

Event Timeline