#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/vfs.h>
#include <sys/cred.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <sys/errno.h>
#include <sys/kmem.h>
#include <sys/user.h>
#include <sys/buf.h>
#include <sys/var.h>
#include <sys/conf.h>
#include <sys/debug.h>
#include <sys/proc.h>
#include <sys/signal.h>
#include <sys/siginfo.h>
#include <sys/acct.h>
#include <sys/procset.h>
#include <sys/cmn_err.h>
#include <sys/fault.h>
#include <sys/syscall.h>
#include <sys/ucontext.h>
#include <sys/procfs.h>
#include <sys/session.h>
#include <sys/task.h>
#include <sys/project.h>
#include <sys/pool.h>
#include <sys/zone.h>
#include <sys/contract/process_impl.h>
id_t getmyid(idtype_t);
int checkprocset(procset_t *);
static kthread_t *getlwpptr(id_t);
int procinset(proc_t *, procset_t *);
static int lwpinset(proc_t *, procset_t *, kthread_t *, int *);
int
dotoprocs(procset_t *psp, int (*funcp)(), char *arg)
{
proc_t *prp;
int error;
int nfound;
proc_t *lastprp;
ASSERT(funcp != NULL);
error = checkprocset(psp);
if (error) {
return (error);
}
mutex_enter(&pidlock);
if (psp->p_lid == P_MYID) {
psp->p_lid = getmyid(psp->p_lidtype);
}
if (psp->p_rid == P_MYID) {
psp->p_rid = getmyid(psp->p_ridtype);
}
if (psp->p_op == POP_AND) {
if (((psp->p_lidtype == P_PID) && (psp->p_ridtype == P_ALL)) ||
((psp->p_ridtype == P_PID) && (psp->p_lidtype == P_ALL))) {
id_t pid;
pid = (psp->p_lidtype == P_PID) ?
psp->p_lid : psp->p_rid;
if (((prp = prfind((pid_t)pid)) == NULL) ||
(prp->p_stat == SIDL || prp->p_stat == SZOMB ||
prp->p_tlist == NULL || prp->p_flag & SSYS)) {
mutex_exit(&pidlock);
return (ESRCH);
}
error = (*funcp)(prp, arg);
mutex_exit(&pidlock);
if (error == -1)
error = 0;
return (error);
}
}
nfound = 0;
error = 0;
for (prp = practive; prp != NULL; prp = prp->p_next) {
if (!HASZONEACCESS(curproc, prp->p_zone->zone_id))
continue;
if (prp->p_stat == SIDL || prp->p_stat == SZOMB)
continue;
mutex_enter(&prp->p_lock);
if (prp->p_flag & SSYS || prp->p_tlist == NULL ||
procinset(prp, psp) == 0) {
mutex_exit(&prp->p_lock);
} else {
mutex_exit(&prp->p_lock);
nfound++;
lastprp = prp;
if (prp != proc_init) {
error = (*funcp)(prp, arg);
if (error == -1) {
mutex_exit(&pidlock);
return (0);
} else if (error) {
mutex_exit(&pidlock);
return (error);
}
}
}
}
if (nfound == 0) {
mutex_exit(&pidlock);
return (ESRCH);
}
if (nfound == 1 && lastprp == proc_init)
error = (*funcp)(lastprp, arg);
if (error == -1)
error = 0;
mutex_exit(&pidlock);
return (error);
}
int
checkprocset(procset_t *psp)
{
switch (psp->p_lidtype) {
case P_LWPID:
case P_PID:
case P_PPID:
case P_PGID:
case P_SID:
case P_TASKID:
case P_CID:
case P_UID:
case P_GID:
case P_PROJID:
case P_POOLID:
case P_ZONEID:
case P_CTID:
case P_ALL:
break;
default:
return (EINVAL);
}
switch (psp->p_ridtype) {
case P_LWPID:
case P_PID:
case P_PPID:
case P_PGID:
case P_SID:
case P_TASKID:
case P_CID:
case P_UID:
case P_GID:
case P_PROJID:
case P_POOLID:
case P_ZONEID:
case P_CTID:
case P_ALL:
break;
default:
return (EINVAL);
}
switch (psp->p_op) {
case POP_DIFF:
case POP_AND:
case POP_OR:
case POP_XOR:
break;
default:
return (EINVAL);
}
return (0);
}
int
procinset(proc_t *pp, procset_t *psp)
{
int loperand = 0;
int roperand = 0;
int lwplinproc = 0;
int lwprinproc = 0;
kthread_t *tp;
ASSERT(MUTEX_HELD(&pp->p_lock));
switch (psp->p_lidtype) {
case P_LWPID:
if (pp == ttoproc(curthread))
if (getlwpptr(psp->p_lid) != NULL)
lwplinproc++;
break;
case P_PID:
if (pp->p_pid == psp->p_lid)
loperand++;
break;
case P_PPID:
if (pp->p_ppid == psp->p_lid)
loperand++;
break;
case P_PGID:
if (pp->p_pgrp == psp->p_lid)
loperand++;
break;
case P_SID:
mutex_enter(&pp->p_splock);
if (pp->p_sessp->s_sid == psp->p_lid)
loperand++;
mutex_exit(&pp->p_splock);
break;
case P_CID:
tp = proctot(pp);
if (tp == NULL)
return (0);
if (tp->t_cid == psp->p_lid)
loperand++;
break;
case P_TASKID:
if (pp->p_task->tk_tkid == psp->p_lid)
loperand++;
break;
case P_UID:
mutex_enter(&pp->p_crlock);
if (crgetuid(pp->p_cred) == psp->p_lid)
loperand++;
mutex_exit(&pp->p_crlock);
break;
case P_GID:
mutex_enter(&pp->p_crlock);
if (crgetgid(pp->p_cred) == psp->p_lid)
loperand++;
mutex_exit(&pp->p_crlock);
break;
case P_PROJID:
if (pp->p_task->tk_proj->kpj_id == psp->p_lid)
loperand++;
break;
case P_POOLID:
if (pp->p_pool->pool_id == psp->p_lid)
loperand++;
break;
case P_ZONEID:
if (pp->p_zone->zone_id == psp->p_lid)
loperand++;
break;
case P_CTID:
if (PRCTID(pp) == psp->p_lid)
loperand++;
break;
case P_ALL:
loperand++;
break;
default:
#ifdef DEBUG
cmn_err(CE_WARN, "procinset called with bad set");
return (0);
#else
return (0);
#endif
}
switch (psp->p_ridtype) {
case P_LWPID:
if (pp == ttoproc(curthread))
if (getlwpptr(psp->p_rid) != NULL)
lwprinproc++;
break;
case P_PID:
if (pp->p_pid == psp->p_rid)
roperand++;
break;
case P_PPID:
if (pp->p_ppid == psp->p_rid)
roperand++;
break;
case P_PGID:
if (pp->p_pgrp == psp->p_rid)
roperand++;
break;
case P_SID:
mutex_enter(&pp->p_splock);
if (pp->p_sessp->s_sid == psp->p_rid)
roperand++;
mutex_exit(&pp->p_splock);
break;
case P_TASKID:
if (pp->p_task->tk_tkid == psp->p_rid)
roperand++;
break;
case P_CID:
tp = proctot(pp);
if (tp == NULL)
return (0);
if (tp->t_cid == psp->p_rid)
roperand++;
break;
case P_UID:
mutex_enter(&pp->p_crlock);
if (crgetuid(pp->p_cred) == psp->p_rid)
roperand++;
mutex_exit(&pp->p_crlock);
break;
case P_GID:
mutex_enter(&pp->p_crlock);
if (crgetgid(pp->p_cred) == psp->p_rid)
roperand++;
mutex_exit(&pp->p_crlock);
break;
case P_PROJID:
if (pp->p_task->tk_proj->kpj_id == psp->p_rid)
roperand++;
break;
case P_POOLID:
if (pp->p_pool->pool_id == psp->p_rid)
roperand++;
break;
case P_ZONEID:
if (pp->p_zone->zone_id == psp->p_rid)
roperand++;
break;
case P_CTID:
if (PRCTID(pp) == psp->p_rid)
roperand++;
break;
case P_ALL:
roperand++;
break;
default:
#ifdef DEBUG
cmn_err(CE_WARN, "procinset called with bad set");
return (0);
#else
return (0);
#endif
}
switch (psp->p_op) {
case POP_DIFF:
if (loperand && !lwprinproc && !roperand)
return (1);
else
return (0);
case POP_AND:
if (loperand && roperand)
return (1);
else
return (0);
case POP_OR:
if (loperand || roperand)
return (1);
else
return (0);
case POP_XOR:
if ((loperand && !lwprinproc && !roperand) ||
(roperand && !lwplinproc && !loperand))
return (1);
else
return (0);
default:
#ifdef DEBUG
cmn_err(CE_WARN, "procinset called with bad set");
return (0);
#else
return (0);
#endif
}
}
int
lwpinset(proc_t *pp, procset_t *psp, kthread_t *tp, int *done)
{
int loperand = 0;
int roperand = 0;
int lwplinset = 0;
int lwprinset = 0;
ASSERT(ttoproc(tp) == pp);
if (proctot(pp)->t_cid == 0) {
return (0);
}
switch (psp->p_lidtype) {
case P_LWPID:
if (tp->t_tid == psp->p_lid)
lwplinset ++;
break;
case P_PID:
if (pp->p_pid == psp->p_lid)
loperand++;
break;
case P_PPID:
if (pp->p_ppid == psp->p_lid)
loperand++;
break;
case P_PGID:
if (pp->p_pgrp == psp->p_lid)
loperand++;
break;
case P_SID:
mutex_enter(&pp->p_splock);
if (pp->p_sessp->s_sid == psp->p_lid)
loperand++;
mutex_exit(&pp->p_splock);
break;
case P_TASKID:
if (pp->p_task->tk_tkid == psp->p_lid)
loperand++;
break;
case P_CID:
if (tp->t_cid == psp->p_lid)
loperand++;
break;
case P_UID:
mutex_enter(&pp->p_crlock);
if (crgetuid(pp->p_cred) == psp->p_lid)
loperand++;
mutex_exit(&pp->p_crlock);
break;
case P_GID:
mutex_enter(&pp->p_crlock);
if (crgetgid(pp->p_cred) == psp->p_lid)
loperand++;
mutex_exit(&pp->p_crlock);
break;
case P_PROJID:
if (pp->p_task->tk_proj->kpj_id == psp->p_lid)
loperand++;
break;
case P_POOLID:
if (pp->p_pool->pool_id == psp->p_lid)
loperand++;
break;
case P_ZONEID:
if (pp->p_zone->zone_id == psp->p_lid)
loperand++;
break;
case P_CTID:
if (PRCTID(pp) == psp->p_lid)
loperand++;
break;
case P_ALL:
loperand++;
break;
default:
#ifdef DEBUG
cmn_err(CE_WARN, "lwpinset called with bad set");
return (0);
#else
return (0);
#endif
}
switch (psp->p_ridtype) {
case P_LWPID:
if (tp->t_tid == psp->p_rid)
lwprinset ++;
break;
case P_PID:
if (pp->p_pid == psp->p_rid)
roperand++;
break;
case P_PPID:
if (pp->p_ppid == psp->p_rid)
roperand++;
break;
case P_PGID:
if (pp->p_pgrp == psp->p_rid)
roperand++;
break;
case P_SID:
mutex_enter(&pp->p_splock);
if (pp->p_sessp->s_sid == psp->p_rid)
roperand++;
mutex_exit(&pp->p_splock);
break;
case P_TASKID:
if (pp->p_task->tk_tkid == psp->p_rid)
roperand++;
break;
case P_CID:
if (tp->t_cid == psp->p_rid)
roperand++;
break;
case P_UID:
mutex_enter(&pp->p_crlock);
if (crgetuid(pp->p_cred) == psp->p_rid)
roperand++;
mutex_exit(&pp->p_crlock);
break;
case P_GID:
mutex_enter(&pp->p_crlock);
if (crgetgid(pp->p_cred) == psp->p_rid)
roperand++;
mutex_exit(&pp->p_crlock);
break;
case P_PROJID:
if (pp->p_task->tk_proj->kpj_id == psp->p_rid)
roperand++;
break;
case P_POOLID:
if (pp->p_pool->pool_id == psp->p_rid)
roperand++;
break;
case P_ZONEID:
if (pp->p_zone->zone_id == psp->p_rid)
roperand++;
break;
case P_CTID:
if (PRCTID(pp) == psp->p_rid)
roperand++;
break;
case P_ALL:
roperand++;
break;
default:
#ifdef DEBUG
cmn_err(CE_WARN, "lwpinset called with bad set");
return (0);
#else
return (0);
#endif
}
if (lwplinset && lwprinset)
*done = 1;
switch (psp->p_op) {
case POP_DIFF:
if ((loperand || lwplinset) && !(lwprinset || roperand))
return (1);
else
return (0);
case POP_AND:
if ((loperand || lwplinset) && (roperand || lwprinset))
return (1);
else
return (0);
case POP_OR:
if (loperand || roperand || lwplinset || lwprinset)
return (1);
else
return (0);
case POP_XOR:
if (((loperand || lwplinset) &&
!(lwprinset || roperand)) ||
((roperand || lwprinset) &&
!(lwplinset || loperand)))
return (1);
else
return (0);
default:
#ifdef DEBUG
cmn_err(CE_WARN, "lwpinset called with bad set");
return (0);
#else
return (0);
#endif
}
}
boolean_t
cur_inset_only(procset_t *psp)
{
if (((psp->p_lidtype == P_PID &&
(psp->p_lid == P_MYID ||
psp->p_lid == ttoproc(curthread)->p_pid)) ||
((psp->p_lidtype == P_LWPID) &&
(psp->p_lid == P_MYID ||
psp->p_lid == curthread->t_tid))) &&
psp->p_op == POP_AND && psp->p_ridtype == P_ALL)
return (B_TRUE);
if (((psp->p_ridtype == P_PID &&
(psp->p_rid == P_MYID ||
psp->p_rid == ttoproc(curthread)->p_pid)) ||
((psp->p_ridtype == P_LWPID) &&
(psp->p_rid == P_MYID ||
psp->p_rid == curthread->t_tid))) &&
psp->p_op == POP_AND && psp->p_lidtype == P_ALL)
return (B_TRUE);
return (B_FALSE);
}
id_t
getmyid(idtype_t idtype)
{
proc_t *pp;
uid_t uid;
gid_t gid;
pid_t sid;
pp = ttoproc(curthread);
switch (idtype) {
case P_LWPID:
return (curthread->t_tid);
case P_PID:
return (pp->p_pid);
case P_PPID:
return (pp->p_ppid);
case P_PGID:
return (pp->p_pgrp);
case P_SID:
mutex_enter(&pp->p_splock);
sid = pp->p_sessp->s_sid;
mutex_exit(&pp->p_splock);
return (sid);
case P_TASKID:
return (pp->p_task->tk_tkid);
case P_CID:
return (curthread->t_cid);
case P_UID:
mutex_enter(&pp->p_crlock);
uid = crgetuid(pp->p_cred);
mutex_exit(&pp->p_crlock);
return (uid);
case P_GID:
mutex_enter(&pp->p_crlock);
gid = crgetgid(pp->p_cred);
mutex_exit(&pp->p_crlock);
return (gid);
case P_PROJID:
return (pp->p_task->tk_proj->kpj_id);
case P_POOLID:
return (pp->p_pool->pool_id);
case P_ZONEID:
return (pp->p_zone->zone_id);
case P_CTID:
return (PRCTID(pp));
case P_ALL:
return (0);
default:
return (-1);
}
}
static kthread_t *
getlwpptr(id_t id)
{
proc_t *p;
kthread_t *t;
ASSERT(MUTEX_HELD(&(ttoproc(curthread)->p_lock)));
if (id == P_MYID)
t = curthread;
else {
p = ttoproc(curthread);
t = idtot(p, id);
}
return (t);
}
int
dotolwp(procset_t *psp, int (*funcp)(), char *arg)
{
int error = 0;
int nfound = 0;
kthread_t *tp;
proc_t *pp;
int done = 0;
error = checkprocset(psp);
if (error) {
return (error);
}
mutex_enter(&pidlock);
if (psp->p_lid == P_MYID) {
psp->p_lid = getmyid(psp->p_lidtype);
}
if (psp->p_rid == P_MYID) {
psp->p_rid = getmyid(psp->p_ridtype);
}
pp = ttoproc(curthread);
mutex_enter(&pp->p_lock);
if (procinset(pp, psp) ||
(tp = pp->p_tlist) == NULL) {
mutex_exit(&pp->p_lock);
mutex_exit(&pidlock);
return (0);
}
do {
if (lwpinset(pp, psp, tp, &done)) {
nfound ++;
error = (*funcp)(arg, tp);
if (error) {
mutex_exit(&pp->p_lock);
mutex_exit(&pidlock);
return (error);
}
}
} while (((tp = tp->t_forw) != pp->p_tlist) && !done);
if (nfound == 0) {
mutex_exit(&pp->p_lock);
mutex_exit(&pidlock);
return (ESRCH);
}
mutex_exit(&pidlock);
return (error);
}