mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-14 14:55:41 +00:00
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
This commit is contained in:
parent
2636ba4d03
commit
b307954481
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=341084
@ -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, int flags)
|
||||
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, int flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
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 | CTLFLAG_RW,
|
||||
"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, const char *prefix_descr,
|
||||
* 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;
|
||||
}
|
||||
|
@ -165,6 +165,18 @@ priv_check_cred(struct ucred *cred, int priv, int flags)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
|
@ -1629,6 +1629,37 @@ p_cansched(struct thread *td, struct proc *p)
|
||||
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 = 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
|
||||
@ -1636,13 +1667,10 @@ p_cansched(struct thread *td, struct proc *p)
|
||||
* 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)))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user