xref: /illumos-gate/usr/src/uts/common/syscall/pgrpsys.c (revision ac2250cb76bb32944fd2c8a3ba2cd3f79747748d)
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