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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 #include <sys/types.h>
30 #include <sys/sysmacros.h>
31 #include <sys/param.h>
32 #include <sys/systm.h>
35 #include <sys/vnode.h>
37 #include <sys/errno.h>
43 #include <sys/debug.h>
45 #include <sys/signal.h>
46 #include <sys/siginfo.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>
56 #include <sys/project.h>
59 #include <sys/contract/process_impl.h>
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 *);
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
84 dotoprocs(procset_t
*psp
, int (*funcp
)(), char *arg
)
86 proc_t
*prp
; /* A process from the set */
88 int nfound
; /* Nbr of processes found. */
89 proc_t
*lastprp
; /* Last proc found. */
91 ASSERT(funcp
!= NULL
);
94 * Check that the procset_t is valid.
96 error
= checkprocset(psp
);
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.
106 mutex_enter(&pidlock
);
107 if (psp
->p_lid
== P_MYID
) {
108 psp
->p_lid
= getmyid(psp
->p_lidtype
);
110 if (psp
->p_rid
== P_MYID
) {
111 psp
->p_rid
= getmyid(psp
->p_ridtype
);
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.
124 * Perform the check symmetrically: either the left or right side may
125 * specify a pid, with the opposite side being 'all'.
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
))) {
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
)) {
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.
143 mutex_exit(&pidlock
);
147 * Operate only on the specified proc. It's okay
150 error
= (*funcp
)(prp
, arg
);
151 mutex_exit(&pidlock
);
161 for (prp
= practive
; prp
!= NULL
; prp
= prp
->p_next
) {
163 * If caller is in a non-global zone, skip processes
166 if (!HASZONEACCESS(curproc
, prp
->p_zone
->zone_id
))
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.
174 if (prp
->p_stat
== SIDL
|| prp
->p_stat
== SZOMB
)
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
);
182 mutex_exit(&prp
->p_lock
);
185 if (prp
!= proc_init
) {
186 error
= (*funcp
)(prp
, arg
);
188 mutex_exit(&pidlock
);
191 mutex_exit(&pidlock
);
198 mutex_exit(&pidlock
);
201 if (nfound
== 1 && lastprp
== proc_init
)
202 error
= (*funcp
)(lastprp
, arg
);
205 mutex_exit(&pidlock
);
210 * Check if a procset_t is valid. Return zero or an errno.
213 checkprocset(procset_t
*psp
)
215 switch (psp
->p_lidtype
) {
235 switch (psp
->p_ridtype
) {
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.
276 * This function expects to be called with a valid procset_t.
277 * The set should be checked using checkprocset() before calling
281 procinset(proc_t
*pp
, procset_t
*psp
)
289 ASSERT(MUTEX_HELD(&pp
->p_lock
));
291 switch (psp
->p_lidtype
) {
294 if (pp
== ttoproc(curthread
))
295 if (getlwpptr(psp
->p_lid
) != NULL
)
300 if (pp
->p_pid
== psp
->p_lid
)
305 if (pp
->p_ppid
== psp
->p_lid
)
310 if (pp
->p_pgrp
== psp
->p_lid
)
315 mutex_enter(&pp
->p_splock
);
316 if (pp
->p_sessp
->s_sid
== psp
->p_lid
)
318 mutex_exit(&pp
->p_splock
);
325 if (tp
->t_cid
== psp
->p_lid
)
330 if (pp
->p_task
->tk_tkid
== psp
->p_lid
)
335 mutex_enter(&pp
->p_crlock
);
336 if (crgetuid(pp
->p_cred
) == psp
->p_lid
)
338 mutex_exit(&pp
->p_crlock
);
342 mutex_enter(&pp
->p_crlock
);
343 if (crgetgid(pp
->p_cred
) == psp
->p_lid
)
345 mutex_exit(&pp
->p_crlock
);
349 if (pp
->p_task
->tk_proj
->kpj_id
== psp
->p_lid
)
354 if (pp
->p_pool
->pool_id
== psp
->p_lid
)
359 if (pp
->p_zone
->zone_id
== psp
->p_lid
)
364 if (PRCTID(pp
) == psp
->p_lid
)
374 cmn_err(CE_WARN
, "procinset called with bad set");
381 switch (psp
->p_ridtype
) {
384 if (pp
== ttoproc(curthread
))
385 if (getlwpptr(psp
->p_rid
) != NULL
)
390 if (pp
->p_pid
== psp
->p_rid
)
395 if (pp
->p_ppid
== psp
->p_rid
)
400 if (pp
->p_pgrp
== psp
->p_rid
)
405 mutex_enter(&pp
->p_splock
);
406 if (pp
->p_sessp
->s_sid
== psp
->p_rid
)
408 mutex_exit(&pp
->p_splock
);
412 if (pp
->p_task
->tk_tkid
== psp
->p_rid
)
420 if (tp
->t_cid
== psp
->p_rid
)
425 mutex_enter(&pp
->p_crlock
);
426 if (crgetuid(pp
->p_cred
) == psp
->p_rid
)
428 mutex_exit(&pp
->p_crlock
);
432 mutex_enter(&pp
->p_crlock
);
433 if (crgetgid(pp
->p_cred
) == psp
->p_rid
)
435 mutex_exit(&pp
->p_crlock
);
439 if (pp
->p_task
->tk_proj
->kpj_id
== psp
->p_rid
)
444 if (pp
->p_pool
->pool_id
== psp
->p_rid
)
449 if (pp
->p_zone
->zone_id
== psp
->p_rid
)
454 if (PRCTID(pp
) == psp
->p_rid
)
464 cmn_err(CE_WARN
, "procinset called with bad set");
474 if (loperand
&& !lwprinproc
&& !roperand
)
480 if (loperand
&& roperand
)
486 if (loperand
|| roperand
)
492 if ((loperand
&& !lwprinproc
&& !roperand
) ||
493 (roperand
&& !lwplinproc
&& !loperand
))
500 cmn_err(CE_WARN
, "procinset called with bad set");
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.
514 * This function expects to be called with a valid procset_t.
515 * The set should be checked using checkprocset() before calling
519 lwpinset(proc_t
*pp
, procset_t
*psp
, kthread_t
*tp
, int *done
)
526 ASSERT(ttoproc(tp
) == pp
);
529 * If process is in the sys class return (0).
531 if (proctot(pp
)->t_cid
== 0) {
535 switch (psp
->p_lidtype
) {
538 if (tp
->t_tid
== psp
->p_lid
)
543 if (pp
->p_pid
== psp
->p_lid
)
548 if (pp
->p_ppid
== psp
->p_lid
)
553 if (pp
->p_pgrp
== psp
->p_lid
)
558 mutex_enter(&pp
->p_splock
);
559 if (pp
->p_sessp
->s_sid
== psp
->p_lid
)
561 mutex_exit(&pp
->p_splock
);
565 if (pp
->p_task
->tk_tkid
== psp
->p_lid
)
570 if (tp
->t_cid
== psp
->p_lid
)
575 mutex_enter(&pp
->p_crlock
);
576 if (crgetuid(pp
->p_cred
) == psp
->p_lid
)
578 mutex_exit(&pp
->p_crlock
);
582 mutex_enter(&pp
->p_crlock
);
583 if (crgetgid(pp
->p_cred
) == psp
->p_lid
)
585 mutex_exit(&pp
->p_crlock
);
589 if (pp
->p_task
->tk_proj
->kpj_id
== psp
->p_lid
)
594 if (pp
->p_pool
->pool_id
== psp
->p_lid
)
599 if (pp
->p_zone
->zone_id
== psp
->p_lid
)
604 if (PRCTID(pp
) == psp
->p_lid
)
614 cmn_err(CE_WARN
, "lwpinset called with bad set");
621 switch (psp
->p_ridtype
) {
624 if (tp
->t_tid
== psp
->p_rid
)
629 if (pp
->p_pid
== psp
->p_rid
)
634 if (pp
->p_ppid
== psp
->p_rid
)
639 if (pp
->p_pgrp
== psp
->p_rid
)
644 mutex_enter(&pp
->p_splock
);
645 if (pp
->p_sessp
->s_sid
== psp
->p_rid
)
647 mutex_exit(&pp
->p_splock
);
651 if (pp
->p_task
->tk_tkid
== psp
->p_rid
)
656 if (tp
->t_cid
== psp
->p_rid
)
661 mutex_enter(&pp
->p_crlock
);
662 if (crgetuid(pp
->p_cred
) == psp
->p_rid
)
664 mutex_exit(&pp
->p_crlock
);
668 mutex_enter(&pp
->p_crlock
);
669 if (crgetgid(pp
->p_cred
) == psp
->p_rid
)
671 mutex_exit(&pp
->p_crlock
);
675 if (pp
->p_task
->tk_proj
->kpj_id
== psp
->p_rid
)
680 if (pp
->p_pool
->pool_id
== psp
->p_rid
)
685 if (pp
->p_zone
->zone_id
== psp
->p_rid
)
690 if (PRCTID(pp
) == psp
->p_rid
)
700 cmn_err(CE_WARN
, "lwpinset called with bad set");
707 if (lwplinset
&& lwprinset
)
713 if ((loperand
|| lwplinset
) && !(lwprinset
|| roperand
))
719 if ((loperand
|| lwplinset
) && (roperand
|| lwprinset
))
725 if (loperand
|| roperand
|| lwplinset
|| lwprinset
)
731 if (((loperand
|| lwplinset
) &&
732 !(lwprinset
|| roperand
)) ||
733 ((roperand
|| lwprinset
) &&
734 !(lwplinset
|| loperand
)))
741 cmn_err(CE_WARN
, "lwpinset called with bad set");
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.
756 cur_inset_only(procset_t
*psp
)
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
)
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
)
780 getmyid(idtype_t idtype
)
787 pp
= ttoproc(curthread
);
791 return (curthread
->t_tid
);
803 mutex_enter(&pp
->p_splock
);
804 sid
= pp
->p_sessp
->s_sid
;
805 mutex_exit(&pp
->p_splock
);
809 return (pp
->p_task
->tk_tkid
);
812 return (curthread
->t_cid
);
815 mutex_enter(&pp
->p_crlock
);
816 uid
= crgetuid(pp
->p_cred
);
817 mutex_exit(&pp
->p_crlock
);
821 mutex_enter(&pp
->p_crlock
);
822 gid
= crgetgid(pp
->p_cred
);
823 mutex_exit(&pp
->p_crlock
);
827 return (pp
->p_task
->tk_proj
->kpj_id
);
830 return (pp
->p_pool
->pool_id
);
833 return (pp
->p_zone
->zone_id
);
840 * The value doesn't matter for P_ALL.
855 ASSERT(MUTEX_HELD(&(ttoproc(curthread
)->p_lock
)));
860 p
= ttoproc(curthread
);
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.
881 dotolwp(procset_t
*psp
, int (*funcp
)(), char *arg
)
890 * Check that the procset_t is valid.
892 error
= checkprocset(psp
);
897 mutex_enter(&pidlock
);
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.
905 if (psp
->p_lid
== P_MYID
) {
906 psp
->p_lid
= getmyid(psp
->p_lidtype
);
908 if (psp
->p_rid
== P_MYID
) {
909 psp
->p_rid
= getmyid(psp
->p_ridtype
);
912 pp
= ttoproc(curthread
);
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
);
922 if (lwpinset(pp
, psp
, tp
, &done
)) {
924 error
= (*funcp
)(arg
, tp
);
926 mutex_exit(&pp
->p_lock
);
927 mutex_exit(&pidlock
);
931 } while (((tp
= tp
->t_forw
) != pp
->p_tlist
) && !done
);
934 mutex_exit(&pp
->p_lock
);
935 mutex_exit(&pidlock
);
939 mutex_exit(&pidlock
);