o Centralize inter-process access control, introducing:

int p_can(p1, p2, operation, privused)

  which allows specification of subject process, object process,
  inter-process operation, and an optional call-by-reference privused
  flag, allowing the caller to determine if privilege was required
  for the call to succeed.  This allows jail, kern.ps_showallprocs and
  regular credential-based interaction checks to occur in one block of
  code.  Possible operations are P_CAN_SEE, P_CAN_SCHED, P_CAN_KILL,
  and P_CAN_DEBUG.  p_can currently breaks out as a wrapper to a
  series of static function checks in kern_prot, which should not
  be invoked directly.

o Commented out capabilities entries are included for some checks.

o Update most inter-process authorization to make use of p_can() instead
  of manual checks, PRISON_CHECK(), P_TRESPASS(), and
  kern.ps_showallprocs.

o Modify suser{,_xxx} to use const arguments, as it no longer modifies
  process flags due to the disabling of ASU.

o Modify some checks/errors in procfs so that ENOENT is returned instead
  of ESRCH, further improving concealment of processes that should not
  be visible to other processes.  Also introduce new access checks to
  improve hiding of processes for procfs_lookup(), procfs_getattr(),
  procfs_readdir().  Correct a bug reported by bp concerning not
  handling the CREATE case in procfs_lookup().  Remove volatile flag in
  procfs that caused apparently spurious qualifier warnigns (approved by
  bde).

o Add comment noting that ktrace() has not been updated, as its access
  control checks are different from ptrace(), whereas they should
  probably be the same.  Further discussion should happen on this topic.

