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 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright 2026 Oxide Computer Company
28 */
29
30 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
32
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/sysmacros.h>
36 #include <sys/systm.h>
37 #include <sys/errno.h>
38 #include <sys/file.h>
39 #include <sys/proc.h>
40 #include <sys/session.h>
41 #include <sys/debug.h>
42 #include <sys/pgrpsys.h>
43
44 /* ARGSUSED */
45 int
setpgrp(int flag,int pid,int pgid)46 setpgrp(int flag, int pid, int pgid)
47 {
48 proc_t *p = curproc;
49 int retval = 0;
50 int sid;
51
52 switch (flag) {
53
54 case PGRPSYS_SETPGRP:
55 mutex_enter(&pidlock);
56 if (p->p_sessp->s_sidp != p->p_pidp && !pgmembers(p->p_pid)) {
57 mutex_exit(&pidlock);
58 sess_create();
59 } else
60 mutex_exit(&pidlock);
61 mutex_enter(&p->p_splock);
62 sid = p->p_sessp->s_sid;
63 mutex_exit(&p->p_splock);
64 return (sid);
65
66 case PGRPSYS_SETSID:
67 mutex_enter(&pidlock);
68 if (p->p_pgidp == p->p_pidp || pgmembers(p->p_pid)) {
69 mutex_exit(&pidlock);
70 return (set_errno(EPERM));
71 }
72 mutex_exit(&pidlock);
73 sess_create();
74 mutex_enter(&p->p_splock);
75 sid = p->p_sessp->s_sid;
76 mutex_exit(&p->p_splock);
77 return (sid);
78
79 case PGRPSYS_SETPGID:
80 {
81 mutex_enter(&pidlock);
82 if (pid == 0)
83 pid = p->p_pid;
84 else if (pid < 0 || pid >= maxpid) {
85 mutex_exit(&pidlock);
86 return (set_errno(EINVAL));
87 } else if (pid != p->p_pid) {
88 for (p = p->p_child; /* empty */; p = p->p_sibling) {
89 if (p == NULL) {
90 mutex_exit(&pidlock);
91 return (set_errno(ESRCH));
92 }
93 if (p->p_pid == pid)
94 break;
95 }
96 if (p->p_flag & SEXECED) {
97 mutex_exit(&pidlock);
98 return (set_errno(EACCES));
99 }
100 if (p->p_sessp != ttoproc(curthread)->p_sessp) {
101 mutex_exit(&pidlock);
102 return (set_errno(EPERM));
103 }
104 }
105
106 if (p->p_sessp->s_sid == pid) {
107 mutex_exit(&pidlock);
108 return (set_errno(EPERM));
109 }
110
111 if (pgid == 0)
112 pgid = p->p_pid;
113 else if (pgid < 0 || pgid >= maxpid) {
114 mutex_exit(&pidlock);
115 return (set_errno(EINVAL));
116 }
117
118 if (p->p_pgrp == pgid) {
119 mutex_exit(&pidlock);
120 break;
121 } else if (p->p_pid == pgid) {
122 /*
123 * We need to protect p_pgidp with p_lock because
124 * /proc looks at it while holding only p_lock.
125 */
126 mutex_enter(&p->p_lock);
127 pgexit(p);
128 pgjoin(p, p->p_pidp);
129 mutex_exit(&p->p_lock);
130 } else {
131 register proc_t *q;
132
133 if ((q = pgfind(pgid)) == NULL ||
134 q->p_sessp != p->p_sessp) {
135 mutex_exit(&pidlock);
136 return (set_errno(EPERM));
137 }
138 /*
139 * See comment above about p_lock and /proc
140 */
141 mutex_enter(&p->p_lock);
142 pgexit(p);
143 pgjoin(p, q->p_pgidp);
144 mutex_exit(&p->p_lock);
145 }
146 mutex_exit(&pidlock);
147 break;
148 }
149
150 case PGRPSYS_GETPGRP:
151 mutex_enter(&pidlock);
152 retval = p->p_pgrp;
153 mutex_exit(&pidlock);
154 break;
155
156 case PGRPSYS_GETSID:
157 case PGRPSYS_GETPGID:
158 if (pid < 0 || pid >= maxpid) {
159 return (set_errno(EINVAL));
160 }
161 mutex_enter(&pidlock);
162 if (pid != 0 && p->p_pid != pid &&
163 ((p = prfind(pid)) == NULL || p->p_stat == SIDL)) {
164 mutex_exit(&pidlock);
165 return (set_errno(ESRCH));
166 }
167 if (flag == PGRPSYS_GETSID)
168 retval = p->p_sessp->s_sid;
169 else
170 retval = p->p_pgrp;
171 mutex_exit(&pidlock);
172 break;
173
174 }
175 return (retval);
176 }
177