Date: Tue, 27 Nov 2018 17:51:50 +0000 (UTC) From: Jamie Gritton <jamie@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r341084 - in head: sys/kern sys/sys usr.sbin/jail Message-ID: <201811271751.wARHpoPt077616@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201811271751.wARHpoPt077616>