Index: sys/kern/kern_jail.c =================================================================== --- sys/kern/kern_jail.c +++ sys/kern/kern_jail.c @@ -194,6 +194,8 @@ {"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); @@ -498,6 +500,7 @@ 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 +1533,9 @@ } } } - 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 +3788,8 @@ "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 +3841,16 @@ * 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; } Index: sys/kern/kern_prot.c =================================================================== --- sys/kern/kern_prot.c +++ sys/kern/kern_prot.c @@ -1629,6 +1629,38 @@ return (0); } +/* + * 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 = (req->td->td_ucred->cr_prison->pr_allow & + PR_ALLOW_UNPRIV_DEBUG) == PR_ALLOW_UNPRIV_DEBUG; + 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 @@ -1636,13 +1668,10 @@ * 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, 0, 0, + sysctl_unprivileged_proc_debug, "I", "Unprivileged processes may use process debugging facilities"); /*- @@ -1660,7 +1689,7 @@ KASSERT(td == curthread, ("%s: td not curthread", __func__)); PROC_LOCK_ASSERT(p, MA_OWNED); - if (!unprivileged_proc_debug) { + if (!(td->td_ucred->cr_prison->pr_allow & PR_ALLOW_UNPRIV_DEBUG)) { error = priv_check(td, PRIV_DEBUG_UNPRIV); if (error) return (error); Index: sys/sys/jail.h =================================================================== --- sys/sys/jail.h +++ sys/sys/jail.h @@ -231,7 +231,14 @@ #define PR_ALLOW_READ_MSGBUF 0x00000100 #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_UNPRIV_DEBUG 0x00020000 +#define PR_ALLOW_ALL_STATIC 0x000381ff + +/* + * 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