Deleted Added
full compact
kern_prot.c (90756) kern_prot.c (91140)
1/*
2 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 * Copyright (c) 2000-2001 Robert N. M. Watson. All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94
1/*
2 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 * Copyright (c) 2000-2001 Robert N. M. Watson. All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94
40 * $FreeBSD: head/sys/kern/kern_prot.c 90756 2002-02-17 07:30:34Z dillon $
40 * $FreeBSD: head/sys/kern/kern_prot.c 91140 2002-02-23 11:12:57Z tanimura $
41 */
42
43/*
44 * System calls related to processes and protection
45 */
46
47#include "opt_compat.h"
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/acct.h>
52#include <sys/kernel.h>
53#include <sys/lock.h>
41 */
42
43/*
44 * System calls related to processes and protection
45 */
46
47#include "opt_compat.h"
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/acct.h>
52#include <sys/kernel.h>
53#include <sys/lock.h>
54#include <sys/malloc.h>
54#include <sys/mutex.h>
55#include <sys/mutex.h>
55#include <sys/proc.h>
56#include <sys/sx.h>
56#include <sys/sx.h>
57#include <sys/proc.h>
57#include <sys/sysproto.h>
58#include <sys/jail.h>
58#include <sys/sysproto.h>
59#include <sys/jail.h>
59#include <sys/malloc.h>
60#include <sys/pioctl.h>
61#include <sys/resourcevar.h>
62#include <sys/sysctl.h>
63
64static MALLOC_DEFINE(M_CRED, "cred", "credentials");
65
66SYSCTL_DECL(_security);
67SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0,
68 "BSD security policy");
69
70#ifndef _SYS_SYSPROTO_H_
71struct getpid_args {
72 int dummy;
73};
74#endif
75/*
76 * MPSAFE
77 */
78/* ARGSUSED */
79int
80getpid(td, uap)
81 struct thread *td;
82 struct getpid_args *uap;
83{
84 struct proc *p = td->td_proc;
85 int s;
86
87 s = mtx_lock_giant(kern_giant_proc);
88 td->td_retval[0] = p->p_pid;
89#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
90 PROC_LOCK(p);
91 td->td_retval[1] = p->p_pptr->p_pid;
92 PROC_UNLOCK(p);
93#endif
94 mtx_unlock_giant(s);
95 return (0);
96}
97
98#ifndef _SYS_SYSPROTO_H_
99struct getppid_args {
100 int dummy;
101};
102#endif
103/*
104 * MPSAFE
105 */
106/* ARGSUSED */
107int
108getppid(td, uap)
109 struct thread *td;
110 struct getppid_args *uap;
111{
112 struct proc *p = td->td_proc;
113 int s;
114
115 s = mtx_lock_giant(kern_giant_proc);
116 PROC_LOCK(p);
117 td->td_retval[0] = p->p_pptr->p_pid;
118 PROC_UNLOCK(p);
119 mtx_unlock_giant(s);
120 return (0);
121}
122
123/*
124 * Get process group ID; note that POSIX getpgrp takes no parameter.
125 */
126#ifndef _SYS_SYSPROTO_H_
127struct getpgrp_args {
128 int dummy;
129};
130#endif
131/*
132 * MPSAFE
133 */
134int
135getpgrp(td, uap)
136 struct thread *td;
137 struct getpgrp_args *uap;
138{
139 struct proc *p = td->td_proc;
60#include <sys/pioctl.h>
61#include <sys/resourcevar.h>
62#include <sys/sysctl.h>
63
64static MALLOC_DEFINE(M_CRED, "cred", "credentials");
65
66SYSCTL_DECL(_security);
67SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0,
68 "BSD security policy");
69
70#ifndef _SYS_SYSPROTO_H_
71struct getpid_args {
72 int dummy;
73};
74#endif
75/*
76 * MPSAFE
77 */
78/* ARGSUSED */
79int
80getpid(td, uap)
81 struct thread *td;
82 struct getpid_args *uap;
83{
84 struct proc *p = td->td_proc;
85 int s;
86
87 s = mtx_lock_giant(kern_giant_proc);
88 td->td_retval[0] = p->p_pid;
89#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
90 PROC_LOCK(p);
91 td->td_retval[1] = p->p_pptr->p_pid;
92 PROC_UNLOCK(p);
93#endif
94 mtx_unlock_giant(s);
95 return (0);
96}
97
98#ifndef _SYS_SYSPROTO_H_
99struct getppid_args {
100 int dummy;
101};
102#endif
103/*
104 * MPSAFE
105 */
106/* ARGSUSED */
107int
108getppid(td, uap)
109 struct thread *td;
110 struct getppid_args *uap;
111{
112 struct proc *p = td->td_proc;
113 int s;
114
115 s = mtx_lock_giant(kern_giant_proc);
116 PROC_LOCK(p);
117 td->td_retval[0] = p->p_pptr->p_pid;
118 PROC_UNLOCK(p);
119 mtx_unlock_giant(s);
120 return (0);
121}
122
123/*
124 * Get process group ID; note that POSIX getpgrp takes no parameter.
125 */
126#ifndef _SYS_SYSPROTO_H_
127struct getpgrp_args {
128 int dummy;
129};
130#endif
131/*
132 * MPSAFE
133 */
134int
135getpgrp(td, uap)
136 struct thread *td;
137 struct getpgrp_args *uap;
138{
139 struct proc *p = td->td_proc;
140 int s;
140
141
141 mtx_lock(&Giant);
142 s = mtx_lock_giant(kern_giant_proc);
143 PROC_LOCK(p);
142 td->td_retval[0] = p->p_pgrp->pg_id;
144 td->td_retval[0] = p->p_pgrp->pg_id;
143 mtx_unlock(&Giant);
145 PROC_UNLOCK(p);
146 mtx_unlock_giant(s);
144 return (0);
145}
146
147/* Get an arbitary pid's process group id */
148#ifndef _SYS_SYSPROTO_H_
149struct getpgid_args {
150 pid_t pid;
151};
152#endif
153/*
154 * MPSAFE
155 */
156int
157getpgid(td, uap)
158 struct thread *td;
159 struct getpgid_args *uap;
160{
161 struct proc *p = td->td_proc;
162 struct proc *pt;
163 int error, s;
164
165 s = mtx_lock_giant(kern_giant_proc);
166 error = 0;
147 return (0);
148}
149
150/* Get an arbitary pid's process group id */
151#ifndef _SYS_SYSPROTO_H_
152struct getpgid_args {
153 pid_t pid;
154};
155#endif
156/*
157 * MPSAFE
158 */
159int
160getpgid(td, uap)
161 struct thread *td;
162 struct getpgid_args *uap;
163{
164 struct proc *p = td->td_proc;
165 struct proc *pt;
166 int error, s;
167
168 s = mtx_lock_giant(kern_giant_proc);
169 error = 0;
167 if (uap->pid == 0)
170 if (uap->pid == 0) {
171 PROC_LOCK(p);
168 td->td_retval[0] = p->p_pgrp->pg_id;
172 td->td_retval[0] = p->p_pgrp->pg_id;
169 else if ((pt = pfind(uap->pid)) == NULL)
173 PROC_UNLOCK(p);
174 } else if ((pt = pfind(uap->pid)) == NULL)
170 error = ESRCH;
171 else {
172 error = p_cansee(p, pt);
173 if (error == 0)
174 td->td_retval[0] = pt->p_pgrp->pg_id;
175 PROC_UNLOCK(pt);
176 }
177 mtx_unlock_giant(s);
178 return (error);
179}
180
181/*
182 * Get an arbitary pid's session id.
183 */
184#ifndef _SYS_SYSPROTO_H_
185struct getsid_args {
186 pid_t pid;
187};
188#endif
189/*
190 * MPSAFE
191 */
192int
193getsid(td, uap)
194 struct thread *td;
195 struct getsid_args *uap;
196{
197 struct proc *p = td->td_proc;
198 struct proc *pt;
199 int error;
175 error = ESRCH;
176 else {
177 error = p_cansee(p, pt);
178 if (error == 0)
179 td->td_retval[0] = pt->p_pgrp->pg_id;
180 PROC_UNLOCK(pt);
181 }
182 mtx_unlock_giant(s);
183 return (error);
184}
185
186/*
187 * Get an arbitary pid's session id.
188 */
189#ifndef _SYS_SYSPROTO_H_
190struct getsid_args {
191 pid_t pid;
192};
193#endif
194/*
195 * MPSAFE
196 */
197int
198getsid(td, uap)
199 struct thread *td;
200 struct getsid_args *uap;
201{
202 struct proc *p = td->td_proc;
203 struct proc *pt;
204 int error;
205 int s;
200
206
201 mtx_lock(&Giant);
207 s = mtx_lock_giant(kern_giant_proc);
202 error = 0;
208 error = 0;
203 if (uap->pid == 0)
209 if (uap->pid == 0) {
210 PROC_LOCK(p);
204 td->td_retval[0] = p->p_session->s_sid;
211 td->td_retval[0] = p->p_session->s_sid;
205 else if ((pt = pfind(uap->pid)) == NULL)
212 PROC_UNLOCK(p);
213 } else if ((pt = pfind(uap->pid)) == NULL)
206 error = ESRCH;
207 else {
208 error = p_cansee(p, pt);
209 if (error == 0)
210 td->td_retval[0] = pt->p_session->s_sid;
211 PROC_UNLOCK(pt);
212 }
214 error = ESRCH;
215 else {
216 error = p_cansee(p, pt);
217 if (error == 0)
218 td->td_retval[0] = pt->p_session->s_sid;
219 PROC_UNLOCK(pt);
220 }
213 mtx_unlock(&Giant);
221 mtx_unlock_giant(s);
214 return (error);
215}
216
217#ifndef _SYS_SYSPROTO_H_
218struct getuid_args {
219 int dummy;
220};
221#endif
222/*
223 * MPSAFE
224 */
225/* ARGSUSED */
226int
227getuid(td, uap)
228 struct thread *td;
229 struct getuid_args *uap;
230{
231 struct proc *p = td->td_proc;
232
233 mtx_lock(&Giant);
234 td->td_retval[0] = p->p_ucred->cr_ruid;
235#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
236 td->td_retval[1] = p->p_ucred->cr_uid;
237#endif
238 mtx_unlock(&Giant);
239 return (0);
240}
241
242#ifndef _SYS_SYSPROTO_H_
243struct geteuid_args {
244 int dummy;
245};
246#endif
247/*
248 * MPSAFE
249 */
250/* ARGSUSED */
251int
252geteuid(td, uap)
253 struct thread *td;
254 struct geteuid_args *uap;
255{
256 mtx_lock(&Giant);
257 td->td_retval[0] = td->td_proc->p_ucred->cr_uid;
258 mtx_unlock(&Giant);
259 return (0);
260}
261
262#ifndef _SYS_SYSPROTO_H_
263struct getgid_args {
264 int dummy;
265};
266#endif
267/*
268 * MPSAFE
269 */
270/* ARGSUSED */
271int
272getgid(td, uap)
273 struct thread *td;
274 struct getgid_args *uap;
275{
276 struct proc *p = td->td_proc;
277
278 mtx_lock(&Giant);
279 td->td_retval[0] = p->p_ucred->cr_rgid;
280#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
281 td->td_retval[1] = p->p_ucred->cr_groups[0];
282#endif
283 mtx_unlock(&Giant);
284 return (0);
285}
286
287/*
288 * Get effective group ID. The "egid" is groups[0], and could be obtained
289 * via getgroups. This syscall exists because it is somewhat painful to do
290 * correctly in a library function.
291 */
292#ifndef _SYS_SYSPROTO_H_
293struct getegid_args {
294 int dummy;
295};
296#endif
297/*
298 * MPSAFE
299 */
300/* ARGSUSED */
301int
302getegid(td, uap)
303 struct thread *td;
304 struct getegid_args *uap;
305{
306 struct proc *p = td->td_proc;
307
308 mtx_lock(&Giant);
309 td->td_retval[0] = p->p_ucred->cr_groups[0];
310 mtx_unlock(&Giant);
311 return (0);
312}
313
314#ifndef _SYS_SYSPROTO_H_
315struct getgroups_args {
316 u_int gidsetsize;
317 gid_t *gidset;
318};
319#endif
320/*
321 * MPSAFE
322 */
323int
324getgroups(td, uap)
325 struct thread *td;
326 register struct getgroups_args *uap;
327{
328 struct ucred *cred;
329 struct proc *p = td->td_proc;
330 u_int ngrp;
331 int error;
332
333 mtx_lock(&Giant);
334 error = 0;
335 cred = p->p_ucred;
336 if ((ngrp = uap->gidsetsize) == 0) {
337 td->td_retval[0] = cred->cr_ngroups;
338 goto done2;
339 }
340 if (ngrp < cred->cr_ngroups) {
341 error = EINVAL;
342 goto done2;
343 }
344 ngrp = cred->cr_ngroups;
345 if ((error = copyout((caddr_t)cred->cr_groups,
346 (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
347 goto done2;
348 td->td_retval[0] = ngrp;
349done2:
350 mtx_unlock(&Giant);
351 return (error);
352}
353
354#ifndef _SYS_SYSPROTO_H_
355struct setsid_args {
356 int dummy;
357};
358#endif
359/*
360 * MPSAFE
361 */
362/* ARGSUSED */
363int
364setsid(td, uap)
365 register struct thread *td;
366 struct setsid_args *uap;
367{
222 return (error);
223}
224
225#ifndef _SYS_SYSPROTO_H_
226struct getuid_args {
227 int dummy;
228};
229#endif
230/*
231 * MPSAFE
232 */
233/* ARGSUSED */
234int
235getuid(td, uap)
236 struct thread *td;
237 struct getuid_args *uap;
238{
239 struct proc *p = td->td_proc;
240
241 mtx_lock(&Giant);
242 td->td_retval[0] = p->p_ucred->cr_ruid;
243#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
244 td->td_retval[1] = p->p_ucred->cr_uid;
245#endif
246 mtx_unlock(&Giant);
247 return (0);
248}
249
250#ifndef _SYS_SYSPROTO_H_
251struct geteuid_args {
252 int dummy;
253};
254#endif
255/*
256 * MPSAFE
257 */
258/* ARGSUSED */
259int
260geteuid(td, uap)
261 struct thread *td;
262 struct geteuid_args *uap;
263{
264 mtx_lock(&Giant);
265 td->td_retval[0] = td->td_proc->p_ucred->cr_uid;
266 mtx_unlock(&Giant);
267 return (0);
268}
269
270#ifndef _SYS_SYSPROTO_H_
271struct getgid_args {
272 int dummy;
273};
274#endif
275/*
276 * MPSAFE
277 */
278/* ARGSUSED */
279int
280getgid(td, uap)
281 struct thread *td;
282 struct getgid_args *uap;
283{
284 struct proc *p = td->td_proc;
285
286 mtx_lock(&Giant);
287 td->td_retval[0] = p->p_ucred->cr_rgid;
288#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
289 td->td_retval[1] = p->p_ucred->cr_groups[0];
290#endif
291 mtx_unlock(&Giant);
292 return (0);
293}
294
295/*
296 * Get effective group ID. The "egid" is groups[0], and could be obtained
297 * via getgroups. This syscall exists because it is somewhat painful to do
298 * correctly in a library function.
299 */
300#ifndef _SYS_SYSPROTO_H_
301struct getegid_args {
302 int dummy;
303};
304#endif
305/*
306 * MPSAFE
307 */
308/* ARGSUSED */
309int
310getegid(td, uap)
311 struct thread *td;
312 struct getegid_args *uap;
313{
314 struct proc *p = td->td_proc;
315
316 mtx_lock(&Giant);
317 td->td_retval[0] = p->p_ucred->cr_groups[0];
318 mtx_unlock(&Giant);
319 return (0);
320}
321
322#ifndef _SYS_SYSPROTO_H_
323struct getgroups_args {
324 u_int gidsetsize;
325 gid_t *gidset;
326};
327#endif
328/*
329 * MPSAFE
330 */
331int
332getgroups(td, uap)
333 struct thread *td;
334 register struct getgroups_args *uap;
335{
336 struct ucred *cred;
337 struct proc *p = td->td_proc;
338 u_int ngrp;
339 int error;
340
341 mtx_lock(&Giant);
342 error = 0;
343 cred = p->p_ucred;
344 if ((ngrp = uap->gidsetsize) == 0) {
345 td->td_retval[0] = cred->cr_ngroups;
346 goto done2;
347 }
348 if (ngrp < cred->cr_ngroups) {
349 error = EINVAL;
350 goto done2;
351 }
352 ngrp = cred->cr_ngroups;
353 if ((error = copyout((caddr_t)cred->cr_groups,
354 (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
355 goto done2;
356 td->td_retval[0] = ngrp;
357done2:
358 mtx_unlock(&Giant);
359 return (error);
360}
361
362#ifndef _SYS_SYSPROTO_H_
363struct setsid_args {
364 int dummy;
365};
366#endif
367/*
368 * MPSAFE
369 */
370/* ARGSUSED */
371int
372setsid(td, uap)
373 register struct thread *td;
374 struct setsid_args *uap;
375{
376 struct pgrp *pgrp;
368 int error;
369 struct proc *p = td->td_proc;
377 int error;
378 struct proc *p = td->td_proc;
379 struct pgrp *newpgrp;
380 struct session *newsess;
370
381
382 error = 0;
383 pgrp = NULL;
384
371 mtx_lock(&Giant);
385 mtx_lock(&Giant);
372 if (p->p_pgid == p->p_pid || pgfind(p->p_pid))
386
387 MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
388 MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO);
389
390 PGRPSESS_XLOCK();
391
392 if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) {
393 if (pgrp != NULL)
394 PGRP_UNLOCK(pgrp);
373 error = EPERM;
395 error = EPERM;
374 else {
375 (void)enterpgrp(p, p->p_pid, 1);
396 goto fail;
397 } else {
398 (void)enterpgrp(p, p->p_pid, newpgrp, newsess);
376 td->td_retval[0] = p->p_pid;
377 error = 0;
378 }
399 td->td_retval[0] = p->p_pid;
400 error = 0;
401 }
402 PGRPSESS_XUNLOCK();
379 mtx_unlock(&Giant);
403 mtx_unlock(&Giant);
380 return (error);
404 return (0);
405
406fail:
407 PGRPSESS_XUNLOCK();
408
409 FREE(newpgrp, M_PGRP);
410 FREE(newsess, M_SESSION);
411
412 mtx_unlock(&Giant);
413 return (0);
381}
382
383/*
384 * set process group (setpgid/old setpgrp)
385 *
386 * caller does setpgid(targpid, targpgid)
387 *
388 * pid must be caller or child of caller (ESRCH)
389 * if a child
390 * pid must be in same session (EPERM)
391 * pid can't have done an exec (EACCES)
392 * if pgid != pid
393 * there must exist some pid in same session having pgid (EPERM)
394 * pid must not be session leader (EPERM)
395 */
396#ifndef _SYS_SYSPROTO_H_
397struct setpgid_args {
398 int pid; /* target process id */
399 int pgid; /* target pgrp id */
400};
401#endif
402/*
403 * MPSAFE
404 */
405/* ARGSUSED */
406int
407setpgid(td, uap)
408 struct thread *td;
409 register struct setpgid_args *uap;
410{
411 struct proc *curp = td->td_proc;
412 register struct proc *targp; /* target process */
413 register struct pgrp *pgrp; /* target pgrp */
414 int error;
414}
415
416/*
417 * set process group (setpgid/old setpgrp)
418 *
419 * caller does setpgid(targpid, targpgid)
420 *
421 * pid must be caller or child of caller (ESRCH)
422 * if a child
423 * pid must be in same session (EPERM)
424 * pid can't have done an exec (EACCES)
425 * if pgid != pid
426 * there must exist some pid in same session having pgid (EPERM)
427 * pid must not be session leader (EPERM)
428 */
429#ifndef _SYS_SYSPROTO_H_
430struct setpgid_args {
431 int pid; /* target process id */
432 int pgid; /* target pgrp id */
433};
434#endif
435/*
436 * MPSAFE
437 */
438/* ARGSUSED */
439int
440setpgid(td, uap)
441 struct thread *td;
442 register struct setpgid_args *uap;
443{
444 struct proc *curp = td->td_proc;
445 register struct proc *targp; /* target process */
446 register struct pgrp *pgrp; /* target pgrp */
447 int error;
448 struct pgrp *newpgrp;
415
416 if (uap->pgid < 0)
417 return (EINVAL);
449
450 if (uap->pgid < 0)
451 return (EINVAL);
452
453 error = 0;
454
418 mtx_lock(&Giant);
455 mtx_lock(&Giant);
419 sx_slock(&proctree_lock);
456
457 MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
458
459 PGRPSESS_XLOCK();
460
420 if (uap->pid != 0 && uap->pid != curp->p_pid) {
461 if (uap->pid != 0 && uap->pid != curp->p_pid) {
421 if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) {
462 sx_slock(&proctree_lock);
463 if ((targp = pfind(uap->pid)) == NULL) {
422 if (targp)
423 PROC_UNLOCK(targp);
464 if (targp)
465 PROC_UNLOCK(targp);
466 sx_sunlock(&proctree_lock);
424 error = ESRCH;
467 error = ESRCH;
425 goto done2;
468 goto fail;
426 }
469 }
470 if (!inferior(targp)) {
471 PROC_UNLOCK(targp);
472 sx_sunlock(&proctree_lock);
473 goto fail;
474 }
475 sx_sunlock(&proctree_lock);
427 if ((error = p_cansee(curproc, targp))) {
428 PROC_UNLOCK(targp);
476 if ((error = p_cansee(curproc, targp))) {
477 PROC_UNLOCK(targp);
429 goto done2;
478 goto fail;
430 }
431 if (targp->p_pgrp == NULL ||
432 targp->p_session != curp->p_session) {
433 PROC_UNLOCK(targp);
434 error = EPERM;
479 }
480 if (targp->p_pgrp == NULL ||
481 targp->p_session != curp->p_session) {
482 PROC_UNLOCK(targp);
483 error = EPERM;
435 goto done2;
484 goto fail;
436 }
437 if (targp->p_flag & P_EXEC) {
438 PROC_UNLOCK(targp);
439 error = EACCES;
485 }
486 if (targp->p_flag & P_EXEC) {
487 PROC_UNLOCK(targp);
488 error = EACCES;
440 goto done2;
489 goto fail;
441 }
490 }
442 } else {
491 PROC_UNLOCK(targp);
492 } else
443 targp = curp;
493 targp = curp;
444 PROC_LOCK(curp); /* XXX: not needed */
445 }
446 if (SESS_LEADER(targp)) {
494 if (SESS_LEADER(targp)) {
447 PROC_UNLOCK(targp);
448 error = EPERM;
495 error = EPERM;
449 goto done2;
496 goto fail;
450 }
451 if (uap->pgid == 0)
452 uap->pgid = targp->p_pid;
497 }
498 if (uap->pgid == 0)
499 uap->pgid = targp->p_pid;
453 else if (uap->pgid != targp->p_pid) {
454 if ((pgrp = pgfind(uap->pgid)) == 0 ||
500 if (uap->pgid == targp->p_pid) {
501 if (targp->p_pgid == uap->pgid)
502 goto done;
503 error = enterpgrp(targp, uap->pgid, newpgrp, NULL);
504 if (error == 0)
505 newpgrp = NULL;
506 } else {
507 if ((pgrp = pgfind(uap->pgid)) == NULL ||
455 pgrp->pg_session != curp->p_session) {
508 pgrp->pg_session != curp->p_session) {
456 PROC_UNLOCK(targp);
509 if (pgrp != NULL)
510 PGRP_UNLOCK(pgrp);
457 error = EPERM;
511 error = EPERM;
458 goto done2;
512 goto fail;
459 }
513 }
514 if (pgrp == targp->p_pgrp) {
515 PGRP_UNLOCK(pgrp);
516 goto done;
517 }
518 PGRP_UNLOCK(pgrp);
519 error = enterthispgrp(targp, pgrp);
460 }
520 }
461 /* XXX: We should probably hold the lock across enterpgrp. */
462 PROC_UNLOCK(targp);
463 error = enterpgrp(targp, uap->pgid, 0);
464done2:
465 sx_sunlock(&proctree_lock);
521done:
522 PGRPSESS_XUNLOCK();
523 if (newpgrp != NULL)
524 FREE(newpgrp, M_PGRP);
466 mtx_unlock(&Giant);
525 mtx_unlock(&Giant);
526 return (0);
527
528fail:
529 PGRPSESS_XUNLOCK();
530
531 KASSERT(newpgrp != NULL, ("setpgid failed and newpgrp is null."));
532 FREE(newpgrp, M_PGRP);
533
534 mtx_unlock(&Giant);
467 return (error);
468}
469
470/*
471 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
472 * compatible. It says that setting the uid/gid to euid/egid is a special
473 * case of "appropriate privilege". Once the rules are expanded out, this
474 * basically means that setuid(nnn) sets all three id's, in all permitted
475 * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid())
476 * does not set the saved id - this is dangerous for traditional BSD
477 * programs. For this reason, we *really* do not want to set
478 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
479 */
480#define POSIX_APPENDIX_B_4_2_2
481
482#ifndef _SYS_SYSPROTO_H_
483struct setuid_args {
484 uid_t uid;
485};
486#endif
487/*
488 * MPSAFE
489 */
490/* ARGSUSED */
491int
492setuid(td, uap)
493 struct thread *td;
494 struct setuid_args *uap;
495{
496 struct proc *p = td->td_proc;
497 struct ucred *newcred, *oldcred;
498 uid_t uid;
499 int error;
500
501 uid = uap->uid;
502 mtx_lock(&Giant);
503 error = 0;
504 oldcred = p->p_ucred;
505
506 /*
507 * See if we have "permission" by POSIX 1003.1 rules.
508 *
509 * Note that setuid(geteuid()) is a special case of
510 * "appropriate privileges" in appendix B.4.2.2. We need
511 * to use this clause to be compatible with traditional BSD
512 * semantics. Basically, it means that "setuid(xx)" sets all
513 * three id's (assuming you have privs).
514 *
515 * Notes on the logic. We do things in three steps.
516 * 1: We determine if the euid is going to change, and do EPERM
517 * right away. We unconditionally change the euid later if this
518 * test is satisfied, simplifying that part of the logic.
519 * 2: We determine if the real and/or saved uids are going to
520 * change. Determined by compile options.
521 * 3: Change euid last. (after tests in #2 for "appropriate privs")
522 */
523 if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */
524#ifdef _POSIX_SAVED_IDS
525 uid != oldcred->cr_svuid && /* allow setuid(saved gid) */
526#endif
527#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */
528 uid != oldcred->cr_uid && /* allow setuid(geteuid()) */
529#endif
530 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
531 goto done2;
532
533 newcred = crdup(oldcred);
534#ifdef _POSIX_SAVED_IDS
535 /*
536 * Do we have "appropriate privileges" (are we root or uid == euid)
537 * If so, we are changing the real uid and/or saved uid.
538 */
539 if (
540#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */
541 uid == oldcred->cr_uid ||
542#endif
543 suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
544#endif
545 {
546 /*
547 * Set the real uid and transfer proc count to new user.
548 */
549 if (uid != oldcred->cr_ruid) {
550 change_ruid(newcred, uid);
551 setsugid(p);
552 }
553 /*
554 * Set saved uid
555 *
556 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
557 * the security of seteuid() depends on it. B.4.2.2 says it
558 * is important that we should do this.
559 */
560 if (uid != oldcred->cr_svuid) {
561 change_svuid(newcred, uid);
562 setsugid(p);
563 }
564 }
565
566 /*
567 * In all permitted cases, we are changing the euid.
568 * Copy credentials so other references do not see our changes.
569 */
570 if (uid != oldcred->cr_uid) {
571 change_euid(newcred, uid);
572 setsugid(p);
573 }
574 p->p_ucred = newcred;
575 crfree(oldcred);
576done2:
577 mtx_unlock(&Giant);
578 return (error);
579}
580
581#ifndef _SYS_SYSPROTO_H_
582struct seteuid_args {
583 uid_t euid;
584};
585#endif
586/*
587 * MPSAFE
588 */
589/* ARGSUSED */
590int
591seteuid(td, uap)
592 struct thread *td;
593 struct seteuid_args *uap;
594{
595 struct proc *p = td->td_proc;
596 struct ucred *newcred, *oldcred;
597 uid_t euid;
598 int error;
599
600 euid = uap->euid;
601 mtx_lock(&Giant);
602 error = 0;
603 oldcred = p->p_ucred;
604 if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */
605 euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */
606 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
607 goto done2;
608 /*
609 * Everything's okay, do it. Copy credentials so other references do
610 * not see our changes.
611 */
612 newcred = crdup(oldcred);
613 if (oldcred->cr_uid != euid) {
614 change_euid(newcred, euid);
615 setsugid(p);
616 }
617 p->p_ucred = newcred;
618 crfree(oldcred);
619done2:
620 mtx_unlock(&Giant);
621 return (error);
622}
623
624#ifndef _SYS_SYSPROTO_H_
625struct setgid_args {
626 gid_t gid;
627};
628#endif
629/*
630 * MPSAFE
631 */
632/* ARGSUSED */
633int
634setgid(td, uap)
635 struct thread *td;
636 struct setgid_args *uap;
637{
638 struct proc *p = td->td_proc;
639 struct ucred *newcred, *oldcred;
640 gid_t gid;
641 int error;
642
643 gid = uap->gid;
644 mtx_lock(&Giant);
645 error = 0;
646 oldcred = p->p_ucred;
647
648 /*
649 * See if we have "permission" by POSIX 1003.1 rules.
650 *
651 * Note that setgid(getegid()) is a special case of
652 * "appropriate privileges" in appendix B.4.2.2. We need
653 * to use this clause to be compatible with traditional BSD
654 * semantics. Basically, it means that "setgid(xx)" sets all
655 * three id's (assuming you have privs).
656 *
657 * For notes on the logic here, see setuid() above.
658 */
659 if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */
660#ifdef _POSIX_SAVED_IDS
661 gid != oldcred->cr_svgid && /* allow setgid(saved gid) */
662#endif
663#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */
664 gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */
665#endif
666 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
667 goto done2;
668
669 newcred = crdup(oldcred);
670#ifdef _POSIX_SAVED_IDS
671 /*
672 * Do we have "appropriate privileges" (are we root or gid == egid)
673 * If so, we are changing the real uid and saved gid.
674 */
675 if (
676#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */
677 gid == oldcred->cr_groups[0] ||
678#endif
679 suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
680#endif
681 {
682 /*
683 * Set real gid
684 */
685 if (oldcred->cr_rgid != gid) {
686 change_rgid(newcred, gid);
687 setsugid(p);
688 }
689 /*
690 * Set saved gid
691 *
692 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
693 * the security of setegid() depends on it. B.4.2.2 says it
694 * is important that we should do this.
695 */
696 if (oldcred->cr_svgid != gid) {
697 change_svgid(newcred, gid);
698 setsugid(p);
699 }
700 }
701 /*
702 * In all cases permitted cases, we are changing the egid.
703 * Copy credentials so other references do not see our changes.
704 */
705 if (oldcred->cr_groups[0] != gid) {
706 change_egid(newcred, gid);
707 setsugid(p);
708 }
709 p->p_ucred = newcred;
710 crfree(oldcred);
711done2:
712 mtx_unlock(&Giant);
713 return (error);
714}
715
716#ifndef _SYS_SYSPROTO_H_
717struct setegid_args {
718 gid_t egid;
719};
720#endif
721/*
722 * MPSAFE
723 */
724/* ARGSUSED */
725int
726setegid(td, uap)
727 struct thread *td;
728 struct setegid_args *uap;
729{
730 struct proc *p = td->td_proc;
731 struct ucred *newcred, *oldcred;
732 gid_t egid;
733 int error;
734
735 egid = uap->egid;
736 mtx_lock(&Giant);
737 error = 0;
738 oldcred = p->p_ucred;
739 if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */
740 egid != oldcred->cr_svgid && /* allow setegid(saved gid) */
741 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
742 goto done2;
743 newcred = crdup(oldcred);
744 if (oldcred->cr_groups[0] != egid) {
745 change_egid(newcred, egid);
746 setsugid(p);
747 }
748 p->p_ucred = newcred;
749 crfree(oldcred);
750done2:
751 mtx_unlock(&Giant);
752 return (error);
753}
754
755#ifndef _SYS_SYSPROTO_H_
756struct setgroups_args {
757 u_int gidsetsize;
758 gid_t *gidset;
759};
760#endif
761/*
762 * MPSAFE
763 */
764/* ARGSUSED */
765int
766setgroups(td, uap)
767 struct thread *td;
768 struct setgroups_args *uap;
769{
770 struct proc *p = td->td_proc;
771 struct ucred *newcred, *oldcred;
772 u_int ngrp;
773 int error;
774
775 ngrp = uap->gidsetsize;
776 mtx_lock(&Giant);
777 oldcred = p->p_ucred;
778 if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
779 goto done2;
780 if (ngrp > NGROUPS) {
781 error = EINVAL;
782 goto done2;
783 }
784 /*
785 * XXX A little bit lazy here. We could test if anything has
786 * changed before crcopy() and setting P_SUGID.
787 */
788 newcred = crdup(oldcred);
789 if (ngrp < 1) {
790 /*
791 * setgroups(0, NULL) is a legitimate way of clearing the
792 * groups vector on non-BSD systems (which generally do not
793 * have the egid in the groups[0]). We risk security holes
794 * when running non-BSD software if we do not do the same.
795 */
796 newcred->cr_ngroups = 1;
797 } else {
798 if ((error = copyin((caddr_t)uap->gidset,
799 (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) {
800 crfree(newcred);
801 goto done2;
802 }
803 newcred->cr_ngroups = ngrp;
804 }
805 setsugid(p);
806 p->p_ucred = newcred;
807 crfree(oldcred);
808done2:
809 mtx_unlock(&Giant);
810 return (error);
811}
812
813#ifndef _SYS_SYSPROTO_H_
814struct setreuid_args {
815 uid_t ruid;
816 uid_t euid;
817};
818#endif
819/*
820 * MPSAFE
821 */
822/* ARGSUSED */
823int
824setreuid(td, uap)
825 register struct thread *td;
826 struct setreuid_args *uap;
827{
828 struct proc *p = td->td_proc;
829 struct ucred *newcred, *oldcred;
830 uid_t euid, ruid;
831 int error;
832
833 euid = uap->euid;
834 ruid = uap->ruid;
835 mtx_lock(&Giant);
836 error = 0;
837 oldcred = p->p_ucred;
838 if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
839 ruid != oldcred->cr_svuid) ||
840 (euid != (uid_t)-1 && euid != oldcred->cr_uid &&
841 euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
842 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
843 goto done2;
844 newcred = crdup(oldcred);
845 if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
846 change_euid(newcred, euid);
847 setsugid(p);
848 }
849 if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
850 change_ruid(newcred, ruid);
851 setsugid(p);
852 }
853 if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) &&
854 newcred->cr_svuid != newcred->cr_uid) {
855 change_svuid(newcred, newcred->cr_uid);
856 setsugid(p);
857 }
858 p->p_ucred = newcred;
859 crfree(oldcred);
860done2:
861 mtx_unlock(&Giant);
862 return (error);
863}
864
865#ifndef _SYS_SYSPROTO_H_
866struct setregid_args {
867 gid_t rgid;
868 gid_t egid;
869};
870#endif
871/*
872 * MPSAFE
873 */
874/* ARGSUSED */
875int
876setregid(td, uap)
877 register struct thread *td;
878 struct setregid_args *uap;
879{
880 struct proc *p = td->td_proc;
881 struct ucred *newcred, *oldcred;
882 gid_t egid, rgid;
883 int error;
884
885 egid = uap->egid;
886 rgid = uap->rgid;
887 mtx_lock(&Giant);
888 error = 0;
889 oldcred = p->p_ucred;
890 if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
891 rgid != oldcred->cr_svgid) ||
892 (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] &&
893 egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) &&
894 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
895 goto done2;
896 newcred = crdup(oldcred);
897 if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
898 change_egid(newcred, egid);
899 setsugid(p);
900 }
901 if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
902 change_rgid(newcred, rgid);
903 setsugid(p);
904 }
905 if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) &&
906 newcred->cr_svgid != newcred->cr_groups[0]) {
907 change_svgid(newcred, newcred->cr_groups[0]);
908 setsugid(p);
909 }
910 p->p_ucred = newcred;
911 crfree(oldcred);
912done2:
913 mtx_unlock(&Giant);
914 return (error);
915}
916
917/*
918 * setresuid(ruid, euid, suid) is like setreuid except control over the
919 * saved uid is explicit.
920 */
921
922#ifndef _SYS_SYSPROTO_H_
923struct setresuid_args {
924 uid_t ruid;
925 uid_t euid;
926 uid_t suid;
927};
928#endif
929/*
930 * MPSAFE
931 */
932/* ARGSUSED */
933int
934setresuid(td, uap)
935 register struct thread *td;
936 struct setresuid_args *uap;
937{
938 struct proc *p = td->td_proc;
939 struct ucred *newcred, *oldcred;
940 uid_t euid, ruid, suid;
941 int error;
942
943 euid = uap->euid;
944 ruid = uap->ruid;
945 suid = uap->suid;
946 mtx_lock(&Giant);
947 oldcred = p->p_ucred;
948 if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
949 ruid != oldcred->cr_svuid &&
950 ruid != oldcred->cr_uid) ||
951 (euid != (uid_t)-1 && euid != oldcred->cr_ruid &&
952 euid != oldcred->cr_svuid &&
953 euid != oldcred->cr_uid) ||
954 (suid != (uid_t)-1 && suid != oldcred->cr_ruid &&
955 suid != oldcred->cr_svuid &&
956 suid != oldcred->cr_uid)) &&
957 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
958 goto done2;
959 newcred = crdup(oldcred);
960 if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
961 change_euid(newcred, euid);
962 setsugid(p);
963 }
964 if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
965 change_ruid(newcred, ruid);
966 setsugid(p);
967 }
968 if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) {
969 change_svuid(newcred, suid);
970 setsugid(p);
971 }
972 p->p_ucred = newcred;
973 crfree(oldcred);
974 error = 0;
975done2:
976 mtx_unlock(&Giant);
977 return (error);
978}
979
980/*
981 * setresgid(rgid, egid, sgid) is like setregid except control over the
982 * saved gid is explicit.
983 */
984
985#ifndef _SYS_SYSPROTO_H_
986struct setresgid_args {
987 gid_t rgid;
988 gid_t egid;
989 gid_t sgid;
990};
991#endif
992/*
993 * MPSAFE
994 */
995/* ARGSUSED */
996int
997setresgid(td, uap)
998 register struct thread *td;
999 struct setresgid_args *uap;
1000{
1001 struct proc *p = td->td_proc;
1002 struct ucred *newcred, *oldcred;
1003 gid_t egid, rgid, sgid;
1004 int error;
1005
1006 egid = uap->egid;
1007 rgid = uap->rgid;
1008 sgid = uap->sgid;
1009 mtx_lock(&Giant);
1010 oldcred = p->p_ucred;
1011 if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
1012 rgid != oldcred->cr_svgid &&
1013 rgid != oldcred->cr_groups[0]) ||
1014 (egid != (gid_t)-1 && egid != oldcred->cr_rgid &&
1015 egid != oldcred->cr_svgid &&
1016 egid != oldcred->cr_groups[0]) ||
1017 (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid &&
1018 sgid != oldcred->cr_svgid &&
1019 sgid != oldcred->cr_groups[0])) &&
1020 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
1021 goto done2;
1022 newcred = crdup(oldcred);
1023 if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
1024 change_egid(newcred, egid);
1025 setsugid(p);
1026 }
1027 if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
1028 change_rgid(newcred, rgid);
1029 setsugid(p);
1030 }
1031 if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) {
1032 change_svgid(newcred, sgid);
1033 setsugid(p);
1034 }
1035 p->p_ucred = newcred;
1036 crfree(oldcred);
1037 error = 0;
1038done2:
1039 mtx_unlock(&Giant);
1040 return (error);
1041}
1042
1043#ifndef _SYS_SYSPROTO_H_
1044struct getresuid_args {
1045 uid_t *ruid;
1046 uid_t *euid;
1047 uid_t *suid;
1048};
1049#endif
1050/*
1051 * MPSAFE
1052 */
1053/* ARGSUSED */
1054int
1055getresuid(td, uap)
1056 register struct thread *td;
1057 struct getresuid_args *uap;
1058{
1059 struct ucred *cred;
1060 struct proc *p = td->td_proc;
1061 int error1 = 0, error2 = 0, error3 = 0;
1062
1063 mtx_lock(&Giant);
1064 cred = p->p_ucred;
1065 if (uap->ruid)
1066 error1 = copyout((caddr_t)&cred->cr_ruid,
1067 (caddr_t)uap->ruid, sizeof(cred->cr_ruid));
1068 if (uap->euid)
1069 error2 = copyout((caddr_t)&cred->cr_uid,
1070 (caddr_t)uap->euid, sizeof(cred->cr_uid));
1071 if (uap->suid)
1072 error3 = copyout((caddr_t)&cred->cr_svuid,
1073 (caddr_t)uap->suid, sizeof(cred->cr_svuid));
1074 mtx_unlock(&Giant);
1075 return (error1 ? error1 : error2 ? error2 : error3);
1076}
1077
1078#ifndef _SYS_SYSPROTO_H_
1079struct getresgid_args {
1080 gid_t *rgid;
1081 gid_t *egid;
1082 gid_t *sgid;
1083};
1084#endif
1085/*
1086 * MPSAFE
1087 */
1088/* ARGSUSED */
1089int
1090getresgid(td, uap)
1091 register struct thread *td;
1092 struct getresgid_args *uap;
1093{
1094 struct ucred *cred;
1095 struct proc *p = td->td_proc;
1096 int error1 = 0, error2 = 0, error3 = 0;
1097
1098 mtx_lock(&Giant);
1099 cred = p->p_ucred;
1100 if (uap->rgid)
1101 error1 = copyout((caddr_t)&cred->cr_rgid,
1102 (caddr_t)uap->rgid, sizeof(cred->cr_rgid));
1103 if (uap->egid)
1104 error2 = copyout((caddr_t)&cred->cr_groups[0],
1105 (caddr_t)uap->egid, sizeof(cred->cr_groups[0]));
1106 if (uap->sgid)
1107 error3 = copyout((caddr_t)&cred->cr_svgid,
1108 (caddr_t)uap->sgid, sizeof(cred->cr_svgid));
1109 mtx_unlock(&Giant);
1110 return (error1 ? error1 : error2 ? error2 : error3);
1111}
1112
1113#ifndef _SYS_SYSPROTO_H_
1114struct issetugid_args {
1115 int dummy;
1116};
1117#endif
1118/*
1119 * NOT MPSAFE?
1120 */
1121/* ARGSUSED */
1122int
1123issetugid(td, uap)
1124 register struct thread *td;
1125 struct issetugid_args *uap;
1126{
1127 struct proc *p = td->td_proc;
1128
1129 /*
1130 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
1131 * we use P_SUGID because we consider changing the owners as
1132 * "tainting" as well.
1133 * This is significant for procs that start as root and "become"
1134 * a user without an exec - programs cannot know *everything*
1135 * that libc *might* have put in their data segment.
1136 */
535 return (error);
536}
537
538/*
539 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
540 * compatible. It says that setting the uid/gid to euid/egid is a special
541 * case of "appropriate privilege". Once the rules are expanded out, this
542 * basically means that setuid(nnn) sets all three id's, in all permitted
543 * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid())
544 * does not set the saved id - this is dangerous for traditional BSD
545 * programs. For this reason, we *really* do not want to set
546 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
547 */
548#define POSIX_APPENDIX_B_4_2_2
549
550#ifndef _SYS_SYSPROTO_H_
551struct setuid_args {
552 uid_t uid;
553};
554#endif
555/*
556 * MPSAFE
557 */
558/* ARGSUSED */
559int
560setuid(td, uap)
561 struct thread *td;
562 struct setuid_args *uap;
563{
564 struct proc *p = td->td_proc;
565 struct ucred *newcred, *oldcred;
566 uid_t uid;
567 int error;
568
569 uid = uap->uid;
570 mtx_lock(&Giant);
571 error = 0;
572 oldcred = p->p_ucred;
573
574 /*
575 * See if we have "permission" by POSIX 1003.1 rules.
576 *
577 * Note that setuid(geteuid()) is a special case of
578 * "appropriate privileges" in appendix B.4.2.2. We need
579 * to use this clause to be compatible with traditional BSD
580 * semantics. Basically, it means that "setuid(xx)" sets all
581 * three id's (assuming you have privs).
582 *
583 * Notes on the logic. We do things in three steps.
584 * 1: We determine if the euid is going to change, and do EPERM
585 * right away. We unconditionally change the euid later if this
586 * test is satisfied, simplifying that part of the logic.
587 * 2: We determine if the real and/or saved uids are going to
588 * change. Determined by compile options.
589 * 3: Change euid last. (after tests in #2 for "appropriate privs")
590 */
591 if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */
592#ifdef _POSIX_SAVED_IDS
593 uid != oldcred->cr_svuid && /* allow setuid(saved gid) */
594#endif
595#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */
596 uid != oldcred->cr_uid && /* allow setuid(geteuid()) */
597#endif
598 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
599 goto done2;
600
601 newcred = crdup(oldcred);
602#ifdef _POSIX_SAVED_IDS
603 /*
604 * Do we have "appropriate privileges" (are we root or uid == euid)
605 * If so, we are changing the real uid and/or saved uid.
606 */
607 if (
608#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */
609 uid == oldcred->cr_uid ||
610#endif
611 suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
612#endif
613 {
614 /*
615 * Set the real uid and transfer proc count to new user.
616 */
617 if (uid != oldcred->cr_ruid) {
618 change_ruid(newcred, uid);
619 setsugid(p);
620 }
621 /*
622 * Set saved uid
623 *
624 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
625 * the security of seteuid() depends on it. B.4.2.2 says it
626 * is important that we should do this.
627 */
628 if (uid != oldcred->cr_svuid) {
629 change_svuid(newcred, uid);
630 setsugid(p);
631 }
632 }
633
634 /*
635 * In all permitted cases, we are changing the euid.
636 * Copy credentials so other references do not see our changes.
637 */
638 if (uid != oldcred->cr_uid) {
639 change_euid(newcred, uid);
640 setsugid(p);
641 }
642 p->p_ucred = newcred;
643 crfree(oldcred);
644done2:
645 mtx_unlock(&Giant);
646 return (error);
647}
648
649#ifndef _SYS_SYSPROTO_H_
650struct seteuid_args {
651 uid_t euid;
652};
653#endif
654/*
655 * MPSAFE
656 */
657/* ARGSUSED */
658int
659seteuid(td, uap)
660 struct thread *td;
661 struct seteuid_args *uap;
662{
663 struct proc *p = td->td_proc;
664 struct ucred *newcred, *oldcred;
665 uid_t euid;
666 int error;
667
668 euid = uap->euid;
669 mtx_lock(&Giant);
670 error = 0;
671 oldcred = p->p_ucred;
672 if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */
673 euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */
674 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
675 goto done2;
676 /*
677 * Everything's okay, do it. Copy credentials so other references do
678 * not see our changes.
679 */
680 newcred = crdup(oldcred);
681 if (oldcred->cr_uid != euid) {
682 change_euid(newcred, euid);
683 setsugid(p);
684 }
685 p->p_ucred = newcred;
686 crfree(oldcred);
687done2:
688 mtx_unlock(&Giant);
689 return (error);
690}
691
692#ifndef _SYS_SYSPROTO_H_
693struct setgid_args {
694 gid_t gid;
695};
696#endif
697/*
698 * MPSAFE
699 */
700/* ARGSUSED */
701int
702setgid(td, uap)
703 struct thread *td;
704 struct setgid_args *uap;
705{
706 struct proc *p = td->td_proc;
707 struct ucred *newcred, *oldcred;
708 gid_t gid;
709 int error;
710
711 gid = uap->gid;
712 mtx_lock(&Giant);
713 error = 0;
714 oldcred = p->p_ucred;
715
716 /*
717 * See if we have "permission" by POSIX 1003.1 rules.
718 *
719 * Note that setgid(getegid()) is a special case of
720 * "appropriate privileges" in appendix B.4.2.2. We need
721 * to use this clause to be compatible with traditional BSD
722 * semantics. Basically, it means that "setgid(xx)" sets all
723 * three id's (assuming you have privs).
724 *
725 * For notes on the logic here, see setuid() above.
726 */
727 if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */
728#ifdef _POSIX_SAVED_IDS
729 gid != oldcred->cr_svgid && /* allow setgid(saved gid) */
730#endif
731#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */
732 gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */
733#endif
734 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
735 goto done2;
736
737 newcred = crdup(oldcred);
738#ifdef _POSIX_SAVED_IDS
739 /*
740 * Do we have "appropriate privileges" (are we root or gid == egid)
741 * If so, we are changing the real uid and saved gid.
742 */
743 if (
744#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */
745 gid == oldcred->cr_groups[0] ||
746#endif
747 suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
748#endif
749 {
750 /*
751 * Set real gid
752 */
753 if (oldcred->cr_rgid != gid) {
754 change_rgid(newcred, gid);
755 setsugid(p);
756 }
757 /*
758 * Set saved gid
759 *
760 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
761 * the security of setegid() depends on it. B.4.2.2 says it
762 * is important that we should do this.
763 */
764 if (oldcred->cr_svgid != gid) {
765 change_svgid(newcred, gid);
766 setsugid(p);
767 }
768 }
769 /*
770 * In all cases permitted cases, we are changing the egid.
771 * Copy credentials so other references do not see our changes.
772 */
773 if (oldcred->cr_groups[0] != gid) {
774 change_egid(newcred, gid);
775 setsugid(p);
776 }
777 p->p_ucred = newcred;
778 crfree(oldcred);
779done2:
780 mtx_unlock(&Giant);
781 return (error);
782}
783
784#ifndef _SYS_SYSPROTO_H_
785struct setegid_args {
786 gid_t egid;
787};
788#endif
789/*
790 * MPSAFE
791 */
792/* ARGSUSED */
793int
794setegid(td, uap)
795 struct thread *td;
796 struct setegid_args *uap;
797{
798 struct proc *p = td->td_proc;
799 struct ucred *newcred, *oldcred;
800 gid_t egid;
801 int error;
802
803 egid = uap->egid;
804 mtx_lock(&Giant);
805 error = 0;
806 oldcred = p->p_ucred;
807 if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */
808 egid != oldcred->cr_svgid && /* allow setegid(saved gid) */
809 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
810 goto done2;
811 newcred = crdup(oldcred);
812 if (oldcred->cr_groups[0] != egid) {
813 change_egid(newcred, egid);
814 setsugid(p);
815 }
816 p->p_ucred = newcred;
817 crfree(oldcred);
818done2:
819 mtx_unlock(&Giant);
820 return (error);
821}
822
823#ifndef _SYS_SYSPROTO_H_
824struct setgroups_args {
825 u_int gidsetsize;
826 gid_t *gidset;
827};
828#endif
829/*
830 * MPSAFE
831 */
832/* ARGSUSED */
833int
834setgroups(td, uap)
835 struct thread *td;
836 struct setgroups_args *uap;
837{
838 struct proc *p = td->td_proc;
839 struct ucred *newcred, *oldcred;
840 u_int ngrp;
841 int error;
842
843 ngrp = uap->gidsetsize;
844 mtx_lock(&Giant);
845 oldcred = p->p_ucred;
846 if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
847 goto done2;
848 if (ngrp > NGROUPS) {
849 error = EINVAL;
850 goto done2;
851 }
852 /*
853 * XXX A little bit lazy here. We could test if anything has
854 * changed before crcopy() and setting P_SUGID.
855 */
856 newcred = crdup(oldcred);
857 if (ngrp < 1) {
858 /*
859 * setgroups(0, NULL) is a legitimate way of clearing the
860 * groups vector on non-BSD systems (which generally do not
861 * have the egid in the groups[0]). We risk security holes
862 * when running non-BSD software if we do not do the same.
863 */
864 newcred->cr_ngroups = 1;
865 } else {
866 if ((error = copyin((caddr_t)uap->gidset,
867 (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) {
868 crfree(newcred);
869 goto done2;
870 }
871 newcred->cr_ngroups = ngrp;
872 }
873 setsugid(p);
874 p->p_ucred = newcred;
875 crfree(oldcred);
876done2:
877 mtx_unlock(&Giant);
878 return (error);
879}
880
881#ifndef _SYS_SYSPROTO_H_
882struct setreuid_args {
883 uid_t ruid;
884 uid_t euid;
885};
886#endif
887/*
888 * MPSAFE
889 */
890/* ARGSUSED */
891int
892setreuid(td, uap)
893 register struct thread *td;
894 struct setreuid_args *uap;
895{
896 struct proc *p = td->td_proc;
897 struct ucred *newcred, *oldcred;
898 uid_t euid, ruid;
899 int error;
900
901 euid = uap->euid;
902 ruid = uap->ruid;
903 mtx_lock(&Giant);
904 error = 0;
905 oldcred = p->p_ucred;
906 if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
907 ruid != oldcred->cr_svuid) ||
908 (euid != (uid_t)-1 && euid != oldcred->cr_uid &&
909 euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
910 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
911 goto done2;
912 newcred = crdup(oldcred);
913 if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
914 change_euid(newcred, euid);
915 setsugid(p);
916 }
917 if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
918 change_ruid(newcred, ruid);
919 setsugid(p);
920 }
921 if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) &&
922 newcred->cr_svuid != newcred->cr_uid) {
923 change_svuid(newcred, newcred->cr_uid);
924 setsugid(p);
925 }
926 p->p_ucred = newcred;
927 crfree(oldcred);
928done2:
929 mtx_unlock(&Giant);
930 return (error);
931}
932
933#ifndef _SYS_SYSPROTO_H_
934struct setregid_args {
935 gid_t rgid;
936 gid_t egid;
937};
938#endif
939/*
940 * MPSAFE
941 */
942/* ARGSUSED */
943int
944setregid(td, uap)
945 register struct thread *td;
946 struct setregid_args *uap;
947{
948 struct proc *p = td->td_proc;
949 struct ucred *newcred, *oldcred;
950 gid_t egid, rgid;
951 int error;
952
953 egid = uap->egid;
954 rgid = uap->rgid;
955 mtx_lock(&Giant);
956 error = 0;
957 oldcred = p->p_ucred;
958 if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
959 rgid != oldcred->cr_svgid) ||
960 (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] &&
961 egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) &&
962 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
963 goto done2;
964 newcred = crdup(oldcred);
965 if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
966 change_egid(newcred, egid);
967 setsugid(p);
968 }
969 if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
970 change_rgid(newcred, rgid);
971 setsugid(p);
972 }
973 if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) &&
974 newcred->cr_svgid != newcred->cr_groups[0]) {
975 change_svgid(newcred, newcred->cr_groups[0]);
976 setsugid(p);
977 }
978 p->p_ucred = newcred;
979 crfree(oldcred);
980done2:
981 mtx_unlock(&Giant);
982 return (error);
983}
984
985/*
986 * setresuid(ruid, euid, suid) is like setreuid except control over the
987 * saved uid is explicit.
988 */
989
990#ifndef _SYS_SYSPROTO_H_
991struct setresuid_args {
992 uid_t ruid;
993 uid_t euid;
994 uid_t suid;
995};
996#endif
997/*
998 * MPSAFE
999 */
1000/* ARGSUSED */
1001int
1002setresuid(td, uap)
1003 register struct thread *td;
1004 struct setresuid_args *uap;
1005{
1006 struct proc *p = td->td_proc;
1007 struct ucred *newcred, *oldcred;
1008 uid_t euid, ruid, suid;
1009 int error;
1010
1011 euid = uap->euid;
1012 ruid = uap->ruid;
1013 suid = uap->suid;
1014 mtx_lock(&Giant);
1015 oldcred = p->p_ucred;
1016 if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
1017 ruid != oldcred->cr_svuid &&
1018 ruid != oldcred->cr_uid) ||
1019 (euid != (uid_t)-1 && euid != oldcred->cr_ruid &&
1020 euid != oldcred->cr_svuid &&
1021 euid != oldcred->cr_uid) ||
1022 (suid != (uid_t)-1 && suid != oldcred->cr_ruid &&
1023 suid != oldcred->cr_svuid &&
1024 suid != oldcred->cr_uid)) &&
1025 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
1026 goto done2;
1027 newcred = crdup(oldcred);
1028 if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
1029 change_euid(newcred, euid);
1030 setsugid(p);
1031 }
1032 if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
1033 change_ruid(newcred, ruid);
1034 setsugid(p);
1035 }
1036 if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) {
1037 change_svuid(newcred, suid);
1038 setsugid(p);
1039 }
1040 p->p_ucred = newcred;
1041 crfree(oldcred);
1042 error = 0;
1043done2:
1044 mtx_unlock(&Giant);
1045 return (error);
1046}
1047
1048/*
1049 * setresgid(rgid, egid, sgid) is like setregid except control over the
1050 * saved gid is explicit.
1051 */
1052
1053#ifndef _SYS_SYSPROTO_H_
1054struct setresgid_args {
1055 gid_t rgid;
1056 gid_t egid;
1057 gid_t sgid;
1058};
1059#endif
1060/*
1061 * MPSAFE
1062 */
1063/* ARGSUSED */
1064int
1065setresgid(td, uap)
1066 register struct thread *td;
1067 struct setresgid_args *uap;
1068{
1069 struct proc *p = td->td_proc;
1070 struct ucred *newcred, *oldcred;
1071 gid_t egid, rgid, sgid;
1072 int error;
1073
1074 egid = uap->egid;
1075 rgid = uap->rgid;
1076 sgid = uap->sgid;
1077 mtx_lock(&Giant);
1078 oldcred = p->p_ucred;
1079 if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
1080 rgid != oldcred->cr_svgid &&
1081 rgid != oldcred->cr_groups[0]) ||
1082 (egid != (gid_t)-1 && egid != oldcred->cr_rgid &&
1083 egid != oldcred->cr_svgid &&
1084 egid != oldcred->cr_groups[0]) ||
1085 (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid &&
1086 sgid != oldcred->cr_svgid &&
1087 sgid != oldcred->cr_groups[0])) &&
1088 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
1089 goto done2;
1090 newcred = crdup(oldcred);
1091 if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
1092 change_egid(newcred, egid);
1093 setsugid(p);
1094 }
1095 if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
1096 change_rgid(newcred, rgid);
1097 setsugid(p);
1098 }
1099 if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) {
1100 change_svgid(newcred, sgid);
1101 setsugid(p);
1102 }
1103 p->p_ucred = newcred;
1104 crfree(oldcred);
1105 error = 0;
1106done2:
1107 mtx_unlock(&Giant);
1108 return (error);
1109}
1110
1111#ifndef _SYS_SYSPROTO_H_
1112struct getresuid_args {
1113 uid_t *ruid;
1114 uid_t *euid;
1115 uid_t *suid;
1116};
1117#endif
1118/*
1119 * MPSAFE
1120 */
1121/* ARGSUSED */
1122int
1123getresuid(td, uap)
1124 register struct thread *td;
1125 struct getresuid_args *uap;
1126{
1127 struct ucred *cred;
1128 struct proc *p = td->td_proc;
1129 int error1 = 0, error2 = 0, error3 = 0;
1130
1131 mtx_lock(&Giant);
1132 cred = p->p_ucred;
1133 if (uap->ruid)
1134 error1 = copyout((caddr_t)&cred->cr_ruid,
1135 (caddr_t)uap->ruid, sizeof(cred->cr_ruid));
1136 if (uap->euid)
1137 error2 = copyout((caddr_t)&cred->cr_uid,
1138 (caddr_t)uap->euid, sizeof(cred->cr_uid));
1139 if (uap->suid)
1140 error3 = copyout((caddr_t)&cred->cr_svuid,
1141 (caddr_t)uap->suid, sizeof(cred->cr_svuid));
1142 mtx_unlock(&Giant);
1143 return (error1 ? error1 : error2 ? error2 : error3);
1144}
1145
1146#ifndef _SYS_SYSPROTO_H_
1147struct getresgid_args {
1148 gid_t *rgid;
1149 gid_t *egid;
1150 gid_t *sgid;
1151};
1152#endif
1153/*
1154 * MPSAFE
1155 */
1156/* ARGSUSED */
1157int
1158getresgid(td, uap)
1159 register struct thread *td;
1160 struct getresgid_args *uap;
1161{
1162 struct ucred *cred;
1163 struct proc *p = td->td_proc;
1164 int error1 = 0, error2 = 0, error3 = 0;
1165
1166 mtx_lock(&Giant);
1167 cred = p->p_ucred;
1168 if (uap->rgid)
1169 error1 = copyout((caddr_t)&cred->cr_rgid,
1170 (caddr_t)uap->rgid, sizeof(cred->cr_rgid));
1171 if (uap->egid)
1172 error2 = copyout((caddr_t)&cred->cr_groups[0],
1173 (caddr_t)uap->egid, sizeof(cred->cr_groups[0]));
1174 if (uap->sgid)
1175 error3 = copyout((caddr_t)&cred->cr_svgid,
1176 (caddr_t)uap->sgid, sizeof(cred->cr_svgid));
1177 mtx_unlock(&Giant);
1178 return (error1 ? error1 : error2 ? error2 : error3);
1179}
1180
1181#ifndef _SYS_SYSPROTO_H_
1182struct issetugid_args {
1183 int dummy;
1184};
1185#endif
1186/*
1187 * NOT MPSAFE?
1188 */
1189/* ARGSUSED */
1190int
1191issetugid(td, uap)
1192 register struct thread *td;
1193 struct issetugid_args *uap;
1194{
1195 struct proc *p = td->td_proc;
1196
1197 /*
1198 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
1199 * we use P_SUGID because we consider changing the owners as
1200 * "tainting" as well.
1201 * This is significant for procs that start as root and "become"
1202 * a user without an exec - programs cannot know *everything*
1203 * that libc *might* have put in their data segment.
1204 */
1205 PROC_LOCK(p);
1137 td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
1206 td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
1207 PROC_UNLOCK(p);
1138 return (0);
1139}
1140
1141/*
1142 * MPSAFE
1143 */
1144int
1145__setugid(td, uap)
1146 struct thread *td;
1147 struct __setugid_args *uap;
1148{
1149#ifdef REGRESSION
1150 int error;
1151
1152 mtx_lock(&Giant);
1153 error = 0;
1154 switch (uap->flag) {
1155 case 0:
1208 return (0);
1209}
1210
1211/*
1212 * MPSAFE
1213 */
1214int
1215__setugid(td, uap)
1216 struct thread *td;
1217 struct __setugid_args *uap;
1218{
1219#ifdef REGRESSION
1220 int error;
1221
1222 mtx_lock(&Giant);
1223 error = 0;
1224 switch (uap->flag) {
1225 case 0:
1226 PROC_LOCK(td->td_proc);
1156 td->td_proc->p_flag &= ~P_SUGID;
1227 td->td_proc->p_flag &= ~P_SUGID;
1228 PROC_UNLOCK(td->td_proc);
1157 break;
1158 case 1:
1229 break;
1230 case 1:
1231 PROC_LOCK(td->td_proc);
1159 td->td_proc->p_flag |= P_SUGID;
1232 td->td_proc->p_flag |= P_SUGID;
1233 PROC_UNLOCK(td->td_proc);
1160 break;
1161 default:
1162 error = EINVAL;
1163 break;
1164 }
1165 mtx_unlock(&Giant);
1166 return (error);
1167#else /* !REGRESSION */
1168
1169 return (ENOSYS);
1170#endif /* REGRESSION */
1171}
1172
1173/*
1174 * Check if gid is a member of the group set.
1175 */
1176int
1177groupmember(gid, cred)
1178 gid_t gid;
1179 struct ucred *cred;
1180{
1181 register gid_t *gp;
1182 gid_t *egp;
1183
1184 egp = &(cred->cr_groups[cred->cr_ngroups]);
1185 for (gp = cred->cr_groups; gp < egp; gp++)
1186 if (*gp == gid)
1187 return (1);
1188 return (0);
1189}
1190
1191/*
1192 * `suser_enabled' (which can be set by the security.suser_enabled
1193 * sysctl) determines whether the system 'super-user' policy is in effect.
1194 * If it is nonzero, an effective uid of 0 connotes special privilege,
1195 * overriding many mandatory and discretionary protections. If it is zero,
1196 * uid 0 is offered no special privilege in the kernel security policy.
1197 * Setting it to zero may seriously impact the functionality of many
1198 * existing userland programs, and should not be done without careful
1199 * consideration of the consequences.
1200 */
1201int suser_enabled = 1;
1202SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW,
1203 &suser_enabled, 0, "processes with uid 0 have privilege");
1204TUNABLE_INT("security.bsd.suser_enabled", &suser_enabled);
1205
1206/*
1207 * Test whether the specified credentials imply "super-user" privilege.
1208 * Return 0 or EPERM.
1209 */
1210int
1211suser(p)
1212 struct proc *p;
1213{
1214
1215 return (suser_xxx(0, p, 0));
1216}
1217
1218/*
1219 * version for when the thread pointer is available and not the proc.
1220 * (saves having to include proc.h into every file that needs to do the change.)
1221 */
1222int
1223suser_td(td)
1224 struct thread *td;
1225{
1226 return (suser_xxx(0, td->td_proc, 0));
1227}
1228
1229/*
1230 * wrapper to use if you have the thread on hand but not the proc.
1231 */
1232int
1233suser_xxx_td(cred, td, flag)
1234 struct ucred *cred;
1235 struct thread *td;
1236 int flag;
1237{
1238 return(suser_xxx(cred, td->td_proc, flag));
1239}
1240
1241int
1242suser_xxx(cred, proc, flag)
1243 struct ucred *cred;
1244 struct proc *proc;
1245 int flag;
1246{
1247 if (!suser_enabled)
1248 return (EPERM);
1249 if (!cred && !proc) {
1250 printf("suser_xxx(): THINK!\n");
1251 return (EPERM);
1252 }
1253 if (cred == NULL)
1254 cred = proc->p_ucred;
1255 if (cred->cr_uid != 0)
1256 return (EPERM);
1257 if (jailed(cred) && !(flag & PRISON_ROOT))
1258 return (EPERM);
1259 return (0);
1260}
1261
1262/*
1263 * Test the active securelevel against a given level. securelevel_gt()
1264 * implements (securelevel > level). securelevel_ge() implements
1265 * (securelevel >= level). Note that the logic is inverted -- these
1266 * functions return EPERM on "success" and 0 on "failure".
1267 *
1268 * cr is permitted to be NULL for the time being, as there were some
1269 * existing securelevel checks that occurred without a process/credential
1270 * context. In the future this will be disallowed, so a kernel message
1271 * is displayed.
1272 */
1273int
1274securelevel_gt(struct ucred *cr, int level)
1275{
1276 int active_securelevel;
1277
1278 active_securelevel = securelevel;
1279 if (cr == NULL)
1280 printf("securelevel_gt: cr is NULL\n");
1281 if (cr->cr_prison != NULL) {
1282 mtx_lock(&cr->cr_prison->pr_mtx);
1283 active_securelevel = imax(cr->cr_prison->pr_securelevel,
1284 active_securelevel);
1285 mtx_unlock(&cr->cr_prison->pr_mtx);
1286 }
1287 return (active_securelevel > level ? EPERM : 0);
1288}
1289
1290int
1291securelevel_ge(struct ucred *cr, int level)
1292{
1293 int active_securelevel;
1294
1295 active_securelevel = securelevel;
1296 if (cr == NULL)
1297 printf("securelevel_gt: cr is NULL\n");
1298 if (cr->cr_prison != NULL) {
1299 mtx_lock(&cr->cr_prison->pr_mtx);
1300 active_securelevel = imax(cr->cr_prison->pr_securelevel,
1301 active_securelevel);
1302 mtx_unlock(&cr->cr_prison->pr_mtx);
1303 }
1304 return (active_securelevel >= level ? EPERM : 0);
1305}
1306
1307/*
1308 * 'see_other_uids' determines whether or not visibility of processes
1309 * and sockets with credentials holding different real uids is possible
1310 * using a variety of system MIBs.
1311 * XXX: data declarations should be together near the beginning of the file.
1312 */
1313static int see_other_uids = 1;
1314SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW,
1315 &see_other_uids, 0,
1316 "Unprivileged processes may see subjects/objects with different real uid");
1317
1318/*-
1319 * Determine if u1 "can see" the subject specified by u2.
1320 * Returns: 0 for permitted, an errno value otherwise
1321 * Locks: none
1322 * References: *u1 and *u2 must not change during the call
1323 * u1 may equal u2, in which case only one reference is required
1324 */
1325int
1326cr_cansee(struct ucred *u1, struct ucred *u2)
1327{
1328 int error;
1329
1330 if ((error = prison_check(u1, u2)))
1331 return (error);
1332 if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) {
1333 if (suser_xxx(u1, NULL, PRISON_ROOT) != 0)
1334 return (ESRCH);
1335 }
1336 return (0);
1337}
1338
1339/*-
1340 * Determine if p1 "can see" the subject specified by p2.
1341 * Returns: 0 for permitted, an errno value otherwise
1342 * Locks: Sufficient locks to protect p1->p_ucred and p2->p_ucred must
1343 * be held. Normally, p1 will be curproc, and a lock must be held
1344 * for p2.
1345 * References: p1 and p2 must be valid for the lifetime of the call
1346 */
1347int
1348p_cansee(struct proc *p1, struct proc *p2)
1349{
1350
1351 /* Wrap cr_cansee() for all functionality. */
1352 return (cr_cansee(p1->p_ucred, p2->p_ucred));
1353}
1354
1355/*-
1356 * Determine whether cred may deliver the specified signal to proc.
1357 * Returns: 0 for permitted, an errno value otherwise.
1358 * Locks: A lock must be held for proc.
1359 * References: cred and proc must be valid for the lifetime of the call.
1360 */
1361int
1362cr_cansignal(struct ucred *cred, struct proc *proc, int signum)
1363{
1364 int error;
1365
1366 /*
1367 * Jail semantics limit the scope of signalling to proc in the
1368 * same jail as cred, if cred is in jail.
1369 */
1370 error = prison_check(cred, proc->p_ucred);
1371 if (error)
1372 return (error);
1373
1374 /*
1375 * UNIX signal semantics depend on the status of the P_SUGID
1376 * bit on the target process. If the bit is set, then additional
1377 * restrictions are placed on the set of available signals.
1378 */
1379 if (proc->p_flag & P_SUGID) {
1380 switch (signum) {
1381 case 0:
1382 case SIGKILL:
1383 case SIGINT:
1384 case SIGTERM:
1385 case SIGSTOP:
1386 case SIGTTIN:
1387 case SIGTTOU:
1388 case SIGTSTP:
1389 case SIGHUP:
1390 case SIGUSR1:
1391 case SIGUSR2:
1392 /*
1393 * Generally, permit job and terminal control
1394 * signals.
1395 */
1396 break;
1397 default:
1398 /* Not permitted without privilege. */
1399 error = suser_xxx(cred, NULL, PRISON_ROOT);
1400 if (error)
1401 return (error);
1402 }
1403 }
1404
1405 /*
1406 * Generally, the target credential's ruid or svuid must match the
1407 * subject credential's ruid or euid.
1408 */
1409 if (cred->cr_ruid != proc->p_ucred->cr_ruid &&
1410 cred->cr_ruid != proc->p_ucred->cr_svuid &&
1411 cred->cr_uid != proc->p_ucred->cr_ruid &&
1412 cred->cr_uid != proc->p_ucred->cr_svuid) {
1413 /* Not permitted without privilege. */
1414 error = suser_xxx(cred, NULL, PRISON_ROOT);
1415 if (error)
1416 return (error);
1417 }
1418
1419 return (0);
1420}
1421
1422
1423/*-
1424 * Determine whether p1 may deliver the specified signal to p2.
1425 * Returns: 0 for permitted, an errno value otherwise
1426 * Locks: Sufficient locks to protect various components of p1 and p2
1427 * must be held. Normally, p1 will be curproc, and a lock must
1428 * be held for p2.
1429 * References: p1 and p2 must be valid for the lifetime of the call
1430 */
1431int
1432p_cansignal(struct proc *p1, struct proc *p2, int signum)
1433{
1434
1435 if (p1 == p2)
1436 return (0);
1437
1438 /*
1439 * UNIX signalling semantics require that processes in the same
1440 * session always be able to deliver SIGCONT to one another,
1441 * overriding the remaining protections.
1442 */
1443 if (signum == SIGCONT && p1->p_session == p2->p_session)
1444 return (0);
1445
1446 return (cr_cansignal(p1->p_ucred, p2, signum));
1447}
1448
1449/*-
1450 * Determine whether p1 may reschedule p2.
1451 * Returns: 0 for permitted, an errno value otherwise
1452 * Locks: Sufficient locks to protect various components of p1 and p2
1453 * must be held. Normally, p1 will be curproc, and a lock must
1454 * be held for p2.
1455 * References: p1 and p2 must be valid for the lifetime of the call
1456 */
1457int
1458p_cansched(struct proc *p1, struct proc *p2)
1459{
1460 int error;
1461
1462 if (p1 == p2)
1463 return (0);
1464 if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1465 return (error);
1466 if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid)
1467 return (0);
1468 if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid)
1469 return (0);
1470 if (suser_xxx(0, p1, PRISON_ROOT) == 0)
1471 return (0);
1472
1473#ifdef CAPABILITIES
1474 if (!cap_check(NULL, p1, CAP_SYS_NICE, PRISON_ROOT))
1475 return (0);
1476#endif
1477
1478 return (EPERM);
1479}
1480
1481/*
1482 * The 'unprivileged_proc_debug' flag may be used to disable a variety of
1483 * unprivileged inter-process debugging services, including some procfs
1484 * functionality, ptrace(), and ktrace(). In the past, inter-process
1485 * debugging has been involved in a variety of security problems, and sites
1486 * not requiring the service might choose to disable it when hardening
1487 * systems.
1488 *
1489 * XXX: Should modifying and reading this variable require locking?
1490 * XXX: data declarations should be together near the beginning of the file.
1491 */
1492static int unprivileged_proc_debug = 1;
1493SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW,
1494 &unprivileged_proc_debug, 0,
1495 "Unprivileged processes may use process debugging facilities");
1496
1497/*-
1498 * Determine whether p1 may debug p2.
1499 * Returns: 0 for permitted, an errno value otherwise
1500 * Locks: Sufficient locks to protect various components of p1 and p2
1501 * must be held. Normally, p1 will be curproc, and a lock must
1502 * be held for p2.
1503 * References: p1 and p2 must be valid for the lifetime of the call
1504 */
1505int
1506p_candebug(struct proc *p1, struct proc *p2)
1507{
1508 int credentialchanged, error, grpsubset, i, uidsubset;
1509
1510 if (!unprivileged_proc_debug) {
1511 error = suser_xxx(NULL, p1, PRISON_ROOT);
1512 if (error)
1513 return (error);
1514 }
1515 if (p1 == p2)
1516 return (0);
1517 if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1518 return (error);
1519
1520 /*
1521 * Is p2's group set a subset of p1's effective group set? This
1522 * includes p2's egid, group access list, rgid, and svgid.
1523 */
1524 grpsubset = 1;
1525 for (i = 0; i < p2->p_ucred->cr_ngroups; i++) {
1526 if (!groupmember(p2->p_ucred->cr_groups[i], p1->p_ucred)) {
1527 grpsubset = 0;
1528 break;
1529 }
1530 }
1531 grpsubset = grpsubset &&
1532 groupmember(p2->p_ucred->cr_rgid, p1->p_ucred) &&
1533 groupmember(p2->p_ucred->cr_svgid, p1->p_ucred);
1534
1535 /*
1536 * Are the uids present in p2's credential equal to p1's
1537 * effective uid? This includes p2's euid, svuid, and ruid.
1538 */
1539 uidsubset = (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid &&
1540 p1->p_ucred->cr_uid == p2->p_ucred->cr_svuid &&
1541 p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid);
1542
1543 /*
1544 * Has the credential of the process changed since the last exec()?
1545 */
1546 credentialchanged = (p2->p_flag & P_SUGID);
1547
1548 /*
1549 * If p2's gids aren't a subset, or the uids aren't a subset,
1550 * or the credential has changed, require appropriate privilege
1551 * for p1 to debug p2. For POSIX.1e capabilities, this will
1552 * require CAP_SYS_PTRACE.
1553 */
1554 if (!grpsubset || !uidsubset || credentialchanged) {
1555 error = suser_xxx(NULL, p1, PRISON_ROOT);
1556 if (error)
1557 return (error);
1558 }
1559
1560 /* Can't trace init when securelevel > 0. */
1561 if (p2 == initproc) {
1562 error = securelevel_gt(p1->p_ucred, 0);
1563 if (error)
1564 return (error);
1565 }
1566
1567 /*
1568 * Can't trace a process that's currently exec'ing.
1569 * XXX: Note, this is not a security policy decision, it's a
1570 * basic correctness/functionality decision. Therefore, this check
1571 * should be moved to the caller's of p_candebug().
1572 */
1573 if ((p2->p_flag & P_INEXEC) != 0)
1574 return (EAGAIN);
1575
1576 return (0);
1577}
1578
1579/*
1580 * Allocate a zeroed cred structure.
1581 */
1582struct ucred *
1583crget()
1584{
1585 register struct ucred *cr;
1586
1587 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO);
1588 cr->cr_ref = 1;
1589 cr->cr_mtxp = mtx_pool_find(cr);
1590 return (cr);
1591}
1592
1593/*
1594 * Claim another reference to a ucred structure.
1595 */
1596struct ucred *
1597crhold(cr)
1598 struct ucred *cr;
1599{
1600
1601 mtx_lock(cr->cr_mtxp);
1602 cr->cr_ref++;
1603 mtx_unlock(cr->cr_mtxp);
1604 return (cr);
1605}
1606
1607/*
1608 * Free a cred structure.
1609 * Throws away space when ref count gets to 0.
1610 */
1611void
1612crfree(cr)
1613 struct ucred *cr;
1614{
1615 struct mtx *mtxp = cr->cr_mtxp;
1616
1617 mtx_lock(mtxp);
1618 KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
1619 if (--cr->cr_ref == 0) {
1620 /*
1621 * Some callers of crget(), such as nfs_statfs(),
1622 * allocate a temporary credential, but don't
1623 * allocate a uidinfo structure.
1624 */
1625 mtx_unlock(mtxp);
1626 if (cr->cr_uidinfo != NULL)
1627 uifree(cr->cr_uidinfo);
1628 if (cr->cr_ruidinfo != NULL)
1629 uifree(cr->cr_ruidinfo);
1630 /*
1631 * Free a prison, if any.
1632 */
1633 if (jailed(cr))
1634 prison_free(cr->cr_prison);
1635 FREE((caddr_t)cr, M_CRED);
1636 } else {
1637 mtx_unlock(mtxp);
1638 }
1639}
1640
1641/*
1642 * Check to see if this ucred is shared.
1643 */
1644int
1645crshared(cr)
1646 struct ucred *cr;
1647{
1648 int shared;
1649
1650 mtx_lock(cr->cr_mtxp);
1651 shared = (cr->cr_ref > 1);
1652 mtx_unlock(cr->cr_mtxp);
1653 return (shared);
1654}
1655
1656/*
1657 * Copy a ucred's contents from a template. Does not block.
1658 */
1659void
1660crcopy(dest, src)
1661 struct ucred *dest, *src;
1662{
1663
1664 KASSERT(crshared(dest) == 0, ("crcopy of shared ucred"));
1665 bcopy(&src->cr_startcopy, &dest->cr_startcopy,
1666 (unsigned)((caddr_t)&src->cr_endcopy -
1667 (caddr_t)&src->cr_startcopy));
1668 uihold(dest->cr_uidinfo);
1669 uihold(dest->cr_ruidinfo);
1670 if (jailed(dest))
1671 prison_hold(dest->cr_prison);
1672}
1673
1674/*
1675 * Dup cred struct to a new held one.
1676 */
1677struct ucred *
1678crdup(cr)
1679 struct ucred *cr;
1680{
1681 struct ucred *newcr;
1682
1683 newcr = crget();
1684 crcopy(newcr, cr);
1685 return (newcr);
1686}
1687
1688/*
1689 * small routine to swap a thread's current ucred for the correct one
1690 * taken from the process.
1691 */
1692void
1693cred_update_thread(struct thread *td)
1694{
1695 struct proc *p;
1696
1697 p = td->td_proc;
1698 if (td->td_ucred != NULL) {
1699 mtx_lock(&Giant);
1700 crfree(td->td_ucred);
1701 mtx_unlock(&Giant);
1702 td->td_ucred = NULL;
1703 }
1704 PROC_LOCK(p);
1705 td->td_ucred = crhold(p->p_ucred);
1706 PROC_UNLOCK(p);
1707}
1708
1709/*
1710 * Get login name, if available.
1711 */
1712#ifndef _SYS_SYSPROTO_H_
1713struct getlogin_args {
1714 char *namebuf;
1715 u_int namelen;
1716};
1717#endif
1718/*
1719 * MPSAFE
1720 */
1721/* ARGSUSED */
1722int
1723getlogin(td, uap)
1724 struct thread *td;
1725 struct getlogin_args *uap;
1726{
1727 int error;
1234 break;
1235 default:
1236 error = EINVAL;
1237 break;
1238 }
1239 mtx_unlock(&Giant);
1240 return (error);
1241#else /* !REGRESSION */
1242
1243 return (ENOSYS);
1244#endif /* REGRESSION */
1245}
1246
1247/*
1248 * Check if gid is a member of the group set.
1249 */
1250int
1251groupmember(gid, cred)
1252 gid_t gid;
1253 struct ucred *cred;
1254{
1255 register gid_t *gp;
1256 gid_t *egp;
1257
1258 egp = &(cred->cr_groups[cred->cr_ngroups]);
1259 for (gp = cred->cr_groups; gp < egp; gp++)
1260 if (*gp == gid)
1261 return (1);
1262 return (0);
1263}
1264
1265/*
1266 * `suser_enabled' (which can be set by the security.suser_enabled
1267 * sysctl) determines whether the system 'super-user' policy is in effect.
1268 * If it is nonzero, an effective uid of 0 connotes special privilege,
1269 * overriding many mandatory and discretionary protections. If it is zero,
1270 * uid 0 is offered no special privilege in the kernel security policy.
1271 * Setting it to zero may seriously impact the functionality of many
1272 * existing userland programs, and should not be done without careful
1273 * consideration of the consequences.
1274 */
1275int suser_enabled = 1;
1276SYSCTL_INT(_security_bsd, OID_AUTO, suser_enabled, CTLFLAG_RW,
1277 &suser_enabled, 0, "processes with uid 0 have privilege");
1278TUNABLE_INT("security.bsd.suser_enabled", &suser_enabled);
1279
1280/*
1281 * Test whether the specified credentials imply "super-user" privilege.
1282 * Return 0 or EPERM.
1283 */
1284int
1285suser(p)
1286 struct proc *p;
1287{
1288
1289 return (suser_xxx(0, p, 0));
1290}
1291
1292/*
1293 * version for when the thread pointer is available and not the proc.
1294 * (saves having to include proc.h into every file that needs to do the change.)
1295 */
1296int
1297suser_td(td)
1298 struct thread *td;
1299{
1300 return (suser_xxx(0, td->td_proc, 0));
1301}
1302
1303/*
1304 * wrapper to use if you have the thread on hand but not the proc.
1305 */
1306int
1307suser_xxx_td(cred, td, flag)
1308 struct ucred *cred;
1309 struct thread *td;
1310 int flag;
1311{
1312 return(suser_xxx(cred, td->td_proc, flag));
1313}
1314
1315int
1316suser_xxx(cred, proc, flag)
1317 struct ucred *cred;
1318 struct proc *proc;
1319 int flag;
1320{
1321 if (!suser_enabled)
1322 return (EPERM);
1323 if (!cred && !proc) {
1324 printf("suser_xxx(): THINK!\n");
1325 return (EPERM);
1326 }
1327 if (cred == NULL)
1328 cred = proc->p_ucred;
1329 if (cred->cr_uid != 0)
1330 return (EPERM);
1331 if (jailed(cred) && !(flag & PRISON_ROOT))
1332 return (EPERM);
1333 return (0);
1334}
1335
1336/*
1337 * Test the active securelevel against a given level. securelevel_gt()
1338 * implements (securelevel > level). securelevel_ge() implements
1339 * (securelevel >= level). Note that the logic is inverted -- these
1340 * functions return EPERM on "success" and 0 on "failure".
1341 *
1342 * cr is permitted to be NULL for the time being, as there were some
1343 * existing securelevel checks that occurred without a process/credential
1344 * context. In the future this will be disallowed, so a kernel message
1345 * is displayed.
1346 */
1347int
1348securelevel_gt(struct ucred *cr, int level)
1349{
1350 int active_securelevel;
1351
1352 active_securelevel = securelevel;
1353 if (cr == NULL)
1354 printf("securelevel_gt: cr is NULL\n");
1355 if (cr->cr_prison != NULL) {
1356 mtx_lock(&cr->cr_prison->pr_mtx);
1357 active_securelevel = imax(cr->cr_prison->pr_securelevel,
1358 active_securelevel);
1359 mtx_unlock(&cr->cr_prison->pr_mtx);
1360 }
1361 return (active_securelevel > level ? EPERM : 0);
1362}
1363
1364int
1365securelevel_ge(struct ucred *cr, int level)
1366{
1367 int active_securelevel;
1368
1369 active_securelevel = securelevel;
1370 if (cr == NULL)
1371 printf("securelevel_gt: cr is NULL\n");
1372 if (cr->cr_prison != NULL) {
1373 mtx_lock(&cr->cr_prison->pr_mtx);
1374 active_securelevel = imax(cr->cr_prison->pr_securelevel,
1375 active_securelevel);
1376 mtx_unlock(&cr->cr_prison->pr_mtx);
1377 }
1378 return (active_securelevel >= level ? EPERM : 0);
1379}
1380
1381/*
1382 * 'see_other_uids' determines whether or not visibility of processes
1383 * and sockets with credentials holding different real uids is possible
1384 * using a variety of system MIBs.
1385 * XXX: data declarations should be together near the beginning of the file.
1386 */
1387static int see_other_uids = 1;
1388SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW,
1389 &see_other_uids, 0,
1390 "Unprivileged processes may see subjects/objects with different real uid");
1391
1392/*-
1393 * Determine if u1 "can see" the subject specified by u2.
1394 * Returns: 0 for permitted, an errno value otherwise
1395 * Locks: none
1396 * References: *u1 and *u2 must not change during the call
1397 * u1 may equal u2, in which case only one reference is required
1398 */
1399int
1400cr_cansee(struct ucred *u1, struct ucred *u2)
1401{
1402 int error;
1403
1404 if ((error = prison_check(u1, u2)))
1405 return (error);
1406 if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) {
1407 if (suser_xxx(u1, NULL, PRISON_ROOT) != 0)
1408 return (ESRCH);
1409 }
1410 return (0);
1411}
1412
1413/*-
1414 * Determine if p1 "can see" the subject specified by p2.
1415 * Returns: 0 for permitted, an errno value otherwise
1416 * Locks: Sufficient locks to protect p1->p_ucred and p2->p_ucred must
1417 * be held. Normally, p1 will be curproc, and a lock must be held
1418 * for p2.
1419 * References: p1 and p2 must be valid for the lifetime of the call
1420 */
1421int
1422p_cansee(struct proc *p1, struct proc *p2)
1423{
1424
1425 /* Wrap cr_cansee() for all functionality. */
1426 return (cr_cansee(p1->p_ucred, p2->p_ucred));
1427}
1428
1429/*-
1430 * Determine whether cred may deliver the specified signal to proc.
1431 * Returns: 0 for permitted, an errno value otherwise.
1432 * Locks: A lock must be held for proc.
1433 * References: cred and proc must be valid for the lifetime of the call.
1434 */
1435int
1436cr_cansignal(struct ucred *cred, struct proc *proc, int signum)
1437{
1438 int error;
1439
1440 /*
1441 * Jail semantics limit the scope of signalling to proc in the
1442 * same jail as cred, if cred is in jail.
1443 */
1444 error = prison_check(cred, proc->p_ucred);
1445 if (error)
1446 return (error);
1447
1448 /*
1449 * UNIX signal semantics depend on the status of the P_SUGID
1450 * bit on the target process. If the bit is set, then additional
1451 * restrictions are placed on the set of available signals.
1452 */
1453 if (proc->p_flag & P_SUGID) {
1454 switch (signum) {
1455 case 0:
1456 case SIGKILL:
1457 case SIGINT:
1458 case SIGTERM:
1459 case SIGSTOP:
1460 case SIGTTIN:
1461 case SIGTTOU:
1462 case SIGTSTP:
1463 case SIGHUP:
1464 case SIGUSR1:
1465 case SIGUSR2:
1466 /*
1467 * Generally, permit job and terminal control
1468 * signals.
1469 */
1470 break;
1471 default:
1472 /* Not permitted without privilege. */
1473 error = suser_xxx(cred, NULL, PRISON_ROOT);
1474 if (error)
1475 return (error);
1476 }
1477 }
1478
1479 /*
1480 * Generally, the target credential's ruid or svuid must match the
1481 * subject credential's ruid or euid.
1482 */
1483 if (cred->cr_ruid != proc->p_ucred->cr_ruid &&
1484 cred->cr_ruid != proc->p_ucred->cr_svuid &&
1485 cred->cr_uid != proc->p_ucred->cr_ruid &&
1486 cred->cr_uid != proc->p_ucred->cr_svuid) {
1487 /* Not permitted without privilege. */
1488 error = suser_xxx(cred, NULL, PRISON_ROOT);
1489 if (error)
1490 return (error);
1491 }
1492
1493 return (0);
1494}
1495
1496
1497/*-
1498 * Determine whether p1 may deliver the specified signal to p2.
1499 * Returns: 0 for permitted, an errno value otherwise
1500 * Locks: Sufficient locks to protect various components of p1 and p2
1501 * must be held. Normally, p1 will be curproc, and a lock must
1502 * be held for p2.
1503 * References: p1 and p2 must be valid for the lifetime of the call
1504 */
1505int
1506p_cansignal(struct proc *p1, struct proc *p2, int signum)
1507{
1508
1509 if (p1 == p2)
1510 return (0);
1511
1512 /*
1513 * UNIX signalling semantics require that processes in the same
1514 * session always be able to deliver SIGCONT to one another,
1515 * overriding the remaining protections.
1516 */
1517 if (signum == SIGCONT && p1->p_session == p2->p_session)
1518 return (0);
1519
1520 return (cr_cansignal(p1->p_ucred, p2, signum));
1521}
1522
1523/*-
1524 * Determine whether p1 may reschedule p2.
1525 * Returns: 0 for permitted, an errno value otherwise
1526 * Locks: Sufficient locks to protect various components of p1 and p2
1527 * must be held. Normally, p1 will be curproc, and a lock must
1528 * be held for p2.
1529 * References: p1 and p2 must be valid for the lifetime of the call
1530 */
1531int
1532p_cansched(struct proc *p1, struct proc *p2)
1533{
1534 int error;
1535
1536 if (p1 == p2)
1537 return (0);
1538 if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1539 return (error);
1540 if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid)
1541 return (0);
1542 if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid)
1543 return (0);
1544 if (suser_xxx(0, p1, PRISON_ROOT) == 0)
1545 return (0);
1546
1547#ifdef CAPABILITIES
1548 if (!cap_check(NULL, p1, CAP_SYS_NICE, PRISON_ROOT))
1549 return (0);
1550#endif
1551
1552 return (EPERM);
1553}
1554
1555/*
1556 * The 'unprivileged_proc_debug' flag may be used to disable a variety of
1557 * unprivileged inter-process debugging services, including some procfs
1558 * functionality, ptrace(), and ktrace(). In the past, inter-process
1559 * debugging has been involved in a variety of security problems, and sites
1560 * not requiring the service might choose to disable it when hardening
1561 * systems.
1562 *
1563 * XXX: Should modifying and reading this variable require locking?
1564 * XXX: data declarations should be together near the beginning of the file.
1565 */
1566static int unprivileged_proc_debug = 1;
1567SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW,
1568 &unprivileged_proc_debug, 0,
1569 "Unprivileged processes may use process debugging facilities");
1570
1571/*-
1572 * Determine whether p1 may debug p2.
1573 * Returns: 0 for permitted, an errno value otherwise
1574 * Locks: Sufficient locks to protect various components of p1 and p2
1575 * must be held. Normally, p1 will be curproc, and a lock must
1576 * be held for p2.
1577 * References: p1 and p2 must be valid for the lifetime of the call
1578 */
1579int
1580p_candebug(struct proc *p1, struct proc *p2)
1581{
1582 int credentialchanged, error, grpsubset, i, uidsubset;
1583
1584 if (!unprivileged_proc_debug) {
1585 error = suser_xxx(NULL, p1, PRISON_ROOT);
1586 if (error)
1587 return (error);
1588 }
1589 if (p1 == p2)
1590 return (0);
1591 if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1592 return (error);
1593
1594 /*
1595 * Is p2's group set a subset of p1's effective group set? This
1596 * includes p2's egid, group access list, rgid, and svgid.
1597 */
1598 grpsubset = 1;
1599 for (i = 0; i < p2->p_ucred->cr_ngroups; i++) {
1600 if (!groupmember(p2->p_ucred->cr_groups[i], p1->p_ucred)) {
1601 grpsubset = 0;
1602 break;
1603 }
1604 }
1605 grpsubset = grpsubset &&
1606 groupmember(p2->p_ucred->cr_rgid, p1->p_ucred) &&
1607 groupmember(p2->p_ucred->cr_svgid, p1->p_ucred);
1608
1609 /*
1610 * Are the uids present in p2's credential equal to p1's
1611 * effective uid? This includes p2's euid, svuid, and ruid.
1612 */
1613 uidsubset = (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid &&
1614 p1->p_ucred->cr_uid == p2->p_ucred->cr_svuid &&
1615 p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid);
1616
1617 /*
1618 * Has the credential of the process changed since the last exec()?
1619 */
1620 credentialchanged = (p2->p_flag & P_SUGID);
1621
1622 /*
1623 * If p2's gids aren't a subset, or the uids aren't a subset,
1624 * or the credential has changed, require appropriate privilege
1625 * for p1 to debug p2. For POSIX.1e capabilities, this will
1626 * require CAP_SYS_PTRACE.
1627 */
1628 if (!grpsubset || !uidsubset || credentialchanged) {
1629 error = suser_xxx(NULL, p1, PRISON_ROOT);
1630 if (error)
1631 return (error);
1632 }
1633
1634 /* Can't trace init when securelevel > 0. */
1635 if (p2 == initproc) {
1636 error = securelevel_gt(p1->p_ucred, 0);
1637 if (error)
1638 return (error);
1639 }
1640
1641 /*
1642 * Can't trace a process that's currently exec'ing.
1643 * XXX: Note, this is not a security policy decision, it's a
1644 * basic correctness/functionality decision. Therefore, this check
1645 * should be moved to the caller's of p_candebug().
1646 */
1647 if ((p2->p_flag & P_INEXEC) != 0)
1648 return (EAGAIN);
1649
1650 return (0);
1651}
1652
1653/*
1654 * Allocate a zeroed cred structure.
1655 */
1656struct ucred *
1657crget()
1658{
1659 register struct ucred *cr;
1660
1661 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO);
1662 cr->cr_ref = 1;
1663 cr->cr_mtxp = mtx_pool_find(cr);
1664 return (cr);
1665}
1666
1667/*
1668 * Claim another reference to a ucred structure.
1669 */
1670struct ucred *
1671crhold(cr)
1672 struct ucred *cr;
1673{
1674
1675 mtx_lock(cr->cr_mtxp);
1676 cr->cr_ref++;
1677 mtx_unlock(cr->cr_mtxp);
1678 return (cr);
1679}
1680
1681/*
1682 * Free a cred structure.
1683 * Throws away space when ref count gets to 0.
1684 */
1685void
1686crfree(cr)
1687 struct ucred *cr;
1688{
1689 struct mtx *mtxp = cr->cr_mtxp;
1690
1691 mtx_lock(mtxp);
1692 KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
1693 if (--cr->cr_ref == 0) {
1694 /*
1695 * Some callers of crget(), such as nfs_statfs(),
1696 * allocate a temporary credential, but don't
1697 * allocate a uidinfo structure.
1698 */
1699 mtx_unlock(mtxp);
1700 if (cr->cr_uidinfo != NULL)
1701 uifree(cr->cr_uidinfo);
1702 if (cr->cr_ruidinfo != NULL)
1703 uifree(cr->cr_ruidinfo);
1704 /*
1705 * Free a prison, if any.
1706 */
1707 if (jailed(cr))
1708 prison_free(cr->cr_prison);
1709 FREE((caddr_t)cr, M_CRED);
1710 } else {
1711 mtx_unlock(mtxp);
1712 }
1713}
1714
1715/*
1716 * Check to see if this ucred is shared.
1717 */
1718int
1719crshared(cr)
1720 struct ucred *cr;
1721{
1722 int shared;
1723
1724 mtx_lock(cr->cr_mtxp);
1725 shared = (cr->cr_ref > 1);
1726 mtx_unlock(cr->cr_mtxp);
1727 return (shared);
1728}
1729
1730/*
1731 * Copy a ucred's contents from a template. Does not block.
1732 */
1733void
1734crcopy(dest, src)
1735 struct ucred *dest, *src;
1736{
1737
1738 KASSERT(crshared(dest) == 0, ("crcopy of shared ucred"));
1739 bcopy(&src->cr_startcopy, &dest->cr_startcopy,
1740 (unsigned)((caddr_t)&src->cr_endcopy -
1741 (caddr_t)&src->cr_startcopy));
1742 uihold(dest->cr_uidinfo);
1743 uihold(dest->cr_ruidinfo);
1744 if (jailed(dest))
1745 prison_hold(dest->cr_prison);
1746}
1747
1748/*
1749 * Dup cred struct to a new held one.
1750 */
1751struct ucred *
1752crdup(cr)
1753 struct ucred *cr;
1754{
1755 struct ucred *newcr;
1756
1757 newcr = crget();
1758 crcopy(newcr, cr);
1759 return (newcr);
1760}
1761
1762/*
1763 * small routine to swap a thread's current ucred for the correct one
1764 * taken from the process.
1765 */
1766void
1767cred_update_thread(struct thread *td)
1768{
1769 struct proc *p;
1770
1771 p = td->td_proc;
1772 if (td->td_ucred != NULL) {
1773 mtx_lock(&Giant);
1774 crfree(td->td_ucred);
1775 mtx_unlock(&Giant);
1776 td->td_ucred = NULL;
1777 }
1778 PROC_LOCK(p);
1779 td->td_ucred = crhold(p->p_ucred);
1780 PROC_UNLOCK(p);
1781}
1782
1783/*
1784 * Get login name, if available.
1785 */
1786#ifndef _SYS_SYSPROTO_H_
1787struct getlogin_args {
1788 char *namebuf;
1789 u_int namelen;
1790};
1791#endif
1792/*
1793 * MPSAFE
1794 */
1795/* ARGSUSED */
1796int
1797getlogin(td, uap)
1798 struct thread *td;
1799 struct getlogin_args *uap;
1800{
1801 int error;
1802 char login[MAXLOGNAME];
1728 struct proc *p = td->td_proc;
1729
1730 mtx_lock(&Giant);
1731 if (uap->namelen > MAXLOGNAME)
1732 uap->namelen = MAXLOGNAME;
1803 struct proc *p = td->td_proc;
1804
1805 mtx_lock(&Giant);
1806 if (uap->namelen > MAXLOGNAME)
1807 uap->namelen = MAXLOGNAME;
1733 error = copyout((caddr_t) p->p_pgrp->pg_session->s_login,
1734 (caddr_t) uap->namebuf, uap->namelen);
1808 PROC_LOCK(p);
1809 SESS_LOCK(p->p_session);
1810 bcopy(p->p_session->s_login, login, uap->namelen);
1811 SESS_UNLOCK(p->p_session);
1812 PROC_UNLOCK(p);
1813 error = copyout((caddr_t) login, (caddr_t) uap->namebuf, uap->namelen);
1735 mtx_unlock(&Giant);
1736 return(error);
1737}
1738
1739/*
1740 * Set login name.
1741 */
1742#ifndef _SYS_SYSPROTO_H_
1743struct setlogin_args {
1744 char *namebuf;
1745};
1746#endif
1747/*
1748 * MPSAFE
1749 */
1750/* ARGSUSED */
1751int
1752setlogin(td, uap)
1753 struct thread *td;
1754 struct setlogin_args *uap;
1755{
1756 struct proc *p = td->td_proc;
1757 int error;
1758 char logintmp[MAXLOGNAME];
1759
1760 mtx_lock(&Giant);
1761 if ((error = suser_xxx(0, p, PRISON_ROOT)) != 0)
1762 goto done2;
1763 error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
1764 sizeof(logintmp), (size_t *)0);
1765 if (error == ENAMETOOLONG)
1766 error = EINVAL;
1814 mtx_unlock(&Giant);
1815 return(error);
1816}
1817
1818/*
1819 * Set login name.
1820 */
1821#ifndef _SYS_SYSPROTO_H_
1822struct setlogin_args {
1823 char *namebuf;
1824};
1825#endif
1826/*
1827 * MPSAFE
1828 */
1829/* ARGSUSED */
1830int
1831setlogin(td, uap)
1832 struct thread *td;
1833 struct setlogin_args *uap;
1834{
1835 struct proc *p = td->td_proc;
1836 int error;
1837 char logintmp[MAXLOGNAME];
1838
1839 mtx_lock(&Giant);
1840 if ((error = suser_xxx(0, p, PRISON_ROOT)) != 0)
1841 goto done2;
1842 error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
1843 sizeof(logintmp), (size_t *)0);
1844 if (error == ENAMETOOLONG)
1845 error = EINVAL;
1767 else if (!error)
1768 (void)memcpy(p->p_pgrp->pg_session->s_login, logintmp,
1846 else if (!error) {
1847 PGRPSESS_XLOCK();
1848 PROC_LOCK(p);
1849 SESS_LOCK(p->p_session);
1850 (void) memcpy(p->p_session->s_login, logintmp,
1769 sizeof(logintmp));
1851 sizeof(logintmp));
1852 SESS_UNLOCK(p->p_session);
1853 PROC_UNLOCK(p);
1854 PGRPSESS_XUNLOCK();
1855 }
1770done2:
1771 mtx_unlock(&Giant);
1772 return (error);
1773}
1774
1775void
1776setsugid(p)
1777 struct proc *p;
1778{
1779 p->p_flag |= P_SUGID;
1780 if (!(p->p_pfsflags & PF_ISUGID))
1781 p->p_stops = 0;
1782}
1783
1784/*-
1785 * Change a process's effective uid.
1786 * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified.
1787 * References: newcred must be an exclusive credential reference for the
1788 * duration of the call.
1789 */
1790void
1791change_euid(newcred, euid)
1792 struct ucred *newcred;
1793 uid_t euid;
1794{
1795
1796 newcred->cr_uid = euid;
1797 uifree(newcred->cr_uidinfo);
1798 newcred->cr_uidinfo = uifind(euid);
1799}
1800
1801/*-
1802 * Change a process's effective gid.
1803 * Side effects: newcred->cr_gid will be modified.
1804 * References: newcred must be an exclusive credential reference for the
1805 * duration of the call.
1806 */
1807void
1808change_egid(newcred, egid)
1809 struct ucred *newcred;
1810 gid_t egid;
1811{
1812
1813 newcred->cr_groups[0] = egid;
1814}
1815
1816/*-
1817 * Change a process's real uid.
1818 * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo
1819 * will be updated, and the old and new cr_ruidinfo proc
1820 * counts will be updated.
1821 * References: newcred must be an exclusive credential reference for the
1822 * duration of the call.
1823 */
1824void
1825change_ruid(newcred, ruid)
1826 struct ucred *newcred;
1827 uid_t ruid;
1828{
1829
1830 (void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
1831 newcred->cr_ruid = ruid;
1832 uifree(newcred->cr_ruidinfo);
1833 newcred->cr_ruidinfo = uifind(ruid);
1834 (void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
1835}
1836
1837/*-
1838 * Change a process's real gid.
1839 * Side effects: newcred->cr_rgid will be updated.
1840 * References: newcred must be an exclusive credential reference for the
1841 * duration of the call.
1842 */
1843void
1844change_rgid(newcred, rgid)
1845 struct ucred *newcred;
1846 gid_t rgid;
1847{
1848
1849 newcred->cr_rgid = rgid;
1850}
1851
1852/*-
1853 * Change a process's saved uid.
1854 * Side effects: newcred->cr_svuid will be updated.
1855 * References: newcred must be an exclusive credential reference for the
1856 * duration of the call.
1857 */
1858void
1859change_svuid(newcred, svuid)
1860 struct ucred *newcred;
1861 uid_t svuid;
1862{
1863
1864 newcred->cr_svuid = svuid;
1865}
1866
1867/*-
1868 * Change a process's saved gid.
1869 * Side effects: newcred->cr_svgid will be updated.
1870 * References: newcred must be an exclusive credential reference for the
1871 * duration of the call.
1872 */
1873void
1874change_svgid(newcred, svgid)
1875 struct ucred *newcred;
1876 gid_t svgid;
1877{
1878
1879 newcred->cr_svgid = svgid;
1880}
1856done2:
1857 mtx_unlock(&Giant);
1858 return (error);
1859}
1860
1861void
1862setsugid(p)
1863 struct proc *p;
1864{
1865 p->p_flag |= P_SUGID;
1866 if (!(p->p_pfsflags & PF_ISUGID))
1867 p->p_stops = 0;
1868}
1869
1870/*-
1871 * Change a process's effective uid.
1872 * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified.
1873 * References: newcred must be an exclusive credential reference for the
1874 * duration of the call.
1875 */
1876void
1877change_euid(newcred, euid)
1878 struct ucred *newcred;
1879 uid_t euid;
1880{
1881
1882 newcred->cr_uid = euid;
1883 uifree(newcred->cr_uidinfo);
1884 newcred->cr_uidinfo = uifind(euid);
1885}
1886
1887/*-
1888 * Change a process's effective gid.
1889 * Side effects: newcred->cr_gid will be modified.
1890 * References: newcred must be an exclusive credential reference for the
1891 * duration of the call.
1892 */
1893void
1894change_egid(newcred, egid)
1895 struct ucred *newcred;
1896 gid_t egid;
1897{
1898
1899 newcred->cr_groups[0] = egid;
1900}
1901
1902/*-
1903 * Change a process's real uid.
1904 * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo
1905 * will be updated, and the old and new cr_ruidinfo proc
1906 * counts will be updated.
1907 * References: newcred must be an exclusive credential reference for the
1908 * duration of the call.
1909 */
1910void
1911change_ruid(newcred, ruid)
1912 struct ucred *newcred;
1913 uid_t ruid;
1914{
1915
1916 (void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
1917 newcred->cr_ruid = ruid;
1918 uifree(newcred->cr_ruidinfo);
1919 newcred->cr_ruidinfo = uifind(ruid);
1920 (void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
1921}
1922
1923/*-
1924 * Change a process's real gid.
1925 * Side effects: newcred->cr_rgid will be updated.
1926 * References: newcred must be an exclusive credential reference for the
1927 * duration of the call.
1928 */
1929void
1930change_rgid(newcred, rgid)
1931 struct ucred *newcred;
1932 gid_t rgid;
1933{
1934
1935 newcred->cr_rgid = rgid;
1936}
1937
1938/*-
1939 * Change a process's saved uid.
1940 * Side effects: newcred->cr_svuid will be updated.
1941 * References: newcred must be an exclusive credential reference for the
1942 * duration of the call.
1943 */
1944void
1945change_svuid(newcred, svuid)
1946 struct ucred *newcred;
1947 uid_t svuid;
1948{
1949
1950 newcred->cr_svuid = svuid;
1951}
1952
1953/*-
1954 * Change a process's saved gid.
1955 * Side effects: newcred->cr_svgid will be updated.
1956 * References: newcred must be an exclusive credential reference for the
1957 * duration of the call.
1958 */
1959void
1960change_svgid(newcred, svgid)
1961 struct ucred *newcred;
1962 gid_t svgid;
1963{
1964
1965 newcred->cr_svgid = svgid;
1966}