Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_prot.c
Show First 20 Lines • Show All 1,624 Lines • ▼ Show 20 Lines | if (td->td_ucred->cr_ruid != p->p_ucred->cr_ruid && | ||||
error = priv_check(td, PRIV_SCHED_DIFFCRED); | error = priv_check(td, PRIV_SCHED_DIFFCRED); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
return (0); | 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); | |||||
jamie: It would be a little neater to replace with "val = prison_allow(req->td->td_ucred… | |||||
Done Inline ActionsGood call. lattera-gmail.com: Good call. | |||||
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 | * The 'unprivileged_proc_debug' flag may be used to disable a variety of | ||||
* unprivileged inter-process debugging services, including some procfs | * unprivileged inter-process debugging services, including some procfs | ||||
* functionality, ptrace(), and ktrace(). In the past, inter-process | * functionality, ptrace(), and ktrace(). In the past, inter-process | ||||
* debugging has been involved in a variety of security problems, and sites | * debugging has been involved in a variety of security problems, and sites | ||||
* not requiring the service might choose to disable it when hardening | * not requiring the service might choose to disable it when hardening | ||||
* systems. | * 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_PROC(_security_bsd, OID_AUTO, unprivileged_proc_debug, | ||||
SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_SECURE, 0, 0, | ||||
&unprivileged_proc_debug, 0, | sysctl_unprivileged_proc_debug, "I", | ||||
"Unprivileged processes may use process debugging facilities"); | "Unprivileged processes may use process debugging facilities"); | ||||
/*- | /*- | ||||
* Determine whether td may debug p. | * Determine whether td may debug p. | ||||
* Returns: 0 for permitted, an errno value otherwise | * Returns: 0 for permitted, an errno value otherwise | ||||
* Locks: Sufficient locks to protect various components of td and p | * Locks: Sufficient locks to protect various components of td and p | ||||
* must be held. td must be curthread, and a lock must | * must be held. td must be curthread, and a lock must | ||||
* be held for p. | * be held for p. | ||||
* References: td and p must be valid for the lifetime of the call | * References: td and p must be valid for the lifetime of the call | ||||
*/ | */ | ||||
int | int | ||||
p_candebug(struct thread *td, struct proc *p) | p_candebug(struct thread *td, struct proc *p) | ||||
{ | { | ||||
int credentialchanged, error, grpsubset, i, uidsubset; | int credentialchanged, error, grpsubset, i, uidsubset; | ||||
KASSERT(td == curthread, ("%s: td not curthread", __func__)); | KASSERT(td == curthread, ("%s: td not curthread", __func__)); | ||||
PROC_LOCK_ASSERT(p, MA_OWNED); | PROC_LOCK_ASSERT(p, MA_OWNED); | ||||
if (!unprivileged_proc_debug) { | |||||
error = priv_check(td, PRIV_DEBUG_UNPRIV); | error = priv_check(td, PRIV_DEBUG_UNPRIV); | ||||
Done Inline ActionsSince you're calling priv_check anyway, this test may be better placed in the "case PRIV_DEBUG_UNPRIV" part of prison_priv_check(). jamie: Since you're calling priv_check anyway, this test may be better placed in the "case… | |||||
Done Inline ActionsI'll take a look. Thanks for the suggestion! lattera-gmail.com: I'll take a look. Thanks for the suggestion! | |||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | |||||
if (td->td_proc == p) | if (td->td_proc == p) | ||||
return (0); | return (0); | ||||
if ((error = prison_check(td->td_ucred, p->p_ucred))) | if ((error = prison_check(td->td_ucred, p->p_ucred))) | ||||
return (error); | return (error); | ||||
#ifdef MAC | #ifdef MAC | ||||
if ((error = mac_proc_check_debug(td->td_ucred, p))) | if ((error = mac_proc_check_debug(td->td_ucred, p))) | ||||
return (error); | return (error); | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 570 Lines • Show Last 20 Lines |
It would be a little neater to replace with "val = prison_allow(req->td->td_ucred, PR_ALLOW_UNPRIV_DEBUG) != 0" (though see my comment above)