o Replace calls to p_can(..., P_CAN_xxx) with calls to p_canxxx().

The p_can(...) construct was a premature (and, it turns out,
  awkward) abstraction.  The individual calls to p_canxxx() better
  reflect differences between the inter-process authorization checks,
  such as differing checks based on the type of signal.  This has
  a side effect of improving code readability.
o Replace direct credential authorization checks in ktrace() with
  invocation of p_candebug(), while maintaining the special case
  check of KTR_ROOT.  This allows ktrace() to "play more nicely"
  with new mandatory access control schemes, as well as making its
  authorization checks consistent with other "debugging class"
  checks.
o Eliminate "privused" construct for p_can*() calls which allowed the
  caller to determine if privilege was required for successful
  evaluation of the access control check.  This primitive is currently
  unused, and as such, serves only to complicate the API.

Approved by:	({procfs,linprocfs} changes) des
Obtained from:	TrustedBSD Project
This commit is contained in:
Robert Watson 2001-07-05 17:10:46 +00:00
parent 0b848380bb
commit a0f75161f9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=79335
17 changed files with 63 additions and 111 deletions

View file

@ -604,7 +604,7 @@ linprocfs_doproccmdline(PFS_FILL_ARGS)
* Linux behaviour is to return zero-length in this case.
*/
if (p->p_args && (ps_argsopen || !p_can(curp, p, P_CAN_SEE, NULL))) {
if (p->p_args && (ps_argsopen || !p_cansee(curp, p))) {
sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
} else if (p != curp) {
sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm);

View file

@ -119,7 +119,7 @@ procfs_control(curp, p, op)
* debug.
*/
if (op != PROCFS_CTL_DETACH &&
((error = p_can(curp, p, P_CAN_DEBUG, NULL))))
((error = p_candebug(curp, p))))
return (error);
/*

View file

@ -68,7 +68,7 @@ procfs_dodbregs(curp, p, pfs, uio)
char *kv;
int kl;
if (p_can(curp, p, P_CAN_DEBUG, NULL))
if (p_candebug(curp, p))
return (EPERM);
kl = sizeof(r);
kv = (char *) &r;

View file

@ -65,7 +65,7 @@ procfs_dofpregs(curp, p, pfs, uio)
char *kv;
int kl;
if (p_can(curp, p, P_CAN_DEBUG, NULL))
if (p_candebug(curp, p))
return EPERM;
kl = sizeof(r);
kv = (char *) &r;

View file

@ -263,7 +263,7 @@ procfs_domem(curp, p, pfs, uio)
* All in all, quite yucky.
*/
if (p_can(curp, p, P_CAN_DEBUG, NULL) &&
if (p_candebug(curp, p) &&
!(uio->uio_rw == UIO_READ &&
procfs_kmemaccess(curp)))
return EPERM;

View file

@ -66,7 +66,7 @@ procfs_doregs(curp, p, pfs, uio)
char *kv;
int kl;
if (p_can(curp, p, P_CAN_DEBUG, NULL))
if (p_candebug(curp, p))
return EPERM;
kl = sizeof(r);
kv = (char *) &r;

View file

@ -219,7 +219,7 @@ procfs_docmdline(curp, p, pfs, uio)
* Linux behaviour is to return zero-length in this case.
*/
if (p->p_args && (ps_argsopen || !p_can(curp, p, P_CAN_SEE, NULL))) {
if (p->p_args && (ps_argsopen || !p_cansee(curp, p))) {
bp = p->p_args->ar_args;
buflen = p->p_args->ar_length;
buf = 0;

View file

@ -143,7 +143,7 @@ procfs_open(ap)
p2 = PFIND(pfs->pfs_pid);
if (p2 == NULL)
return (ENOENT);
if (pfs->pfs_pid && p_can(ap->a_p, p2, P_CAN_SEE, NULL)) {
if (pfs->pfs_pid && p_cansee(ap->a_p, p2)) {
error = ENOENT;
goto out;
}
@ -157,7 +157,7 @@ procfs_open(ap)
}
p1 = ap->a_p;
if (p_can(p1, p2, P_CAN_DEBUG, NULL) &&
if (p_candebug(p1, p2) &&
!procfs_kmemaccess(p1)) {
error = EPERM;
}
@ -242,7 +242,7 @@ procfs_ioctl(ap)
return ENOTTY;
}
if ((error = p_can(p, procp, P_CAN_DEBUG, NULL))) {
if ((error = p_candebug(p, procp))) {
PROC_UNLOCK(procp);
return (error == ESRCH ? ENOENT : error);
}
@ -408,7 +408,7 @@ procfs_getattr(ap)
return (ENOENT);
}
if (p_can(ap->a_p, procp, P_CAN_SEE, NULL)) {
if (p_cansee(ap->a_p, procp)) {
PROC_UNLOCK(procp);
return (ENOENT);
}
@ -625,7 +625,7 @@ procfs_access(ap)
procp = PFIND(pfs->pfs_pid);
if (procp == NULL)
return (ENOENT);
if (p_can(ap->a_p, procp, P_CAN_SEE, NULL)) {
if (p_cansee(ap->a_p, procp)) {
PROC_UNLOCK(procp);
return (ENOENT);
}
@ -699,7 +699,7 @@ procfs_lookup(ap)
if (p == NULL)
break;
if (p_can(curp, p, P_CAN_SEE, NULL)) {
if (p_cansee(curp, p)) {
PROC_UNLOCK(p);
break;
}
@ -800,7 +800,7 @@ procfs_readdir(ap)
p = PFIND(pfs->pfs_pid);
if (p == NULL)
break;
if (p_can(curproc, p, P_CAN_SEE, NULL)) {
if (p_cansee(curproc, p)) {
PROC_UNLOCK(p);
break;
}
@ -868,11 +868,11 @@ procfs_readdir(ap)
p = LIST_NEXT(p, p_list);
if (p == NULL)
goto done;
if (p_can(curproc, p, P_CAN_SEE, NULL))
if (p_cansee(curproc, p))
continue;
pcnt++;
}
while (p_can(curproc, p, P_CAN_SEE, NULL)) {
while (p_cansee(curproc, p)) {
p = LIST_NEXT(p, p_list);
if (p == NULL)
goto done;

View file

@ -172,7 +172,7 @@ filt_procattach(struct knote *kn)
p = pfind(kn->kn_id);
if (p == NULL)
return (ESRCH);
if ((error = p_can(curproc, p, P_CAN_SEE, NULL))) {
if ((error = p_cansee(curproc, p))) {
PROC_UNLOCK(p);
return (error);
}

View file

@ -521,30 +521,20 @@ ktrwrite(vp, kth, uio)
* more permissions than the caller. KTRFAC_ROOT signifies that
* root previously set the tracing status on the target process, and
* so, only root may further change it.
*
* XXX: These checks are stronger than for ptrace()
* XXX: This check should be p_can(... P_CAN_DEBUG ...);
*
* TODO: check groups. use caller effective gid.
*/
static int
ktrcanset(callp, targetp)
struct proc *callp, *targetp;
{
struct ucred *callcr = callp->p_ucred;
struct ucred *targetcr = targetp->p_ucred;
if (prison_check(callcr, targetcr))
if (targetp->p_traceflag & KTRFAC_ROOT &&
suser_xxx(NULL, callp, PRISON_ROOT))
return (0);
if ((callcr->cr_uid == targetcr->cr_ruid &&
targetcr->cr_ruid == targetcr->cr_svuid &&
callcr->cr_rgid == targetcr->cr_rgid && /* XXX */
targetcr->cr_rgid == targetcr->cr_svgid &&
(targetp->p_traceflag & KTRFAC_ROOT) == 0) ||
!suser_xxx(callcr, NULL, PRISON_ROOT))
return (1);
return (0);
if (p_candebug(callp, targetp) != 0)
return (0);
return (1);
}
#endif /* KTRACE */

View file

@ -585,7 +585,7 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
p = pfind((pid_t)name[0]);
if (!p)
return (0);
if (p_can(curproc, p, P_CAN_SEE, NULL)) {
if (p_cansee(curproc, p)) {
PROC_UNLOCK(p);
return (0);
}
@ -616,7 +616,7 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
/*
* Show a user only appropriate processes.
*/
if (p_can(curproc, p, P_CAN_SEE, NULL))
if (p_cansee(curproc, p))
continue;
/*
* Skip embryonic processes.
@ -658,7 +658,7 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
break;
}
if (p_can(curproc, p, P_CAN_SEE, NULL))
if (p_cansee(curproc, p))
continue;
error = sysctl_out_proc(p, req, doingzomb);
@ -694,7 +694,7 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS)
if (!p)
return (0);
if ((!ps_argsopen) && p_can(curproc, p, P_CAN_SEE, NULL)) {
if ((!ps_argsopen) && p_cansee(curproc, p)) {
PROC_UNLOCK(p);
return (0);
}

View file

@ -151,7 +151,7 @@ getpgid(p, uap)
else {
if ((pt = pfind(uap->pid)) == NULL)
return ESRCH;
if ((error = p_can(p, pt, P_CAN_SEE, NULL))) {
if ((error = p_cansee(p, pt))) {
PROC_UNLOCK(pt);
return (error);
}
@ -183,7 +183,7 @@ getsid(p, uap)
else {
if ((pt = pfind(uap->pid)) == NULL)
return ESRCH;
if ((error = p_can(p, pt, P_CAN_SEE, NULL))) {
if ((error = p_cansee(p, pt))) {
PROC_UNLOCK(pt);
return (error);
}
@ -370,7 +370,7 @@ setpgid(curp, uap)
PROC_UNLOCK(targp);
return (ESRCH);
}
if ((error = p_can(curproc, targp, P_CAN_SEE, NULL))) {
if ((error = p_cansee(curproc, targp))) {
PROC_UNLOCK(targp);
return (error);
}
@ -1086,13 +1086,10 @@ u_cansee(struct ucred *u1, struct ucred *u2)
return (0);
}
static int
p_cansee(struct proc *p1, struct proc *p2, int *privused)
int
p_cansee(struct proc *p1, struct proc *p2)
{
/* XXX: privused is going away, so don't do that here. */
if (privused != NULL)
*privused = 0;
/* Wrap u_cansee() for all functionality. */
return (u_cansee(p1->p_ucred, p2->p_ucred));
}
@ -1167,14 +1164,11 @@ p_cansignal(struct proc *p1, struct proc *p2, int signum)
return (0);
}
static int
p_cansched(struct proc *p1, struct proc *p2, int *privused)
int
p_cansched(struct proc *p1, struct proc *p2)
{
int error;
if (privused != NULL)
*privused = 0;
if (p1 == p2)
return (0);
@ -1186,31 +1180,22 @@ p_cansched(struct proc *p1, struct proc *p2, int *privused)
if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid)
return (0);
if (!suser_xxx(0, p1, PRISON_ROOT)) {
if (privused != NULL)
*privused = 1;
if (!suser_xxx(0, p1, PRISON_ROOT))
return (0);
}
#ifdef CAPABILITIES
if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT)) {
if (privused != NULL)
*privused = 1;
if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT))
return (0);
}
#endif
return (EPERM);
}
static int
p_candebug(struct proc *p1, struct proc *p2, int *privused)
int
p_candebug(struct proc *p1, struct proc *p2)
{
int error;
if (privused != NULL)
*privused = 0;
if (p1 == p2)
return (0);
@ -1222,12 +1207,9 @@ p_candebug(struct proc *p1, struct proc *p2, int *privused)
if (p1->p_ucred->cr_uid != p2->p_ucred->cr_uid ||
p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid ||
p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid ||
p2->p_flag & P_SUGID) {
p2->p_flag & P_SUGID)
if ((error = suser_xxx(0, p1, PRISON_ROOT)))
return (error);
if (privused != NULL)
*privused = 1;
}
/* can't trace init when securelevel > 0 */
if (securelevel > 0 && p2->p_pid == 1)
@ -1236,27 +1218,6 @@ p_candebug(struct proc *p1, struct proc *p2, int *privused)
return (0);
}
int
p_can(struct proc *p1, struct proc *p2, int operation,
int *privused)
{
switch(operation) {
case P_CAN_SEE:
return (p_cansee(p1, p2, privused));
case P_CAN_SCHED:
return (p_cansched(p1, p2, privused));
case P_CAN_DEBUG:
return (p_candebug(p1, p2, privused));
default:
panic("p_can: invalid operation");
}
}
/*
* Allocate a zeroed cred structure.
*/

View file

@ -99,7 +99,7 @@ getpriority(curp, uap)
p = pfind(uap->who);
if (p == NULL)
break;
if (p_can(curp, p, P_CAN_SEE, NULL) == 0)
if (p_cansee(curp, p) == 0)
low = p->p_nice;
PROC_UNLOCK(p);
}
@ -113,7 +113,7 @@ getpriority(curp, uap)
else if ((pg = pgfind(uap->who)) == NULL)
break;
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
if (!p_can(curp, p, P_CAN_SEE, NULL) && p->p_nice < low)
if (!p_cansee(curp, p) && p->p_nice < low)
low = p->p_nice;
}
break;
@ -124,7 +124,7 @@ getpriority(curp, uap)
uap->who = curp->p_ucred->cr_uid;
sx_slock(&allproc_lock);
LIST_FOREACH(p, &allproc, p_list)
if (!p_can(curp, p, P_CAN_SEE, NULL) &&
if (!p_cansee(curp, p) &&
p->p_ucred->cr_uid == uap->who &&
p->p_nice < low)
low = p->p_nice;
@ -165,7 +165,7 @@ setpriority(curp, uap)
p = pfind(uap->who);
if (p == 0)
break;
if (p_can(curp, p, P_CAN_SEE, NULL) == 0)
if (p_cansee(curp, p) == 0)
error = donice(curp, p, uap->prio);
PROC_UNLOCK(p);
}
@ -180,7 +180,7 @@ setpriority(curp, uap)
else if ((pg = pgfind(uap->who)) == NULL)
break;
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
if (!p_can(curp, p, P_CAN_SEE, NULL)) {
if (!p_cansee(curp, p)) {
error = donice(curp, p, uap->prio);
found++;
}
@ -194,7 +194,7 @@ setpriority(curp, uap)
sx_slock(&allproc_lock);
LIST_FOREACH(p, &allproc, p_list)
if (p->p_ucred->cr_uid == uap->who &&
!p_can(curp, p, P_CAN_SEE, NULL)) {
!p_cansee(curp, p)) {
error = donice(curp, p, uap->prio);
found++;
}
@ -216,7 +216,7 @@ donice(curp, chgp, n)
{
int error;
if ((error = p_can(curp, chgp, P_CAN_SCHED, NULL)))
if ((error = p_cansched(curp, chgp)))
return (error);
if (n > PRIO_MAX)
n = PRIO_MAX;
@ -263,13 +263,13 @@ rtprio(curp, uap)
switch (uap->function) {
case RTP_LOOKUP:
if ((error = p_can(curp, p, P_CAN_SEE, NULL)))
if ((error = p_cansee(curp, p)))
break;
pri_to_rtp(&p->p_pri, &rtp);
error = copyout(&rtp, uap->rtp, sizeof(struct rtprio));
break;
case RTP_SET:
if ((error = p_can(curp, p, P_CAN_SCHED, NULL)) ||
if ((error = p_cansched(curp, p)) ||
(error = copyin(uap->rtp, &rtp, sizeof(struct rtprio))))
break;
/* disallow setting rtprio in most cases if not superuser */

View file

@ -122,7 +122,7 @@ int sched_setparam(struct proc *p,
return (ESRCH);
}
e = p_can(p, targetp, P_CAN_SCHED, NULL);
e = p_cansched(p, targetp);
PROC_UNLOCK(targetp);
if (e)
return (e);
@ -148,7 +148,7 @@ int sched_getparam(struct proc *p,
return (ESRCH);
}
e = p_can(p, targetp, P_CAN_SEE, NULL);
e = p_cansee(p, targetp);
PROC_UNLOCK(targetp);
if (e)
return (e);
@ -180,7 +180,7 @@ int sched_setscheduler(struct proc *p,
return (ESRCH);
}
e = p_can(p, targetp, P_CAN_SCHED, NULL);
e = p_cansched(p, targetp);
PROC_UNLOCK(targetp);
if (e)
return (e);
@ -205,7 +205,7 @@ int sched_getscheduler(struct proc *p,
return (ESRCH);
}
e = p_can(p, targetp, P_CAN_SEE, NULL);
e = p_cansee(p, targetp);
PROC_UNLOCK(targetp);
if (e)
return (e);
@ -246,7 +246,7 @@ int sched_rr_get_interval(struct proc *p,
return (ESRCH);
}
e = p_can(p, targetp, P_CAN_SEE, NULL);
e = p_cansee(p, targetp);
PROC_UNLOCK(targetp);
if (e)
return (e);

View file

@ -220,7 +220,7 @@ ptrace(curp, uap)
if ((p = pfind(uap->pid)) == NULL)
return ESRCH;
}
if (p_can(curp, p, P_CAN_SEE, NULL)) {
if (p_cansee(curp, p)) {
PROC_UNLOCK(p);
return (ESRCH);
}
@ -246,7 +246,7 @@ ptrace(curp, uap)
return EBUSY;
}
if ((error = p_can(curp, p, P_CAN_DEBUG, NULL))) {
if ((error = p_candebug(curp, p))) {
PROC_UNLOCK(p);
return error;
}

View file

@ -122,7 +122,7 @@ int sched_setparam(struct proc *p,
return (ESRCH);
}
e = p_can(p, targetp, P_CAN_SCHED, NULL);
e = p_cansched(p, targetp);
PROC_UNLOCK(targetp);
if (e)
return (e);
@ -148,7 +148,7 @@ int sched_getparam(struct proc *p,
return (ESRCH);
}
e = p_can(p, targetp, P_CAN_SEE, NULL);
e = p_cansee(p, targetp);
PROC_UNLOCK(targetp);
if (e)
return (e);
@ -180,7 +180,7 @@ int sched_setscheduler(struct proc *p,
return (ESRCH);
}
e = p_can(p, targetp, P_CAN_SCHED, NULL);
e = p_cansched(p, targetp);
PROC_UNLOCK(targetp);
if (e)
return (e);
@ -205,7 +205,7 @@ int sched_getscheduler(struct proc *p,
return (ESRCH);
}
e = p_can(p, targetp, P_CAN_SEE, NULL);
e = p_cansee(p, targetp);
PROC_UNLOCK(targetp);
if (e)
return (e);
@ -246,7 +246,7 @@ int sched_rr_get_interval(struct proc *p,
return (ESRCH);
}
e = p_can(p, targetp, P_CAN_SEE, NULL);
e = p_cansee(p, targetp);
PROC_UNLOCK(targetp);
if (e)
return (e);

View file

@ -518,8 +518,9 @@ void fork_return __P((struct proc *, struct trapframe *));
int inferior __P((struct proc *p));
int leavepgrp __P((struct proc *p));
void mi_switch __P((void));
int p_can __P((struct proc *p1, struct proc *p2, int operation,
int *privused));
int p_candebug __P((struct proc *p1, struct proc *p2));
int p_cansee __P((struct proc *p1, struct proc *p2));
int p_cansched __P((struct proc *p1, struct proc *p2));
int p_cansignal __P((struct proc *p1, struct proc *p2, int signum));
int p_trespass __P((struct proc *p1, struct proc *p2));
void procinit __P((void));