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 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