Reviewed by:	bde, green, phk, freebsd-security, others
Approved by:	bde
Obtained from:	TrustedBSD Project
This commit is contained in:
rwatson 2000-08-30 04:49:09 +00:00
parent 496b1356ff
commit 3dc6d2b9ea
20 changed files with 256 additions and 84 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -137,7 +137,7 @@ procfs_open(ap)
p2 = PFIND(pfs->pfs_pid);
if (p2 == NULL)
return (ENOENT);
if (pfs->pfs_pid && !PRISON_CHECK(ap->a_p, p2))
if (pfs->pfs_pid && p_can(ap->a_p, p2, P_CAN_SEE, NULL))
return (ENOENT);
switch (pfs->pfs_type) {
@ -147,7 +147,7 @@ procfs_open(ap)
return (EBUSY);
p1 = ap->a_p;
if (p_trespass(p1, p2) &&
if (p_can(p1, p2, P_CAN_DEBUG, NULL) &&
!procfs_kmemaccess(p1))
return (EPERM);
@ -239,8 +239,11 @@ procfs_ioctl(ap)
return ENOTTY;
}
if (p_trespass(p, procp))
return EPERM;
if ((error = p_can(p, procp, P_CAN_DEBUG, NULL))) {
if (error == ESRCH)
error = ENOENT;
return (error);
}
switch (ap->a_command) {
case PIOCBIS:
@ -417,6 +420,9 @@ procfs_getattr(ap)
if (procp == 0 || procp->p_cred == NULL ||
procp->p_ucred == NULL)
return (ENOENT);
if (p_can(ap->a_p, procp, P_CAN_SEE, NULL))
return (ENOENT);
}
error = 0;
@ -612,16 +618,23 @@ procfs_access(ap)
struct proc *a_p;
} */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
struct proc *procp;
struct vattr *vap;
struct vattr vattr;
int error;
/*
* If you're the super-user,
* you always get access.
*/
if (ap->a_cred->cr_uid == 0)
return (0);
switch (pfs->pfs_type) {
case Proot:
case Pcurproc:
break;
default:
procp = PFIND(pfs->pfs_pid);
if (procp == NULL)
return (ENOENT);
if (p_can(ap->a_p, procp, P_CAN_SEE, NULL))
return (ENOENT);
}
vap = &vattr;
error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p);
@ -674,7 +687,7 @@ procfs_lookup(ap)
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
char *pname = cnp->cn_nameptr;
/* struct proc *curp = cnp->cn_proc; */
struct proc *curp = cnp->cn_proc;
struct proc_target *pt;
pid_t pid;
struct pfsnode *pfs;
@ -683,7 +696,8 @@ procfs_lookup(ap)
*vpp = NULL;
if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME ||
cnp->cn_nameiop == CREATE)
return (EROFS);
if (cnp->cn_namelen == 1 && *pname == '.') {
@ -710,6 +724,9 @@ procfs_lookup(ap)
if (p == 0)
break;
if (p_can(curp, p, P_CAN_SEE, NULL))
break;
return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
case Pproc:
@ -803,7 +820,7 @@ procfs_readdir(ap)
p = PFIND(pfs->pfs_pid);
if (p == NULL)
break;
if (!PRISON_CHECK(curproc, p))
if (p_can(curproc, p, P_CAN_SEE, NULL))
break;
for (pt = &proc_targets[i];
@ -838,7 +855,7 @@ procfs_readdir(ap)
int doingzomb = 0;
#endif
int pcnt = 0;
volatile struct proc *p = allproc.lh_first;
struct proc *p = allproc.lh_first;
for (; p && uio->uio_resid >= delen; i++, pcnt++) {
bzero((char *) dp, delen);
@ -866,11 +883,11 @@ procfs_readdir(ap)
p = p->p_list.le_next;
if (!p)
goto done;
if (!PRISON_CHECK(curproc, p))
if (p_can(curproc, p, P_CAN_SEE, NULL))
continue;
pcnt++;
}
while (!PRISON_CHECK(curproc, p)) {
while (p_can(curproc, p, P_CAN_SEE, NULL)) {
p = p->p_list.le_next;
if (!p)
goto done;

View File

@ -200,7 +200,7 @@ filt_procattach(struct knote *kn)
p = pfind(kn->kn_id);
if (p == NULL)
return (ESRCH);
if (! PRISON_CHECK(curproc, p))
if (p_can(curproc, p, P_CAN_SEE, NULL))
return (EACCES);
kn->kn_ptr.p_proc = p;

View File

@ -513,6 +513,8 @@ ktrwrite(vp, kth, uio)
* 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()
*
* TODO: check groups. use caller effective gid.
*/
static int

View File

@ -55,7 +55,7 @@ MALLOC_DEFINE(M_SESSION, "session", "session header");
static MALLOC_DEFINE(M_PROC, "proc", "Proc structures");
MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures");
static int ps_showallprocs = 1;
int ps_showallprocs = 1;
SYSCTL_INT(_kern, OID_AUTO, ps_showallprocs, CTLFLAG_RW,
&ps_showallprocs, 0, "");
@ -586,7 +586,7 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
p = pfind((pid_t)name[0]);
if (!p)
return (0);
if (!PRISON_CHECK(curproc, p))
if (p_can(curproc, p, P_CAN_SEE, NULL))
return (0);
error = sysctl_out_proc(p, req, 0);
return (error);
@ -611,9 +611,9 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
p = LIST_FIRST(&zombproc);
for (; p != 0; p = LIST_NEXT(p, p_list)) {
/*
* Show a user only their processes.
* Show a user only appropriate processes.
*/
if ((!ps_showallprocs) && p_trespass(curproc, p))
if (p_can(curproc, p, P_CAN_SEE, NULL))
continue;
/*
* Skip embryonic processes.
@ -655,7 +655,7 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
break;
}
if (!PRISON_CHECK(curproc, p))
if (p_can(curproc, p, P_CAN_SEE, NULL))
continue;
error = sysctl_out_proc(p, req, doingzomb);
@ -688,7 +688,7 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS)
if (!p)
return (0);
if ((!ps_argsopen) && p_trespass(curproc, p))
if ((!ps_argsopen) && p_can(curproc, p, P_CAN_SEE, NULL))
return (0);
if (req->newptr && curproc != p)

View File

@ -945,15 +945,15 @@ SYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0,
*/
int
suser(p)
struct proc *p;
const struct proc *p;
{
return suser_xxx(0, p, 0);
}
int
suser_xxx(cred, proc, flag)
struct ucred *cred;
struct proc *proc;
const struct ucred *cred;
const struct proc *proc;
int flag;
{
if (!suser_permitted)
@ -971,31 +971,165 @@ suser_xxx(cred, proc, flag)
return (0);
}
/*
* Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise.
*/
int
p_trespass(struct proc *p1, struct proc *p2)
static int
p_cansee(const struct proc *p1, const struct proc *p2, int *privused)
{
if (privused != NULL)
*privused = 0;
if (!PRISON_CHECK(p1, p2))
return (ESRCH);
if (!ps_showallprocs && (p1->p_ucred->cr_uid != p2->p_ucred->cr_uid) &&
suser_xxx(NULL, p1, PRISON_ROOT))
return (ESRCH);
return (0);
}
static int
p_cankill(const struct proc *p1, const struct proc *p2, int *privused)
{
if (privused != NULL)
*privused = 0;
if (p1 == p2)
return (0);
if (!PRISON_CHECK(p1, p2))
return (ESRCH);
if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
return (0);
if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid)
return (0);
/*
* XXX should a process be able to affect another process
* acting as the same uid (i.e., a userland nfsd or the like?)
*/
if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid)
return (0);
if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid)
return (0);
if (!suser_xxx(0, p1, PRISON_ROOT))
if (!suser_xxx(0, p1, PRISON_ROOT)) {
if (privused != NULL)
*privused = 1;
return (0);
}
#ifdef CAPABILITIES
if (!cap_check_xxx(0, p1, CAP_KILL, PRISON_ROOT)) {
if (privused != NULL)
*privused = 1;
return (0);
}
#endif
return (EPERM);
}
static int
p_cansched(const struct proc *p1, const struct proc *p2, int *privused)
{
if (privused != NULL)
*privused = 0;
if (p1 == p2)
return (0);
if (!PRISON_CHECK(p1, p2))
return (ESRCH);
if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
return (0);
if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid)
return (0);
/*
* XXX should a process be able to affect another process
* acting as the same uid (i.e., a userland nfsd or the like?)
*/
if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid)
return (0);
if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid)
return (0);
if (!suser_xxx(0, p1, PRISON_ROOT)) {
if (privused != NULL)
*privused = 1;
return (0);
}
#ifdef CAPABILITIES
if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT)) {
if (privused != NULL)
*privused = 1;
return (0);
}
#endif
return (EPERM);
}
static int
p_candebug(const struct proc *p1, const struct proc *p2, int *privused)
{
int error;
if (privused != NULL)
*privused = 0;
/* XXX it is authorized, but semantics don't permit it */
if (p1 == p2)
return (0);
if (!PRISON_CHECK(p1, p2))
return (ESRCH);
/* not owned by you, has done setuid (unless you're root) */
/* add a CAP_SYS_PTRACE here? */
if ((p1->p_cred->p_ruid != p2->p_cred->p_ruid) ||
(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)
return (EPERM);
return (0);
}
int
p_can(const struct proc *p1, const struct proc *p2, int operation,
int *privused)
{
switch(operation) {
case P_CAN_SEE:
return (p_cansee(p1, p2, privused));
case P_CAN_KILL:
return (p_cankill(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

@ -88,7 +88,7 @@ getpriority(curp, uap)
p = pfind(uap->who);
if (p == 0)
break;
if (!PRISON_CHECK(curp, p))
if (p_can(curp, p, P_CAN_SEE, NULL))
break;
low = p->p_nice;
break;
@ -101,7 +101,7 @@ getpriority(curp, uap)
else if ((pg = pgfind(uap->who)) == NULL)
break;
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
if ((PRISON_CHECK(curp, p) && p->p_nice < low))
if (!p_can(curp, p, P_CAN_SEE, NULL) && p->p_nice < low)
low = p->p_nice;
}
break;
@ -111,7 +111,7 @@ getpriority(curp, uap)
if (uap->who == 0)
uap->who = curp->p_ucred->cr_uid;
LIST_FOREACH(p, &allproc, p_list)
if (PRISON_CHECK(curp, p) &&
if (!p_can(curp, p, P_CAN_SEE, NULL) &&
p->p_ucred->cr_uid == uap->who &&
p->p_nice < low)
low = p->p_nice;
@ -151,7 +151,7 @@ setpriority(curp, uap)
p = pfind(uap->who);
if (p == 0)
break;
if (!PRISON_CHECK(curp, p))
if (p_can(curp, p, P_CAN_SEE, NULL))
break;
error = donice(curp, p, uap->prio);
found++;
@ -165,7 +165,7 @@ setpriority(curp, uap)
else if ((pg = pgfind(uap->who)) == NULL)
break;
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
if (PRISON_CHECK(curp, p)) {
if (!p_can(curp, p, P_CAN_SEE, NULL)) {
error = donice(curp, p, uap->prio);
found++;
}
@ -178,7 +178,7 @@ setpriority(curp, uap)
uap->who = curp->p_ucred->cr_uid;
LIST_FOREACH(p, &allproc, p_list)
if (p->p_ucred->cr_uid == uap->who &&
PRISON_CHECK(curp, p)) {
!p_can(curp, p, P_CAN_SEE, NULL)) {
error = donice(curp, p, uap->prio);
found++;
}
@ -197,9 +197,10 @@ donice(curp, chgp, n)
register struct proc *curp, *chgp;
register int n;
{
int error;
if (p_trespass(curp, chgp) != 0)
return (EPERM);
if ((error = p_can(curp, chgp, P_CAN_SCHED, NULL)))
return (error);
if (n > PRIO_MAX)
n = PRIO_MAX;
if (n < PRIO_MIN)
@ -250,8 +251,8 @@ rtprio(curp, uap)
case RTP_LOOKUP:
return (copyout(&p->p_rtprio, uap->rtp, sizeof(struct rtprio)));
case RTP_SET:
if (p_trespass(curp, p) != 0)
return (EPERM);
if ((error = p_can(curp, p, P_CAN_SCHED, NULL)))
return (error);
/* disallow setting rtprio in most cases if not superuser */
if (suser(curp) != 0) {
/* can't set someone else's */

View File

@ -97,7 +97,7 @@ SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW,
* Can process p, with pcred pc, send the signal sig to process q?
*/
#define CANSIGNAL(p, q, sig) \
(!p_trespass(p, q) || \
(!p_can(p, q, P_CAN_KILL, NULL) || \
((sig) == SIGCONT && (q)->p_session == (p)->p_session))
/*

View File

@ -217,7 +217,7 @@ ptrace(curp, uap)
if ((p = pfind(uap->pid)) == NULL)
return ESRCH;
}
if (!PRISON_CHECK(curp, p))
if (p_can(curp, p, P_CAN_SEE, NULL))
return (ESRCH);
/*
@ -237,16 +237,8 @@ ptrace(curp, uap)
if (p->p_flag & P_TRACED)
return EBUSY;
/* not owned by you, has done setuid (unless you're root) */
if ((p->p_cred->p_ruid != curp->p_cred->p_ruid) ||
(p->p_flag & P_SUGID)) {
if ((error = suser(curp)) != 0)
return error;
}
/* can't trace init when securelevel > 0 */
if (securelevel > 0 && p->p_pid == 1)
return EPERM;
if ((error = p_can(curp, p, P_CAN_DEBUG, NULL)))
return error;
/* OK */
break;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -137,7 +137,7 @@ procfs_open(ap)
p2 = PFIND(pfs->pfs_pid);
if (p2 == NULL)
return (ENOENT);
if (pfs->pfs_pid && !PRISON_CHECK(ap->a_p, p2))
if (pfs->pfs_pid && p_can(ap->a_p, p2, P_CAN_SEE, NULL))
return (ENOENT);
switch (pfs->pfs_type) {
@ -147,7 +147,7 @@ procfs_open(ap)
return (EBUSY);
p1 = ap->a_p;
if (p_trespass(p1, p2) &&
if (p_can(p1, p2, P_CAN_DEBUG, NULL) &&
!procfs_kmemaccess(p1))
return (EPERM);
@ -239,8 +239,11 @@ procfs_ioctl(ap)
return ENOTTY;
}
if (p_trespass(p, procp))
return EPERM;
if ((error = p_can(p, procp, P_CAN_DEBUG, NULL))) {
if (error == ESRCH)
error = ENOENT;
return (error);
}
switch (ap->a_command) {
case PIOCBIS:
@ -417,6 +420,9 @@ procfs_getattr(ap)
if (procp == 0 || procp->p_cred == NULL ||
procp->p_ucred == NULL)
return (ENOENT);
if (p_can(ap->a_p, procp, P_CAN_SEE, NULL))
return (ENOENT);
}
error = 0;
@ -612,16 +618,23 @@ procfs_access(ap)
struct proc *a_p;
} */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
struct proc *procp;
struct vattr *vap;
struct vattr vattr;
int error;
/*
* If you're the super-user,
* you always get access.
*/
if (ap->a_cred->cr_uid == 0)
return (0);
switch (pfs->pfs_type) {
case Proot:
case Pcurproc:
break;
default:
procp = PFIND(pfs->pfs_pid);
if (procp == NULL)
return (ENOENT);
if (p_can(ap->a_p, procp, P_CAN_SEE, NULL))
return (ENOENT);
}
vap = &vattr;
error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p);
@ -674,7 +687,7 @@ procfs_lookup(ap)
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
char *pname = cnp->cn_nameptr;
/* struct proc *curp = cnp->cn_proc; */
struct proc *curp = cnp->cn_proc;
struct proc_target *pt;
pid_t pid;
struct pfsnode *pfs;
@ -683,7 +696,8 @@ procfs_lookup(ap)
*vpp = NULL;
if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME ||
cnp->cn_nameiop == CREATE)
return (EROFS);
if (cnp->cn_namelen == 1 && *pname == '.') {
@ -710,6 +724,9 @@ procfs_lookup(ap)
if (p == 0)
break;
if (p_can(curp, p, P_CAN_SEE, NULL))
break;
return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
case Pproc:
@ -803,7 +820,7 @@ procfs_readdir(ap)
p = PFIND(pfs->pfs_pid);
if (p == NULL)
break;
if (!PRISON_CHECK(curproc, p))
if (p_can(curproc, p, P_CAN_SEE, NULL))
break;
for (pt = &proc_targets[i];
@ -838,7 +855,7 @@ procfs_readdir(ap)
int doingzomb = 0;
#endif
int pcnt = 0;
volatile struct proc *p = allproc.lh_first;
struct proc *p = allproc.lh_first;
for (; p && uio->uio_resid >= delen; i++, pcnt++) {
bzero((char *) dp, delen);
@ -866,11 +883,11 @@ procfs_readdir(ap)
p = p->p_list.le_next;
if (!p)
goto done;
if (!PRISON_CHECK(curproc, p))
if (p_can(curproc, p, P_CAN_SEE, NULL))
continue;
pcnt++;
}
while (!PRISON_CHECK(curproc, p)) {
while (p_can(curproc, p, P_CAN_SEE, NULL)) {
p = p->p_list.le_next;
if (!p)
goto done;

View File

@ -293,6 +293,11 @@ struct proc {
#define P_OLDMASK 0x2000000 /* need to restore mask before pause */
#define P_ALTSTACK 0x4000000 /* have alternate signal stack */
#define P_CAN_SEE 1
#define P_CAN_KILL 2
#define P_CAN_SCHED 3
#define P_CAN_DEBUG 4
/*
* MOVE TO ucred.h?
*
@ -414,6 +419,7 @@ extern int whichidqs; /* Bit mask summary of non-empty Q's. */
extern u_long ps_arg_cache_limit;
extern int ps_argsopen;
extern int ps_showallprocs;
struct proc *pfind __P((pid_t)); /* Find process by id. */
struct pgrp *pgfind __P((pid_t)); /* Find process group by id. */
@ -429,15 +435,18 @@ int inferior __P((struct proc *p));
int leavepgrp __P((struct proc *p));
void mi_switch __P((void));
void procinit __P((void));
int p_trespass __P((struct proc *p1, struct proc *p2));
int p_can __P((const struct proc *p1, const struct proc *p2, int operation,
int *privused));
void resetpriority __P((struct proc *));
int roundrobin_interval __P((void));
void schedclock __P((struct proc *));
void setrunnable __P((struct proc *));
void setrunqueue __P((struct proc *));
void sleepinit __P((void));
int suser __P((struct proc *));
int suser_xxx __P((struct ucred *cred, struct proc *proc, int flag));
int suser __P((const struct proc *));
int suser_xxx __P((const struct ucred *cred, const struct proc *proc,
int flag));
void remrunqueue __P((struct proc *));
void cpu_switch __P((struct proc *));
void unsleep __P((struct proc *));