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