xref: /illumos-gate/usr/src/uts/common/os/procset.c (revision 2aeafac3612e19716bf8164f89c3c9196342979c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 #include <sys/types.h>
30 #include <sys/sysmacros.h>
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/vfs.h>
34 #include <sys/cred.h>
35 #include <sys/vnode.h>
36 #include <sys/file.h>
37 #include <sys/errno.h>
38 #include <sys/kmem.h>
39 #include <sys/user.h>
40 #include <sys/buf.h>
41 #include <sys/var.h>
42 #include <sys/conf.h>
43 #include <sys/debug.h>
44 #include <sys/proc.h>
45 #include <sys/signal.h>
46 #include <sys/siginfo.h>
47 #include <sys/acct.h>
48 #include <sys/procset.h>
49 #include <sys/cmn_err.h>
50 #include <sys/fault.h>
51 #include <sys/syscall.h>
52 #include <sys/ucontext.h>
53 #include <sys/procfs.h>
54 #include <sys/session.h>
55 #include <sys/task.h>
56 #include <sys/project.h>
57 #include <sys/pool.h>
58 #include <sys/zone.h>
59 #include <sys/contract/process_impl.h>
60 
61 id_t	getmyid(idtype_t);
62 int	checkprocset(procset_t *);
63 static	kthread_t *getlwpptr(id_t);
64 int	procinset(proc_t *, procset_t *);
65 static	int lwpinset(proc_t *, procset_t *, kthread_t *, int *);
66 
67 /*
68  * The dotoprocs function locates the process(es) specified
69  * by the procset structure pointed to by psp.  funcp points to a
70  * function which dotoprocs will call for each process in the
71  * specified set.  The arguments to this function will be a pointer
72  * to the current process from the set and arg.
73  * If the called function returns -1, it means that processing of the
74  * procset should stop and a normal (non-error) return should be made
75  * to the caller of dotoprocs.
76  * If the called function returns any other non-zero value the search
77  * is terminated and the function's return value is returned to
78  * the caller of dotoprocs.  This will normally be an error code.
79  * Otherwise, dotoprocs will return zero after processing the entire
80  * process set unless no processes were found in which case ESRCH will
81  * be returned.
82  */
83 int
84 dotoprocs(procset_t *psp, int (*funcp)(), char *arg)
85 {
86 	proc_t	*prp;	/* A process from the set */
87 	int	error;
88 	int	nfound;	/* Nbr of processes found.	*/
89 	proc_t	*lastprp;	/* Last proc found.	*/
90 
91 	ASSERT(funcp != NULL);
92 
93 	/*
94 	 * Check that the procset_t is valid.
95 	 */
96 	error = checkprocset(psp);
97 	if (error) {
98 		return (error);
99 	}
100 	/*
101 	 * Check for the special value P_MYID in either operand
102 	 * and replace it with the correct value.  We don't check
103 	 * for an error return from getmyid() because the idtypes
104 	 * have been validated by the checkprocset() call above.
105 	 */
106 	mutex_enter(&pidlock);
107 	if (psp->p_lid == P_MYID) {
108 		psp->p_lid = getmyid(psp->p_lidtype);
109 	}
110 	if (psp->p_rid == P_MYID) {
111 		psp->p_rid = getmyid(psp->p_ridtype);
112 	}
113 
114 	/*
115 	 * If psp only acts on a single proc, we can reduce pidlock hold time
116 	 * by avoiding a needless scan of the entire proc list.  Although
117 	 * there are many procset_t combinations which might boil down to a
118 	 * single proc, the most common case is an AND operation where one
119 	 * side is a specific pid, and the other side is P_ALL, so that is
120 	 * the case for which we will provide a fast path.  Other cases could
121 	 * be added in a similar fashion if they were to become significant
122 	 * pidlock bottlenecks.
123 	 *
124 	 * Perform the check symmetrically:  either the left or right side may
125 	 * specify a pid, with the opposite side being 'all'.
126 	 */
127 	if (psp->p_op == POP_AND) {
128 		if (((psp->p_lidtype == P_PID) && (psp->p_ridtype == P_ALL)) ||
129 		    ((psp->p_ridtype == P_PID) && (psp->p_lidtype == P_ALL))) {
130 			id_t pid;
131 
132 			pid = (psp->p_lidtype == P_PID) ?
133 			    psp->p_lid : psp->p_rid;
134 			if (((prp = prfind((pid_t)pid)) == NULL) ||
135 			    (prp->p_stat == SIDL || prp->p_stat == SZOMB ||
136 			    prp->p_tlist == NULL || prp->p_flag & SSYS)) {
137 				/*
138 				 * Specified proc doesn't exist or should
139 				 * not be operated on.
140 				 * Don't need to make HASZONEACCESS check
141 				 * here since prfind() takes care of that.
142 				 */
143 				mutex_exit(&pidlock);
144 				return (ESRCH);
145 			}
146 			/*
147 			 * Operate only on the specified proc.  It's okay
148 			 * if it's init.
149 			 */
150 			error = (*funcp)(prp, arg);
151 			mutex_exit(&pidlock);
152 			if (error == -1)
153 				error = 0;
154 			return (error);
155 		}
156 	}
157 
158 	nfound = 0;
159 	error  = 0;
160 
161 	for (prp = practive; prp != NULL; prp = prp->p_next) {
162 		/*
163 		 * If caller is in a non-global zone, skip processes
164 		 * in other zones.
165 		 */
166 		if (!HASZONEACCESS(curproc, prp->p_zone->zone_id))
167 			continue;
168 
169 		/*
170 		 * Ignore this process if it's coming or going,
171 		 * if it's a system process or if it's not in
172 		 * the given procset_t.
173 		 */
174 		if (prp->p_stat == SIDL || prp->p_stat == SZOMB)
175 			continue;
176 
177 		mutex_enter(&prp->p_lock);
178 		if (prp->p_flag & SSYS || prp->p_tlist == NULL ||
179 		    procinset(prp, psp) == 0) {
180 			mutex_exit(&prp->p_lock);
181 		} else {
182 			mutex_exit(&prp->p_lock);
183 			nfound++;
184 			lastprp = prp;
185 			if (prp != proc_init) {
186 				error = (*funcp)(prp, arg);
187 				if (error == -1) {
188 					mutex_exit(&pidlock);
189 					return (0);
190 				} else if (error) {
191 					mutex_exit(&pidlock);
192 					return (error);
193 				}
194 			}
195 		}
196 	}
197 	if (nfound == 0) {
198 		mutex_exit(&pidlock);
199 		return (ESRCH);
200 	}
201 	if (nfound == 1 && lastprp == proc_init)
202 		error = (*funcp)(lastprp, arg);
203 	if (error == -1)
204 		error = 0;
205 	mutex_exit(&pidlock);
206 	return (error);
207 }
208 
209 /*
210  * Check if a procset_t is valid.  Return zero or an errno.
211  */
212 int
213 checkprocset(procset_t *psp)
214 {
215 	switch (psp->p_lidtype) {
216 	case P_LWPID:
217 	case P_PID:
218 	case P_PPID:
219 	case P_PGID:
220 	case P_SID:
221 	case P_TASKID:
222 	case P_CID:
223 	case P_UID:
224 	case P_GID:
225 	case P_PROJID:
226 	case P_POOLID:
227 	case P_ZONEID:
228 	case P_CTID:
229 	case P_ALL:
230 		break;
231 	default:
232 		return (EINVAL);
233 	}
234 
235 	switch (psp->p_ridtype) {
236 	case P_LWPID:
237 	case P_PID:
238 	case P_PPID:
239 	case P_PGID:
240 	case P_SID:
241 	case P_TASKID:
242 	case P_CID:
243 	case P_UID:
244 	case P_GID:
245 	case P_PROJID:
246 	case P_POOLID:
247 	case P_ZONEID:
248 	case P_CTID:
249 	case P_ALL:
250 		break;
251 	default:
252 		return (EINVAL);
253 	}
254 
255 	switch (psp->p_op) {
256 	case POP_DIFF:
257 	case POP_AND:
258 	case POP_OR:
259 	case POP_XOR:
260 		break;
261 	default:
262 		return (EINVAL);
263 	}
264 
265 	return (0);
266 }
267 
268 /*
269  * procinset returns 1 if the process pointed to by pp is in the process
270  * set specified by psp, otherwise 0 is returned. If either process set operand
271  * has type P_CID and pp refers to a process that is exiting, by which we mean
272  * that its p_tlist is NULL, then procinset will return 0. pp's p_lock must be
273  * held across the call to this function. The caller should ensure that the
274  * process does not belong to the SYS scheduling class.
275  *
276  * This function expects to be called with a valid procset_t.
277  * The set should be checked using checkprocset() before calling
278  * this function.
279  */
280 int
281 procinset(proc_t *pp, procset_t *psp)
282 {
283 	int	loperand = 0;
284 	int	roperand = 0;
285 	int	lwplinproc = 0;
286 	int	lwprinproc = 0;
287 	kthread_t	*tp;
288 
289 	ASSERT(MUTEX_HELD(&pp->p_lock));
290 
291 	switch (psp->p_lidtype) {
292 
293 	case P_LWPID:
294 		if (pp == ttoproc(curthread))
295 			if (getlwpptr(psp->p_lid) != NULL)
296 				lwplinproc++;
297 		break;
298 
299 	case P_PID:
300 		if (pp->p_pid == psp->p_lid)
301 			loperand++;
302 		break;
303 
304 	case P_PPID:
305 		if (pp->p_ppid == psp->p_lid)
306 			loperand++;
307 		break;
308 
309 	case P_PGID:
310 		if (pp->p_pgrp == psp->p_lid)
311 			loperand++;
312 		break;
313 
314 	case P_SID:
315 		mutex_enter(&pp->p_splock);
316 		if (pp->p_sessp->s_sid == psp->p_lid)
317 			loperand++;
318 		mutex_exit(&pp->p_splock);
319 		break;
320 
321 	case P_CID:
322 		tp = proctot(pp);
323 		if (tp == NULL)
324 			return (0);
325 		if (tp->t_cid == psp->p_lid)
326 			loperand++;
327 		break;
328 
329 	case P_TASKID:
330 		if (pp->p_task->tk_tkid == psp->p_lid)
331 			loperand++;
332 		break;
333 
334 	case P_UID:
335 		mutex_enter(&pp->p_crlock);
336 		if (crgetuid(pp->p_cred) == psp->p_lid)
337 			loperand++;
338 		mutex_exit(&pp->p_crlock);
339 		break;
340 
341 	case P_GID:
342 		mutex_enter(&pp->p_crlock);
343 		if (crgetgid(pp->p_cred) == psp->p_lid)
344 			loperand++;
345 		mutex_exit(&pp->p_crlock);
346 		break;
347 
348 	case P_PROJID:
349 		if (pp->p_task->tk_proj->kpj_id == psp->p_lid)
350 			loperand++;
351 		break;
352 
353 	case P_POOLID:
354 		if (pp->p_pool->pool_id == psp->p_lid)
355 			loperand++;
356 		break;
357 
358 	case P_ZONEID:
359 		if (pp->p_zone->zone_id == psp->p_lid)
360 			loperand++;
361 		break;
362 
363 	case P_CTID:
364 		if (PRCTID(pp) == psp->p_lid)
365 			loperand++;
366 		break;
367 
368 	case P_ALL:
369 		loperand++;
370 		break;
371 
372 	default:
373 #ifdef DEBUG
374 		cmn_err(CE_WARN, "procinset called with bad set");
375 		return (0);
376 #else
377 		return (0);
378 #endif
379 	}
380 
381 	switch (psp->p_ridtype) {
382 
383 	case P_LWPID:
384 		if (pp == ttoproc(curthread))
385 			if (getlwpptr(psp->p_rid) != NULL)
386 				lwprinproc++;
387 		break;
388 
389 	case P_PID:
390 		if (pp->p_pid == psp->p_rid)
391 			roperand++;
392 		break;
393 
394 	case P_PPID:
395 		if (pp->p_ppid == psp->p_rid)
396 			roperand++;
397 		break;
398 
399 	case P_PGID:
400 		if (pp->p_pgrp == psp->p_rid)
401 			roperand++;
402 		break;
403 
404 	case P_SID:
405 		mutex_enter(&pp->p_splock);
406 		if (pp->p_sessp->s_sid == psp->p_rid)
407 			roperand++;
408 		mutex_exit(&pp->p_splock);
409 		break;
410 
411 	case P_TASKID:
412 		if (pp->p_task->tk_tkid == psp->p_rid)
413 			roperand++;
414 		break;
415 
416 	case P_CID:
417 		tp = proctot(pp);
418 		if (tp == NULL)
419 			return (0);
420 		if (tp->t_cid == psp->p_rid)
421 			roperand++;
422 		break;
423 
424 	case P_UID:
425 		mutex_enter(&pp->p_crlock);
426 		if (crgetuid(pp->p_cred) == psp->p_rid)
427 			roperand++;
428 		mutex_exit(&pp->p_crlock);
429 		break;
430 
431 	case P_GID:
432 		mutex_enter(&pp->p_crlock);
433 		if (crgetgid(pp->p_cred) == psp->p_rid)
434 			roperand++;
435 		mutex_exit(&pp->p_crlock);
436 		break;
437 
438 	case P_PROJID:
439 		if (pp->p_task->tk_proj->kpj_id == psp->p_rid)
440 			roperand++;
441 		break;
442 
443 	case P_POOLID:
444 		if (pp->p_pool->pool_id == psp->p_rid)
445 			roperand++;
446 		break;
447 
448 	case P_ZONEID:
449 		if (pp->p_zone->zone_id == psp->p_rid)
450 			roperand++;
451 		break;
452 
453 	case P_CTID:
454 		if (PRCTID(pp) == psp->p_rid)
455 			roperand++;
456 		break;
457 
458 	case P_ALL:
459 		roperand++;
460 		break;
461 
462 	default:
463 #ifdef DEBUG
464 		cmn_err(CE_WARN, "procinset called with bad set");
465 		return (0);
466 #else
467 		return (0);
468 #endif
469 	}
470 
471 	switch (psp->p_op) {
472 
473 	case POP_DIFF:
474 		if (loperand && !lwprinproc && !roperand)
475 			return (1);
476 		else
477 			return (0);
478 
479 	case POP_AND:
480 		if (loperand && roperand)
481 			return (1);
482 		else
483 			return (0);
484 
485 	case POP_OR:
486 		if (loperand || roperand)
487 			return (1);
488 		else
489 			return (0);
490 
491 	case POP_XOR:
492 		if ((loperand && !lwprinproc && !roperand) ||
493 		    (roperand && !lwplinproc && !loperand))
494 			return (1);
495 		else
496 			return (0);
497 
498 	default:
499 #ifdef DEBUG
500 		cmn_err(CE_WARN, "procinset called with bad set");
501 		return (0);
502 #else
503 		return (0);
504 #endif
505 	}
506 	/* NOTREACHED */
507 }
508 
509 /*
510  * lwpinset returns 1 if the thread pointed to
511  * by tp is in the process set specified by psp and is not in
512  * the sys scheduling class - otherwise 0 is returned.
513  *
514  * This function expects to be called with a valid procset_t.
515  * The set should be checked using checkprocset() before calling
516  * this function.
517  */
518 int
519 lwpinset(proc_t *pp, procset_t *psp, kthread_t *tp, int *done)
520 {
521 	int	loperand = 0;
522 	int	roperand = 0;
523 	int	lwplinset  = 0;
524 	int	lwprinset  = 0;
525 
526 	ASSERT(ttoproc(tp) == pp);
527 
528 	/*
529 	 * If process is in the sys class return (0).
530 	 */
531 	if (proctot(pp)->t_cid == 0) {
532 		return (0);
533 	}
534 
535 	switch (psp->p_lidtype) {
536 
537 	case P_LWPID:
538 		if (tp->t_tid == psp->p_lid)
539 			lwplinset ++;
540 		break;
541 
542 	case P_PID:
543 		if (pp->p_pid == psp->p_lid)
544 			loperand++;
545 		break;
546 
547 	case P_PPID:
548 		if (pp->p_ppid == psp->p_lid)
549 			loperand++;
550 		break;
551 
552 	case P_PGID:
553 		if (pp->p_pgrp == psp->p_lid)
554 			loperand++;
555 		break;
556 
557 	case P_SID:
558 		mutex_enter(&pp->p_splock);
559 		if (pp->p_sessp->s_sid == psp->p_lid)
560 			loperand++;
561 		mutex_exit(&pp->p_splock);
562 		break;
563 
564 	case P_TASKID:
565 		if (pp->p_task->tk_tkid == psp->p_lid)
566 			loperand++;
567 		break;
568 
569 	case P_CID:
570 		if (tp->t_cid == psp->p_lid)
571 			loperand++;
572 		break;
573 
574 	case P_UID:
575 		mutex_enter(&pp->p_crlock);
576 		if (crgetuid(pp->p_cred) == psp->p_lid)
577 			loperand++;
578 		mutex_exit(&pp->p_crlock);
579 		break;
580 
581 	case P_GID:
582 		mutex_enter(&pp->p_crlock);
583 		if (crgetgid(pp->p_cred) == psp->p_lid)
584 			loperand++;
585 		mutex_exit(&pp->p_crlock);
586 		break;
587 
588 	case P_PROJID:
589 		if (pp->p_task->tk_proj->kpj_id == psp->p_lid)
590 			loperand++;
591 		break;
592 
593 	case P_POOLID:
594 		if (pp->p_pool->pool_id == psp->p_lid)
595 			loperand++;
596 		break;
597 
598 	case P_ZONEID:
599 		if (pp->p_zone->zone_id == psp->p_lid)
600 			loperand++;
601 		break;
602 
603 	case P_CTID:
604 		if (PRCTID(pp) == psp->p_lid)
605 			loperand++;
606 		break;
607 
608 	case P_ALL:
609 		loperand++;
610 		break;
611 
612 	default:
613 #ifdef DEBUG
614 		cmn_err(CE_WARN, "lwpinset called with bad set");
615 		return (0);
616 #else
617 		return (0);
618 #endif
619 	}
620 
621 	switch (psp->p_ridtype) {
622 
623 	case P_LWPID:
624 		if (tp->t_tid == psp->p_rid)
625 			lwprinset ++;
626 		break;
627 
628 	case P_PID:
629 		if (pp->p_pid == psp->p_rid)
630 			roperand++;
631 		break;
632 
633 	case P_PPID:
634 		if (pp->p_ppid == psp->p_rid)
635 			roperand++;
636 		break;
637 
638 	case P_PGID:
639 		if (pp->p_pgrp == psp->p_rid)
640 			roperand++;
641 		break;
642 
643 	case P_SID:
644 		mutex_enter(&pp->p_splock);
645 		if (pp->p_sessp->s_sid == psp->p_rid)
646 			roperand++;
647 		mutex_exit(&pp->p_splock);
648 		break;
649 
650 	case P_TASKID:
651 		if (pp->p_task->tk_tkid == psp->p_rid)
652 			roperand++;
653 		break;
654 
655 	case P_CID:
656 		if (tp->t_cid == psp->p_rid)
657 			roperand++;
658 		break;
659 
660 	case P_UID:
661 		mutex_enter(&pp->p_crlock);
662 		if (crgetuid(pp->p_cred) == psp->p_rid)
663 			roperand++;
664 		mutex_exit(&pp->p_crlock);
665 		break;
666 
667 	case P_GID:
668 		mutex_enter(&pp->p_crlock);
669 		if (crgetgid(pp->p_cred) == psp->p_rid)
670 			roperand++;
671 		mutex_exit(&pp->p_crlock);
672 		break;
673 
674 	case P_PROJID:
675 		if (pp->p_task->tk_proj->kpj_id == psp->p_rid)
676 			roperand++;
677 		break;
678 
679 	case P_POOLID:
680 		if (pp->p_pool->pool_id == psp->p_rid)
681 			roperand++;
682 		break;
683 
684 	case P_ZONEID:
685 		if (pp->p_zone->zone_id == psp->p_rid)
686 			roperand++;
687 		break;
688 
689 	case P_CTID:
690 		if (PRCTID(pp) == psp->p_rid)
691 			roperand++;
692 		break;
693 
694 	case P_ALL:
695 		roperand++;
696 		break;
697 
698 	default:
699 #ifdef DEBUG
700 		cmn_err(CE_WARN, "lwpinset called with bad set");
701 		return (0);
702 #else
703 		return (0);
704 #endif
705 	}
706 
707 	if (lwplinset && lwprinset)
708 		*done = 1;
709 
710 	switch (psp->p_op) {
711 
712 	case POP_DIFF:
713 		if ((loperand || lwplinset) && !(lwprinset || roperand))
714 			return (1);
715 		else
716 			return (0);
717 
718 	case POP_AND:
719 		if ((loperand || lwplinset) && (roperand || lwprinset))
720 			return (1);
721 		else
722 			return (0);
723 
724 	case POP_OR:
725 		if (loperand || roperand || lwplinset || lwprinset)
726 			return (1);
727 		else
728 			return (0);
729 
730 	case POP_XOR:
731 		if (((loperand || lwplinset) &&
732 		    !(lwprinset || roperand)) ||
733 		    ((roperand || lwprinset) &&
734 		    !(lwplinset || loperand)))
735 			return (1);
736 		else
737 			return (0);
738 
739 	default:
740 #ifdef DEBUG
741 		cmn_err(CE_WARN, "lwpinset called with bad set");
742 		return (0);
743 #else
744 		return (0);
745 #endif
746 	}
747 	/* NOTREACHED */
748 }
749 /*
750  * Check for common cases of procsets which specify only the
751  * current process.  cur_inset_only() returns B_TRUE when
752  * the current process is the only one in the set.  B_FALSE
753  * is returned to indicate that this may not be the case.
754  */
755 boolean_t
756 cur_inset_only(procset_t *psp)
757 {
758 	if (((psp->p_lidtype == P_PID &&
759 	    (psp->p_lid == P_MYID ||
760 	    psp->p_lid == ttoproc(curthread)->p_pid)) ||
761 	    ((psp->p_lidtype == P_LWPID) &&
762 	    (psp->p_lid == P_MYID ||
763 	    psp->p_lid == curthread->t_tid))) &&
764 	    psp->p_op == POP_AND && psp->p_ridtype == P_ALL)
765 		return (B_TRUE);
766 
767 	if (((psp->p_ridtype == P_PID &&
768 	    (psp->p_rid == P_MYID ||
769 	    psp->p_rid == ttoproc(curthread)->p_pid)) ||
770 	    ((psp->p_ridtype == P_LWPID) &&
771 	    (psp->p_rid == P_MYID ||
772 	    psp->p_rid == curthread->t_tid))) &&
773 	    psp->p_op == POP_AND && psp->p_lidtype == P_ALL)
774 		return (B_TRUE);
775 
776 	return (B_FALSE);
777 }
778 
779 id_t
780 getmyid(idtype_t idtype)
781 {
782 	proc_t	*pp;
783 	uid_t uid;
784 	gid_t gid;
785 	pid_t sid;
786 
787 	pp = ttoproc(curthread);
788 
789 	switch (idtype) {
790 	case P_LWPID:
791 		return (curthread->t_tid);
792 
793 	case P_PID:
794 		return (pp->p_pid);
795 
796 	case P_PPID:
797 		return (pp->p_ppid);
798 
799 	case P_PGID:
800 		return (pp->p_pgrp);
801 
802 	case P_SID:
803 		mutex_enter(&pp->p_splock);
804 		sid = pp->p_sessp->s_sid;
805 		mutex_exit(&pp->p_splock);
806 		return (sid);
807 
808 	case P_TASKID:
809 		return (pp->p_task->tk_tkid);
810 
811 	case P_CID:
812 		return (curthread->t_cid);
813 
814 	case P_UID:
815 		mutex_enter(&pp->p_crlock);
816 		uid = crgetuid(pp->p_cred);
817 		mutex_exit(&pp->p_crlock);
818 		return (uid);
819 
820 	case P_GID:
821 		mutex_enter(&pp->p_crlock);
822 		gid = crgetgid(pp->p_cred);
823 		mutex_exit(&pp->p_crlock);
824 		return (gid);
825 
826 	case P_PROJID:
827 		return (pp->p_task->tk_proj->kpj_id);
828 
829 	case P_POOLID:
830 		return (pp->p_pool->pool_id);
831 
832 	case P_ZONEID:
833 		return (pp->p_zone->zone_id);
834 
835 	case P_CTID:
836 		return (PRCTID(pp));
837 
838 	case P_ALL:
839 		/*
840 		 * The value doesn't matter for P_ALL.
841 		 */
842 		return (0);
843 
844 	default:
845 		return (-1);
846 	}
847 }
848 
849 static kthread_t *
850 getlwpptr(id_t id)
851 {
852 	proc_t		*p;
853 	kthread_t	*t;
854 
855 	ASSERT(MUTEX_HELD(&(ttoproc(curthread)->p_lock)));
856 
857 	if (id == P_MYID)
858 		t = curthread;
859 	else {
860 		p = ttoproc(curthread);
861 		t = idtot(p, id);
862 	}
863 
864 	return (t);
865 }
866 
867 /*
868  * The dotolwp function locates the LWP(s) specified by the procset structure
869  * pointed to by psp.  If funcp is non-NULL then it points to a function
870  * which dotolwp will call for each LWP in the specified set.
871  * LWPIDs specified in the procset structure always refer to lwps in curproc.
872  * The arguments for this function must be "char *arg", and "kthread_t *tp",
873  * where tp is a pointer to the current thread from the set.
874  * Note that these arguments are passed to the function in reversed order
875  * than the order of arguments passed by dotoprocs() to its callback function.
876  * Also note that there are two separate cases where this routine returns zero.
877  * In the first case no mutex is grabbed, in the second the p_lock mutex
878  * is NOT RELEASED. The priocntl code is expecting this behaviour.
879  */
880 int
881 dotolwp(procset_t *psp, int (*funcp)(), char *arg)
882 {
883 	int		error = 0;
884 	int		nfound = 0;
885 	kthread_t	*tp;
886 	proc_t		*pp;
887 	int		done = 0;
888 
889 	/*
890 	 * Check that the procset_t is valid.
891 	 */
892 	error = checkprocset(psp);
893 	if (error) {
894 		return (error);
895 	}
896 
897 	mutex_enter(&pidlock);
898 
899 	/*
900 	 * Check for the special value P_MYID in either operand
901 	 * and replace it with the correct value.  We don't check
902 	 * for an error return from getmyid() because the idtypes
903 	 * have been validated by the checkprocset() call above.
904 	 */
905 	if (psp->p_lid == P_MYID) {
906 		psp->p_lid = getmyid(psp->p_lidtype);
907 	}
908 	if (psp->p_rid == P_MYID) {
909 		psp->p_rid = getmyid(psp->p_ridtype);
910 	}
911 
912 	pp = ttoproc(curthread);
913 
914 	mutex_enter(&pp->p_lock);
915 	if (procinset(pp, psp) ||
916 	    (tp = pp->p_tlist) == NULL) {
917 		mutex_exit(&pp->p_lock);
918 		mutex_exit(&pidlock);
919 		return (0);
920 	}
921 	do {
922 		if (lwpinset(pp, psp, tp, &done)) {
923 			nfound ++;
924 			error = (*funcp)(arg, tp);
925 			if (error) {
926 				mutex_exit(&pp->p_lock);
927 				mutex_exit(&pidlock);
928 				return (error);
929 			}
930 		}
931 	} while (((tp = tp->t_forw) != pp->p_tlist) && !done);
932 
933 	if (nfound == 0) {
934 		mutex_exit(&pp->p_lock);
935 		mutex_exit(&pidlock);
936 		return (ESRCH);
937 	}
938 
939 	mutex_exit(&pidlock);
940 	return (error);
941 }
942