xref: /freebsd/sys/kern/kern_prot.c (revision 5fab7614f4f201cfa378f11f5523ebce0015ccab)
1df8bae1dSRodney W. Grimes /*
2df8bae1dSRodney W. Grimes  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
3df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
43b243b72SRobert Watson  * Copyright (c) 2000, 2001 Robert N. M. Watson.  All rights reserved.
5df8bae1dSRodney W. Grimes  * (c) UNIX System Laboratories, Inc.
6df8bae1dSRodney W. Grimes  * All or some portions of this file are derived from material licensed
7df8bae1dSRodney W. Grimes  * to the University of California by American Telephone and Telegraph
8df8bae1dSRodney W. Grimes  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
9df8bae1dSRodney W. Grimes  * the permission of UNIX System Laboratories, Inc.
10df8bae1dSRodney W. Grimes  *
11df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
12df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
13df8bae1dSRodney W. Grimes  * are met:
14df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
15df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
16df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
17df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
18df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
19df8bae1dSRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
20df8bae1dSRodney W. Grimes  *    must display the following acknowledgement:
21df8bae1dSRodney W. Grimes  *	This product includes software developed by the University of
22df8bae1dSRodney W. Grimes  *	California, Berkeley and its contributors.
23df8bae1dSRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
24df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
25df8bae1dSRodney W. Grimes  *    without specific prior written permission.
26df8bae1dSRodney W. Grimes  *
27df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
38df8bae1dSRodney W. Grimes  *
39df8bae1dSRodney W. Grimes  *	@(#)kern_prot.c	8.6 (Berkeley) 1/21/94
40c3aac50fSPeter Wemm  * $FreeBSD$
41df8bae1dSRodney W. Grimes  */
42df8bae1dSRodney W. Grimes 
43df8bae1dSRodney W. Grimes /*
44df8bae1dSRodney W. Grimes  * System calls related to processes and protection
45df8bae1dSRodney W. Grimes  */
46df8bae1dSRodney W. Grimes 
475591b823SEivind Eklund #include "opt_compat.h"
48130d0157SRobert Watson #include "opt_global.h"
495591b823SEivind Eklund 
50df8bae1dSRodney W. Grimes #include <sys/param.h>
51df8bae1dSRodney W. Grimes #include <sys/systm.h>
52fb919e4dSMark Murray #include <sys/acct.h>
531c5bb3eaSPeter Wemm #include <sys/kernel.h>
5498f03f90SJake Burkholder #include <sys/lock.h>
55fb919e4dSMark Murray #include <sys/mutex.h>
56df8bae1dSRodney W. Grimes #include <sys/proc.h>
57fb919e4dSMark Murray #include <sys/sysproto.h>
58df8bae1dSRodney W. Grimes #include <sys/malloc.h>
59d5f81602SSean Eric Fagan #include <sys/pioctl.h>
60f535380cSDon Lewis #include <sys/resourcevar.h>
61579f4eb4SRobert Watson #include <sys/sysctl.h>
6291421ba2SRobert Watson #include <sys/jail.h>
63df8bae1dSRodney W. Grimes 
64a1c995b6SPoul-Henning Kamp static MALLOC_DEFINE(M_CRED, "cred", "credentials");
65a1c995b6SPoul-Henning Kamp 
660ef5652eSRobert Watson SYSCTL_NODE(_kern, OID_AUTO, security, CTLFLAG_RW, 0,
670ef5652eSRobert Watson     "Kernel security policy");
680ef5652eSRobert Watson 
69d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
70ad7507e2SSteven Wallace struct getpid_args {
71df8bae1dSRodney W. Grimes 	int	dummy;
72df8bae1dSRodney W. Grimes };
73d2d3e875SBruce Evans #endif
74df8bae1dSRodney W. Grimes 
7536e9f877SMatthew Dillon /*
76835a82eeSMatthew Dillon  * getpid
7736e9f877SMatthew Dillon  */
7898f03f90SJake Burkholder 
79835a82eeSMatthew Dillon /*
80835a82eeSMatthew Dillon  * MPSAFE
81835a82eeSMatthew Dillon  */
82df8bae1dSRodney W. Grimes /* ARGSUSED */
8326f9a767SRodney W. Grimes int
84b40ce416SJulian Elischer getpid(td, uap)
85b40ce416SJulian Elischer 	struct thread *td;
86ad7507e2SSteven Wallace 	struct getpid_args *uap;
87df8bae1dSRodney W. Grimes {
88b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
89d23f5958SMatthew Dillon 	int s;
90df8bae1dSRodney W. Grimes 
91d23f5958SMatthew Dillon 	s = mtx_lock_giant(kern_giant_proc);
92b40ce416SJulian Elischer 	td->td_retval[0] = p->p_pid;
93df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
94bae3a80bSJohn Baldwin 	PROC_LOCK(p);
95b40ce416SJulian Elischer 	td->td_retval[1] = p->p_pptr->p_pid;
96bae3a80bSJohn Baldwin 	PROC_UNLOCK(p);
97df8bae1dSRodney W. Grimes #endif
98d23f5958SMatthew Dillon 	mtx_unlock_giant(s);
99df8bae1dSRodney W. Grimes 	return (0);
100df8bae1dSRodney W. Grimes }
101df8bae1dSRodney W. Grimes 
10298f03f90SJake Burkholder /*
103835a82eeSMatthew Dillon  * getppid
10498f03f90SJake Burkholder  */
10598f03f90SJake Burkholder 
106d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
107ad7507e2SSteven Wallace struct getppid_args {
108ad7507e2SSteven Wallace         int     dummy;
109ad7507e2SSteven Wallace };
110d2d3e875SBruce Evans #endif
111835a82eeSMatthew Dillon /*
112835a82eeSMatthew Dillon  * MPSAFE
113835a82eeSMatthew Dillon  */
114df8bae1dSRodney W. Grimes /* ARGSUSED */
11526f9a767SRodney W. Grimes int
116b40ce416SJulian Elischer getppid(td, uap)
117b40ce416SJulian Elischer 	struct thread *td;
118ad7507e2SSteven Wallace 	struct getppid_args *uap;
119df8bae1dSRodney W. Grimes {
120b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
121d23f5958SMatthew Dillon 	int s;
122df8bae1dSRodney W. Grimes 
123d23f5958SMatthew Dillon 	s = mtx_lock_giant(kern_giant_proc);
124bae3a80bSJohn Baldwin 	PROC_LOCK(p);
125b40ce416SJulian Elischer 	td->td_retval[0] = p->p_pptr->p_pid;
126bae3a80bSJohn Baldwin 	PROC_UNLOCK(p);
127d23f5958SMatthew Dillon 	mtx_unlock_giant(s);
128df8bae1dSRodney W. Grimes 	return (0);
129df8bae1dSRodney W. Grimes }
130df8bae1dSRodney W. Grimes 
13136e9f877SMatthew Dillon /*
13236e9f877SMatthew Dillon  * Get process group ID; note that POSIX getpgrp takes no parameter
13336e9f877SMatthew Dillon  *
13436e9f877SMatthew Dillon  * MP SAFE
13536e9f877SMatthew Dillon  */
136d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
137ad7507e2SSteven Wallace struct getpgrp_args {
138ad7507e2SSteven Wallace         int     dummy;
139ad7507e2SSteven Wallace };
140d2d3e875SBruce Evans #endif
141835a82eeSMatthew Dillon /*
142835a82eeSMatthew Dillon  * MPSAFE
143835a82eeSMatthew Dillon  */
14426f9a767SRodney W. Grimes int
145b40ce416SJulian Elischer getpgrp(td, uap)
146b40ce416SJulian Elischer 	struct thread *td;
147ad7507e2SSteven Wallace 	struct getpgrp_args *uap;
148df8bae1dSRodney W. Grimes {
149b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
150df8bae1dSRodney W. Grimes 
151835a82eeSMatthew Dillon 	mtx_lock(&Giant);
152b40ce416SJulian Elischer 	td->td_retval[0] = p->p_pgrp->pg_id;
153835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
154df8bae1dSRodney W. Grimes 	return (0);
155df8bae1dSRodney W. Grimes }
156df8bae1dSRodney W. Grimes 
1571a5018a0SPeter Wemm /* Get an arbitary pid's process group id */
1581a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_
1591a5018a0SPeter Wemm struct getpgid_args {
1601a5018a0SPeter Wemm 	pid_t	pid;
1611a5018a0SPeter Wemm };
1621a5018a0SPeter Wemm #endif
1631a5018a0SPeter Wemm 
164835a82eeSMatthew Dillon /*
165835a82eeSMatthew Dillon  * MPSAFE
166835a82eeSMatthew Dillon  */
1671a5018a0SPeter Wemm int
168b40ce416SJulian Elischer getpgid(td, uap)
169b40ce416SJulian Elischer 	struct thread *td;
1701a5018a0SPeter Wemm 	struct getpgid_args *uap;
1711a5018a0SPeter Wemm {
172b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
17365de0c7aSDon Lewis 	struct proc *pt;
174835a82eeSMatthew Dillon 	int error = 0;
175d23f5958SMatthew Dillon 	int s;
17665de0c7aSDon Lewis 
177d23f5958SMatthew Dillon 	s = mtx_lock_giant(kern_giant_proc);
1781a5018a0SPeter Wemm 	if (uap->pid == 0)
179b40ce416SJulian Elischer 		td->td_retval[0] = p->p_pgrp->pg_id;
1806a90c862SJohn Baldwin 	else if ((pt = pfind(uap->pid)) == NULL)
181835a82eeSMatthew Dillon 		error = ESRCH;
1826a90c862SJohn Baldwin 	else {
1836a90c862SJohn Baldwin 		error = p_cansee(p, pt);
1846a90c862SJohn Baldwin 		if (error == 0)
185b40ce416SJulian Elischer 			td->td_retval[0] = pt->p_pgrp->pg_id;
18633a9ed9dSJohn Baldwin 		PROC_UNLOCK(pt);
18733a9ed9dSJohn Baldwin 	}
188d23f5958SMatthew Dillon 	mtx_unlock_giant(s);
189835a82eeSMatthew Dillon 	return (error);
1901a5018a0SPeter Wemm }
1911a5018a0SPeter Wemm 
1921a5018a0SPeter Wemm /*
1931a5018a0SPeter Wemm  * Get an arbitary pid's session id.
1941a5018a0SPeter Wemm  */
1951a5018a0SPeter Wemm #ifndef _SYS_SYSPROTO_H_
1961a5018a0SPeter Wemm struct getsid_args {
1971a5018a0SPeter Wemm 	pid_t	pid;
1981a5018a0SPeter Wemm };
1991a5018a0SPeter Wemm #endif
2001a5018a0SPeter Wemm 
201835a82eeSMatthew Dillon /*
202835a82eeSMatthew Dillon  * MPSAFE
203835a82eeSMatthew Dillon  */
2041a5018a0SPeter Wemm int
205b40ce416SJulian Elischer getsid(td, uap)
206b40ce416SJulian Elischer 	struct thread *td;
2071a5018a0SPeter Wemm 	struct getsid_args *uap;
2081a5018a0SPeter Wemm {
209b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
21065de0c7aSDon Lewis 	struct proc *pt;
211835a82eeSMatthew Dillon 	int error = 0;
21265de0c7aSDon Lewis 
213835a82eeSMatthew Dillon 	mtx_lock(&Giant);
2146a90c862SJohn Baldwin 	if (uap->pid == 0)
215b40ce416SJulian Elischer 		td->td_retval[0] = p->p_session->s_sid;
2166a90c862SJohn Baldwin 	else if ((pt = pfind(uap->pid)) == NULL)
217835a82eeSMatthew Dillon 		error = ESRCH;
2186a90c862SJohn Baldwin 	else {
2196a90c862SJohn Baldwin 		error = p_cansee(p, pt);
2206a90c862SJohn Baldwin 		if (error == 0)
221b40ce416SJulian Elischer 			td->td_retval[0] = pt->p_session->s_sid;
22233a9ed9dSJohn Baldwin 		PROC_UNLOCK(pt);
22333a9ed9dSJohn Baldwin 	}
224835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
225835a82eeSMatthew Dillon 	return (error);
2261a5018a0SPeter Wemm }
2271a5018a0SPeter Wemm 
2281a5018a0SPeter Wemm 
2297c8fdcbdSMatthew Dillon /*
2307c8fdcbdSMatthew Dillon  * getuid() - MP SAFE
2317c8fdcbdSMatthew Dillon  */
232d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
233ad7507e2SSteven Wallace struct getuid_args {
234ad7507e2SSteven Wallace         int     dummy;
235ad7507e2SSteven Wallace };
236d2d3e875SBruce Evans #endif
237ad7507e2SSteven Wallace 
238835a82eeSMatthew Dillon /*
239835a82eeSMatthew Dillon  * MPSAFE
240835a82eeSMatthew Dillon  */
241df8bae1dSRodney W. Grimes /* ARGSUSED */
24226f9a767SRodney W. Grimes int
243b40ce416SJulian Elischer getuid(td, uap)
244b40ce416SJulian Elischer 	struct thread *td;
245ad7507e2SSteven Wallace 	struct getuid_args *uap;
246df8bae1dSRodney W. Grimes {
247b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
248df8bae1dSRodney W. Grimes 
249835a82eeSMatthew Dillon 	mtx_lock(&Giant);
250b40ce416SJulian Elischer 	td->td_retval[0] = p->p_ucred->cr_ruid;
251df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
252b40ce416SJulian Elischer 	td->td_retval[1] = p->p_ucred->cr_uid;
253df8bae1dSRodney W. Grimes #endif
254835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
255df8bae1dSRodney W. Grimes 	return (0);
256df8bae1dSRodney W. Grimes }
257df8bae1dSRodney W. Grimes 
2587c8fdcbdSMatthew Dillon /*
2597c8fdcbdSMatthew Dillon  * geteuid() - MP SAFE
2607c8fdcbdSMatthew Dillon  */
261d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
262ad7507e2SSteven Wallace struct geteuid_args {
263ad7507e2SSteven Wallace         int     dummy;
264ad7507e2SSteven Wallace };
265d2d3e875SBruce Evans #endif
266ad7507e2SSteven Wallace 
267df8bae1dSRodney W. Grimes /* ARGSUSED */
26826f9a767SRodney W. Grimes int
269b40ce416SJulian Elischer geteuid(td, uap)
270b40ce416SJulian Elischer 	struct thread *td;
271ad7507e2SSteven Wallace 	struct geteuid_args *uap;
272df8bae1dSRodney W. Grimes {
273835a82eeSMatthew Dillon 	mtx_lock(&Giant);
274b40ce416SJulian Elischer 	td->td_retval[0] = td->td_proc->p_ucred->cr_uid;
275835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
276df8bae1dSRodney W. Grimes 	return (0);
277df8bae1dSRodney W. Grimes }
278df8bae1dSRodney W. Grimes 
2797c8fdcbdSMatthew Dillon /*
2807c8fdcbdSMatthew Dillon  * getgid() - MP SAFE
2817c8fdcbdSMatthew Dillon  */
282d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
283ad7507e2SSteven Wallace struct getgid_args {
284ad7507e2SSteven Wallace         int     dummy;
285ad7507e2SSteven Wallace };
286d2d3e875SBruce Evans #endif
287ad7507e2SSteven Wallace 
288835a82eeSMatthew Dillon /*
289835a82eeSMatthew Dillon  * MPSAFE
290835a82eeSMatthew Dillon  */
291df8bae1dSRodney W. Grimes /* ARGSUSED */
29226f9a767SRodney W. Grimes int
293b40ce416SJulian Elischer getgid(td, uap)
294b40ce416SJulian Elischer 	struct thread *td;
295ad7507e2SSteven Wallace 	struct getgid_args *uap;
296df8bae1dSRodney W. Grimes {
297b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
298df8bae1dSRodney W. Grimes 
299835a82eeSMatthew Dillon 	mtx_lock(&Giant);
300b40ce416SJulian Elischer 	td->td_retval[0] = p->p_ucred->cr_rgid;
301df8bae1dSRodney W. Grimes #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
302b40ce416SJulian Elischer 	td->td_retval[1] = p->p_ucred->cr_groups[0];
303df8bae1dSRodney W. Grimes #endif
304835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
305df8bae1dSRodney W. Grimes 	return (0);
306df8bae1dSRodney W. Grimes }
307df8bae1dSRodney W. Grimes 
308df8bae1dSRodney W. Grimes /*
309df8bae1dSRodney W. Grimes  * Get effective group ID.  The "egid" is groups[0], and could be obtained
310df8bae1dSRodney W. Grimes  * via getgroups.  This syscall exists because it is somewhat painful to do
311df8bae1dSRodney W. Grimes  * correctly in a library function.
312df8bae1dSRodney W. Grimes  */
313d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
314ad7507e2SSteven Wallace struct getegid_args {
315ad7507e2SSteven Wallace         int     dummy;
316ad7507e2SSteven Wallace };
317d2d3e875SBruce Evans #endif
318ad7507e2SSteven Wallace 
319835a82eeSMatthew Dillon /*
320835a82eeSMatthew Dillon  * MPSAFE
321835a82eeSMatthew Dillon  */
322df8bae1dSRodney W. Grimes /* ARGSUSED */
32326f9a767SRodney W. Grimes int
324b40ce416SJulian Elischer getegid(td, uap)
325b40ce416SJulian Elischer 	struct thread *td;
326ad7507e2SSteven Wallace 	struct getegid_args *uap;
327df8bae1dSRodney W. Grimes {
328b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
329df8bae1dSRodney W. Grimes 
330835a82eeSMatthew Dillon 	mtx_lock(&Giant);
331b40ce416SJulian Elischer 	td->td_retval[0] = p->p_ucred->cr_groups[0];
332835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
333df8bae1dSRodney W. Grimes 	return (0);
334df8bae1dSRodney W. Grimes }
335df8bae1dSRodney W. Grimes 
336d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
337df8bae1dSRodney W. Grimes struct getgroups_args {
338df8bae1dSRodney W. Grimes 	u_int	gidsetsize;
339df8bae1dSRodney W. Grimes 	gid_t	*gidset;
340df8bae1dSRodney W. Grimes };
341d2d3e875SBruce Evans #endif
342835a82eeSMatthew Dillon /*
343835a82eeSMatthew Dillon  * MPSAFE
344835a82eeSMatthew Dillon  */
34526f9a767SRodney W. Grimes int
346b40ce416SJulian Elischer getgroups(td, uap)
347b40ce416SJulian Elischer 	struct thread *td;
348df8bae1dSRodney W. Grimes 	register struct	getgroups_args *uap;
349df8bae1dSRodney W. Grimes {
350835a82eeSMatthew Dillon 	struct ucred *cred;
351b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
352b1fc0ec1SRobert Watson 	u_int ngrp;
353835a82eeSMatthew Dillon 	int error = 0;
354df8bae1dSRodney W. Grimes 
355835a82eeSMatthew Dillon 	mtx_lock(&Giant);
356835a82eeSMatthew Dillon 	cred = p->p_ucred;
357df8bae1dSRodney W. Grimes 	if ((ngrp = uap->gidsetsize) == 0) {
358b40ce416SJulian Elischer 		td->td_retval[0] = cred->cr_ngroups;
359835a82eeSMatthew Dillon 		error = 0;
360835a82eeSMatthew Dillon 		goto done2;
361df8bae1dSRodney W. Grimes 	}
362835a82eeSMatthew Dillon 	if (ngrp < cred->cr_ngroups) {
363835a82eeSMatthew Dillon 		error = EINVAL;
364835a82eeSMatthew Dillon 		goto done2;
365835a82eeSMatthew Dillon 	}
366b1fc0ec1SRobert Watson 	ngrp = cred->cr_ngroups;
367b1fc0ec1SRobert Watson 	if ((error = copyout((caddr_t)cred->cr_groups,
368835a82eeSMatthew Dillon 	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) {
369835a82eeSMatthew Dillon 		goto done2;
370835a82eeSMatthew Dillon 	}
371b40ce416SJulian Elischer 	td->td_retval[0] = ngrp;
372835a82eeSMatthew Dillon done2:
373835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
374835a82eeSMatthew Dillon 	return (error);
375df8bae1dSRodney W. Grimes }
376df8bae1dSRodney W. Grimes 
377d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
37882970b81SBruce Evans struct setsid_args {
379ad7507e2SSteven Wallace         int     dummy;
380ad7507e2SSteven Wallace };
381d2d3e875SBruce Evans #endif
382ad7507e2SSteven Wallace 
383835a82eeSMatthew Dillon /*
384835a82eeSMatthew Dillon  * MPSAFE
385835a82eeSMatthew Dillon  */
386df8bae1dSRodney W. Grimes /* ARGSUSED */
38726f9a767SRodney W. Grimes int
388b40ce416SJulian Elischer setsid(td, uap)
389b40ce416SJulian Elischer 	register struct thread *td;
39082970b81SBruce Evans 	struct setsid_args *uap;
391df8bae1dSRodney W. Grimes {
392835a82eeSMatthew Dillon 	int error;
393b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
394df8bae1dSRodney W. Grimes 
395835a82eeSMatthew Dillon 	mtx_lock(&Giant);
396df8bae1dSRodney W. Grimes 	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
397835a82eeSMatthew Dillon 		error = EPERM;
398df8bae1dSRodney W. Grimes 	} else {
399df8bae1dSRodney W. Grimes 		(void)enterpgrp(p, p->p_pid, 1);
400b40ce416SJulian Elischer 		td->td_retval[0] = p->p_pid;
401835a82eeSMatthew Dillon 		error = 0;
402df8bae1dSRodney W. Grimes 	}
403835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
404835a82eeSMatthew Dillon 	return (error);
405df8bae1dSRodney W. Grimes }
406df8bae1dSRodney W. Grimes 
407df8bae1dSRodney W. Grimes /*
408df8bae1dSRodney W. Grimes  * set process group (setpgid/old setpgrp)
409df8bae1dSRodney W. Grimes  *
410df8bae1dSRodney W. Grimes  * caller does setpgid(targpid, targpgid)
411df8bae1dSRodney W. Grimes  *
412df8bae1dSRodney W. Grimes  * pid must be caller or child of caller (ESRCH)
413df8bae1dSRodney W. Grimes  * if a child
414df8bae1dSRodney W. Grimes  *	pid must be in same session (EPERM)
415df8bae1dSRodney W. Grimes  *	pid can't have done an exec (EACCES)
416df8bae1dSRodney W. Grimes  * if pgid != pid
417df8bae1dSRodney W. Grimes  * 	there must exist some pid in same session having pgid (EPERM)
418df8bae1dSRodney W. Grimes  * pid must not be session leader (EPERM)
419df8bae1dSRodney W. Grimes  */
420d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
421df8bae1dSRodney W. Grimes struct setpgid_args {
422df8bae1dSRodney W. Grimes 	int	pid;	/* target process id */
423df8bae1dSRodney W. Grimes 	int	pgid;	/* target pgrp id */
424df8bae1dSRodney W. Grimes };
425d2d3e875SBruce Evans #endif
426835a82eeSMatthew Dillon /*
427835a82eeSMatthew Dillon  * MPSAFE
428835a82eeSMatthew Dillon  */
429df8bae1dSRodney W. Grimes /* ARGSUSED */
43026f9a767SRodney W. Grimes int
431b40ce416SJulian Elischer setpgid(td, uap)
432b40ce416SJulian Elischer 	struct thread *td;
433df8bae1dSRodney W. Grimes 	register struct setpgid_args *uap;
434df8bae1dSRodney W. Grimes {
435b40ce416SJulian Elischer 	struct proc *curp = td->td_proc;
436df8bae1dSRodney W. Grimes 	register struct proc *targp;		/* target process */
437df8bae1dSRodney W. Grimes 	register struct pgrp *pgrp;		/* target pgrp */
438eb9e5c1dSRobert Watson 	int error;
439df8bae1dSRodney W. Grimes 
44078f64bccSBruce Evans 	if (uap->pgid < 0)
44178f64bccSBruce Evans 		return (EINVAL);
442835a82eeSMatthew Dillon 
443835a82eeSMatthew Dillon 	mtx_lock(&Giant);
444835a82eeSMatthew Dillon 
445df8bae1dSRodney W. Grimes 	if (uap->pid != 0 && uap->pid != curp->p_pid) {
44633a9ed9dSJohn Baldwin 		if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) {
44733a9ed9dSJohn Baldwin 			if (targp)
44833a9ed9dSJohn Baldwin 				PROC_UNLOCK(targp);
449835a82eeSMatthew Dillon 			error = ESRCH;
450835a82eeSMatthew Dillon 			goto done2;
45133a9ed9dSJohn Baldwin 		}
452a0f75161SRobert Watson 		if ((error = p_cansee(curproc, targp))) {
45333a9ed9dSJohn Baldwin 			PROC_UNLOCK(targp);
454835a82eeSMatthew Dillon 			goto done2;
45533a9ed9dSJohn Baldwin 		}
45633a9ed9dSJohn Baldwin 		if (targp->p_pgrp == NULL ||
45733a9ed9dSJohn Baldwin 		    targp->p_session != curp->p_session) {
45833a9ed9dSJohn Baldwin 			PROC_UNLOCK(targp);
459835a82eeSMatthew Dillon 			error = EPERM;
460835a82eeSMatthew Dillon 			goto done2;
46133a9ed9dSJohn Baldwin 		}
46233a9ed9dSJohn Baldwin 		if (targp->p_flag & P_EXEC) {
46333a9ed9dSJohn Baldwin 			PROC_UNLOCK(targp);
464835a82eeSMatthew Dillon 			error = EACCES;
465835a82eeSMatthew Dillon 			goto done2;
46633a9ed9dSJohn Baldwin 		}
46733a9ed9dSJohn Baldwin 	} else {
468df8bae1dSRodney W. Grimes 		targp = curp;
46933a9ed9dSJohn Baldwin 		PROC_LOCK(curp);	/* XXX: not needed */
47033a9ed9dSJohn Baldwin 	}
47133a9ed9dSJohn Baldwin 	if (SESS_LEADER(targp)) {
47233a9ed9dSJohn Baldwin 		PROC_UNLOCK(targp);
473835a82eeSMatthew Dillon 		error = EPERM;
474835a82eeSMatthew Dillon 		goto done2;
47533a9ed9dSJohn Baldwin 	}
476835a82eeSMatthew Dillon 	if (uap->pgid == 0) {
477df8bae1dSRodney W. Grimes 		uap->pgid = targp->p_pid;
478835a82eeSMatthew Dillon 	} else if (uap->pgid != targp->p_pid) {
479df8bae1dSRodney W. Grimes 		if ((pgrp = pgfind(uap->pgid)) == 0 ||
48033a9ed9dSJohn Baldwin 	            pgrp->pg_session != curp->p_session) {
48133a9ed9dSJohn Baldwin 			PROC_UNLOCK(targp);
482835a82eeSMatthew Dillon 			error = EPERM;
483835a82eeSMatthew Dillon 			goto done2;
484835a82eeSMatthew Dillon 		}
48533a9ed9dSJohn Baldwin 	}
48633a9ed9dSJohn Baldwin 	/* XXX: We should probably hold the lock across enterpgrp. */
48733a9ed9dSJohn Baldwin 	PROC_UNLOCK(targp);
488835a82eeSMatthew Dillon 	error = enterpgrp(targp, uap->pgid, 0);
489835a82eeSMatthew Dillon done2:
490835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
491835a82eeSMatthew Dillon 	return (error);
492df8bae1dSRodney W. Grimes }
493df8bae1dSRodney W. Grimes 
494a08f4bf6SPeter Wemm /*
495a08f4bf6SPeter Wemm  * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
4962fa72ea7SJeroen Ruigrok van der Werven  * compatible.  It says that setting the uid/gid to euid/egid is a special
497a08f4bf6SPeter Wemm  * case of "appropriate privilege".  Once the rules are expanded out, this
498a08f4bf6SPeter Wemm  * basically means that setuid(nnn) sets all three id's, in all permitted
499a08f4bf6SPeter Wemm  * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
500a08f4bf6SPeter Wemm  * does not set the saved id - this is dangerous for traditional BSD
501a08f4bf6SPeter Wemm  * programs.  For this reason, we *really* do not want to set
502a08f4bf6SPeter Wemm  * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
503a08f4bf6SPeter Wemm  */
504a08f4bf6SPeter Wemm #define POSIX_APPENDIX_B_4_2_2
505a08f4bf6SPeter Wemm 
506d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
507df8bae1dSRodney W. Grimes struct setuid_args {
508df8bae1dSRodney W. Grimes 	uid_t	uid;
509df8bae1dSRodney W. Grimes };
510d2d3e875SBruce Evans #endif
511835a82eeSMatthew Dillon /*
512835a82eeSMatthew Dillon  * MPSAFE
513835a82eeSMatthew Dillon  */
514df8bae1dSRodney W. Grimes /* ARGSUSED */
51526f9a767SRodney W. Grimes int
516b40ce416SJulian Elischer setuid(td, uap)
517b40ce416SJulian Elischer 	struct thread *td;
518df8bae1dSRodney W. Grimes 	struct setuid_args *uap;
519df8bae1dSRodney W. Grimes {
520b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
521b1fc0ec1SRobert Watson 	struct ucred *newcred, *oldcred;
522b1fc0ec1SRobert Watson 	uid_t uid;
523835a82eeSMatthew Dillon 	int error = 0;
524df8bae1dSRodney W. Grimes 
525b1fc0ec1SRobert Watson 	uid = uap->uid;
526b1fc0ec1SRobert Watson 	oldcred = p->p_ucred;
527835a82eeSMatthew Dillon 	mtx_lock(&Giant);
528835a82eeSMatthew Dillon 
529a08f4bf6SPeter Wemm 	/*
530a08f4bf6SPeter Wemm 	 * See if we have "permission" by POSIX 1003.1 rules.
531a08f4bf6SPeter Wemm 	 *
532a08f4bf6SPeter Wemm 	 * Note that setuid(geteuid()) is a special case of
533a08f4bf6SPeter Wemm 	 * "appropriate privileges" in appendix B.4.2.2.  We need
5342fa72ea7SJeroen Ruigrok van der Werven 	 * to use this clause to be compatible with traditional BSD
535a08f4bf6SPeter Wemm 	 * semantics.  Basically, it means that "setuid(xx)" sets all
536a08f4bf6SPeter Wemm 	 * three id's (assuming you have privs).
537a08f4bf6SPeter Wemm 	 *
538a08f4bf6SPeter Wemm 	 * Notes on the logic.  We do things in three steps.
539a08f4bf6SPeter Wemm 	 * 1: We determine if the euid is going to change, and do EPERM
540a08f4bf6SPeter Wemm 	 *    right away.  We unconditionally change the euid later if this
541a08f4bf6SPeter Wemm 	 *    test is satisfied, simplifying that part of the logic.
542a08f4bf6SPeter Wemm 	 * 2: We determine if the real and/or saved uid's are going to
543a08f4bf6SPeter Wemm 	 *    change.  Determined by compile options.
544a08f4bf6SPeter Wemm 	 * 3: Change euid last. (after tests in #2 for "appropriate privs")
545a08f4bf6SPeter Wemm 	 */
546b1fc0ec1SRobert Watson 	if (uid != oldcred->cr_ruid &&		/* allow setuid(getuid()) */
5473f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS
548b1fc0ec1SRobert Watson 	    uid != oldcred->cr_svuid &&		/* allow setuid(saved gid) */
549a08f4bf6SPeter Wemm #endif
550a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
551b1fc0ec1SRobert Watson 	    uid != oldcred->cr_uid &&		/* allow setuid(geteuid()) */
5523f246666SAndrey A. Chernov #endif
553b1fc0ec1SRobert Watson 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
554835a82eeSMatthew Dillon 		goto done2;
555a08f4bf6SPeter Wemm 
556b1fc0ec1SRobert Watson 	newcred = crdup(oldcred);
557a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS
558df8bae1dSRodney W. Grimes 	/*
559a08f4bf6SPeter Wemm 	 * Do we have "appropriate privileges" (are we root or uid == euid)
560a08f4bf6SPeter Wemm 	 * If so, we are changing the real uid and/or saved uid.
561df8bae1dSRodney W. Grimes 	 */
5623f246666SAndrey A. Chernov 	if (
563a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2	/* Use the clause from B.4.2.2 */
564b1fc0ec1SRobert Watson 	    uid == oldcred->cr_uid ||
5653f246666SAndrey A. Chernov #endif
566b1fc0ec1SRobert Watson 	    suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
567a08f4bf6SPeter Wemm #endif
568a08f4bf6SPeter Wemm 	{
569a08f4bf6SPeter Wemm 		/*
570f535380cSDon Lewis 		 * Set the real uid and transfer proc count to new user.
571a08f4bf6SPeter Wemm 		 */
572b1fc0ec1SRobert Watson 		if (uid != oldcred->cr_ruid) {
573b1fc0ec1SRobert Watson 			change_ruid(newcred, uid);
574f535380cSDon Lewis 			setsugid(p);
575d3cdb93dSAndrey A. Chernov 		}
576a08f4bf6SPeter Wemm 		/*
577a08f4bf6SPeter Wemm 		 * Set saved uid
578a08f4bf6SPeter Wemm 		 *
579a08f4bf6SPeter Wemm 		 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
580a08f4bf6SPeter Wemm 		 * the security of seteuid() depends on it.  B.4.2.2 says it
581a08f4bf6SPeter Wemm 		 * is important that we should do this.
582a08f4bf6SPeter Wemm 		 */
583b1fc0ec1SRobert Watson 		if (uid != oldcred->cr_svuid) {
584b1fc0ec1SRobert Watson 			change_svuid(newcred, uid);
585d5f81602SSean Eric Fagan 			setsugid(p);
586a08f4bf6SPeter Wemm 		}
587a08f4bf6SPeter Wemm 	}
588a08f4bf6SPeter Wemm 
589a08f4bf6SPeter Wemm 	/*
590a08f4bf6SPeter Wemm 	 * In all permitted cases, we are changing the euid.
591a08f4bf6SPeter Wemm 	 * Copy credentials so other references do not see our changes.
592a08f4bf6SPeter Wemm 	 */
593b1fc0ec1SRobert Watson 	if (uid != oldcred->cr_uid) {
594b1fc0ec1SRobert Watson 		change_euid(newcred, uid);
595d5f81602SSean Eric Fagan 		setsugid(p);
596a08f4bf6SPeter Wemm 	}
597b1fc0ec1SRobert Watson 	p->p_ucred = newcred;
598b1fc0ec1SRobert Watson 	crfree(oldcred);
599835a82eeSMatthew Dillon done2:
600835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
601835a82eeSMatthew Dillon 	return (error);
602df8bae1dSRodney W. Grimes }
603df8bae1dSRodney W. Grimes 
604d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
605df8bae1dSRodney W. Grimes struct seteuid_args {
606df8bae1dSRodney W. Grimes 	uid_t	euid;
607df8bae1dSRodney W. Grimes };
608d2d3e875SBruce Evans #endif
609835a82eeSMatthew Dillon /*
610835a82eeSMatthew Dillon  * MPSAFE
611835a82eeSMatthew Dillon  */
612df8bae1dSRodney W. Grimes /* ARGSUSED */
61326f9a767SRodney W. Grimes int
614b40ce416SJulian Elischer seteuid(td, uap)
615b40ce416SJulian Elischer 	struct thread *td;
616df8bae1dSRodney W. Grimes 	struct seteuid_args *uap;
617df8bae1dSRodney W. Grimes {
618b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
619b1fc0ec1SRobert Watson 	struct ucred *newcred, *oldcred;
620b1fc0ec1SRobert Watson 	uid_t euid;
621835a82eeSMatthew Dillon 	int error = 0;
622df8bae1dSRodney W. Grimes 
623df8bae1dSRodney W. Grimes 	euid = uap->euid;
624835a82eeSMatthew Dillon 
625835a82eeSMatthew Dillon 	mtx_lock(&Giant);
626b1fc0ec1SRobert Watson 	oldcred = p->p_ucred;
627b1fc0ec1SRobert Watson 	if (euid != oldcred->cr_ruid &&		/* allow seteuid(getuid()) */
628b1fc0ec1SRobert Watson 	    euid != oldcred->cr_svuid &&	/* allow seteuid(saved uid) */
629835a82eeSMatthew Dillon 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) {
630835a82eeSMatthew Dillon 		goto done2;
631835a82eeSMatthew Dillon 	}
632df8bae1dSRodney W. Grimes 	/*
633df8bae1dSRodney W. Grimes 	 * Everything's okay, do it.  Copy credentials so other references do
634df8bae1dSRodney W. Grimes 	 * not see our changes.
635df8bae1dSRodney W. Grimes 	 */
636b1fc0ec1SRobert Watson 	newcred = crdup(oldcred);
637b1fc0ec1SRobert Watson 	if (oldcred->cr_uid != euid) {
638b1fc0ec1SRobert Watson 		change_euid(newcred, euid);
639d5f81602SSean Eric Fagan 		setsugid(p);
640229a15f0SPeter Wemm 	}
641b1fc0ec1SRobert Watson 	p->p_ucred = newcred;
642b1fc0ec1SRobert Watson 	crfree(oldcred);
643835a82eeSMatthew Dillon done2:
644835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
645835a82eeSMatthew Dillon 	return (error);
646df8bae1dSRodney W. Grimes }
647df8bae1dSRodney W. Grimes 
648d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
649df8bae1dSRodney W. Grimes struct setgid_args {
650df8bae1dSRodney W. Grimes 	gid_t	gid;
651df8bae1dSRodney W. Grimes };
652d2d3e875SBruce Evans #endif
653835a82eeSMatthew Dillon /*
654835a82eeSMatthew Dillon  * MPSAFE
655835a82eeSMatthew Dillon  */
656df8bae1dSRodney W. Grimes /* ARGSUSED */
65726f9a767SRodney W. Grimes int
658b40ce416SJulian Elischer setgid(td, uap)
659b40ce416SJulian Elischer 	struct thread *td;
660df8bae1dSRodney W. Grimes 	struct setgid_args *uap;
661df8bae1dSRodney W. Grimes {
662b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
663b1fc0ec1SRobert Watson 	struct ucred *newcred, *oldcred;
664b1fc0ec1SRobert Watson 	gid_t gid;
665835a82eeSMatthew Dillon 	int error = 0;
666df8bae1dSRodney W. Grimes 
667b1fc0ec1SRobert Watson 	gid = uap->gid;
668835a82eeSMatthew Dillon 
669835a82eeSMatthew Dillon 	mtx_lock(&Giant);
670b1fc0ec1SRobert Watson 	oldcred = p->p_ucred;
671a08f4bf6SPeter Wemm 	/*
672a08f4bf6SPeter Wemm 	 * See if we have "permission" by POSIX 1003.1 rules.
673a08f4bf6SPeter Wemm 	 *
674a08f4bf6SPeter Wemm 	 * Note that setgid(getegid()) is a special case of
675a08f4bf6SPeter Wemm 	 * "appropriate privileges" in appendix B.4.2.2.  We need
6762fa72ea7SJeroen Ruigrok van der Werven 	 * to use this clause to be compatible with traditional BSD
677a08f4bf6SPeter Wemm 	 * semantics.  Basically, it means that "setgid(xx)" sets all
678a08f4bf6SPeter Wemm 	 * three id's (assuming you have privs).
679a08f4bf6SPeter Wemm 	 *
680a08f4bf6SPeter Wemm 	 * For notes on the logic here, see setuid() above.
681a08f4bf6SPeter Wemm 	 */
682b1fc0ec1SRobert Watson 	if (gid != oldcred->cr_rgid &&		/* allow setgid(getgid()) */
6833f246666SAndrey A. Chernov #ifdef _POSIX_SAVED_IDS
684b1fc0ec1SRobert Watson 	    gid != oldcred->cr_svgid &&		/* allow setgid(saved gid) */
685a08f4bf6SPeter Wemm #endif
686a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
687b1fc0ec1SRobert Watson 	    gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */
6883f246666SAndrey A. Chernov #endif
689835a82eeSMatthew Dillon 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) {
690835a82eeSMatthew Dillon 		goto done2;
691835a82eeSMatthew Dillon 	}
692a08f4bf6SPeter Wemm 
693b1fc0ec1SRobert Watson 	newcred = crdup(oldcred);
694a08f4bf6SPeter Wemm #ifdef _POSIX_SAVED_IDS
695a08f4bf6SPeter Wemm 	/*
696a08f4bf6SPeter Wemm 	 * Do we have "appropriate privileges" (are we root or gid == egid)
697a08f4bf6SPeter Wemm 	 * If so, we are changing the real uid and saved gid.
698a08f4bf6SPeter Wemm 	 */
699a08f4bf6SPeter Wemm 	if (
700a08f4bf6SPeter Wemm #ifdef POSIX_APPENDIX_B_4_2_2	/* use the clause from B.4.2.2 */
701b1fc0ec1SRobert Watson 	    gid == oldcred->cr_groups[0] ||
702a08f4bf6SPeter Wemm #endif
703b1fc0ec1SRobert Watson 	    suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
704a08f4bf6SPeter Wemm #endif
705a08f4bf6SPeter Wemm 	{
706a08f4bf6SPeter Wemm 		/*
707a08f4bf6SPeter Wemm 		 * Set real gid
708a08f4bf6SPeter Wemm 		 */
709b1fc0ec1SRobert Watson 		if (oldcred->cr_rgid != gid) {
710b1fc0ec1SRobert Watson 			change_rgid(newcred, gid);
711d5f81602SSean Eric Fagan 			setsugid(p);
712a08f4bf6SPeter Wemm 		}
713a08f4bf6SPeter Wemm 		/*
714a08f4bf6SPeter Wemm 		 * Set saved gid
715a08f4bf6SPeter Wemm 		 *
716a08f4bf6SPeter Wemm 		 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
717a08f4bf6SPeter Wemm 		 * the security of setegid() depends on it.  B.4.2.2 says it
718a08f4bf6SPeter Wemm 		 * is important that we should do this.
719a08f4bf6SPeter Wemm 		 */
720b1fc0ec1SRobert Watson 		if (oldcred->cr_svgid != gid) {
721b1fc0ec1SRobert Watson 			change_svgid(newcred, gid);
722d5f81602SSean Eric Fagan 			setsugid(p);
723a08f4bf6SPeter Wemm 		}
724a08f4bf6SPeter Wemm 	}
725a08f4bf6SPeter Wemm 	/*
726a08f4bf6SPeter Wemm 	 * In all cases permitted cases, we are changing the egid.
727a08f4bf6SPeter Wemm 	 * Copy credentials so other references do not see our changes.
728a08f4bf6SPeter Wemm 	 */
729b1fc0ec1SRobert Watson 	if (oldcred->cr_groups[0] != gid) {
730b1fc0ec1SRobert Watson 		change_egid(newcred, gid);
731d5f81602SSean Eric Fagan 		setsugid(p);
732a08f4bf6SPeter Wemm 	}
733b1fc0ec1SRobert Watson 	p->p_ucred = newcred;
734b1fc0ec1SRobert Watson 	crfree(oldcred);
735835a82eeSMatthew Dillon done2:
736835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
737835a82eeSMatthew Dillon 	return (error);
738df8bae1dSRodney W. Grimes }
739df8bae1dSRodney W. Grimes 
740d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
741df8bae1dSRodney W. Grimes struct setegid_args {
742df8bae1dSRodney W. Grimes 	gid_t	egid;
743df8bae1dSRodney W. Grimes };
744d2d3e875SBruce Evans #endif
745835a82eeSMatthew Dillon /*
746835a82eeSMatthew Dillon  * MPSAFE
747835a82eeSMatthew Dillon  */
748df8bae1dSRodney W. Grimes /* ARGSUSED */
74926f9a767SRodney W. Grimes int
750b40ce416SJulian Elischer setegid(td, uap)
751b40ce416SJulian Elischer 	struct thread *td;
752df8bae1dSRodney W. Grimes 	struct setegid_args *uap;
753df8bae1dSRodney W. Grimes {
754b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
755b1fc0ec1SRobert Watson 	struct ucred *newcred, *oldcred;
756b1fc0ec1SRobert Watson 	gid_t egid;
757835a82eeSMatthew Dillon 	int error = 0;
758df8bae1dSRodney W. Grimes 
759df8bae1dSRodney W. Grimes 	egid = uap->egid;
760835a82eeSMatthew Dillon 
761835a82eeSMatthew Dillon 	mtx_lock(&Giant);
762b1fc0ec1SRobert Watson 	oldcred = p->p_ucred;
763b1fc0ec1SRobert Watson 	if (egid != oldcred->cr_rgid &&		/* allow setegid(getgid()) */
764b1fc0ec1SRobert Watson 	    egid != oldcred->cr_svgid &&	/* allow setegid(saved gid) */
765835a82eeSMatthew Dillon 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) {
766835a82eeSMatthew Dillon 		goto done2;
767835a82eeSMatthew Dillon 	}
768b1fc0ec1SRobert Watson 	newcred = crdup(oldcred);
769b1fc0ec1SRobert Watson 	if (oldcred->cr_groups[0] != egid) {
770b1fc0ec1SRobert Watson 		change_egid(newcred, egid);
771d5f81602SSean Eric Fagan 		setsugid(p);
772229a15f0SPeter Wemm 	}
773b1fc0ec1SRobert Watson 	p->p_ucred = newcred;
774b1fc0ec1SRobert Watson 	crfree(oldcred);
775835a82eeSMatthew Dillon done2:
776835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
777835a82eeSMatthew Dillon 	return (error);
778df8bae1dSRodney W. Grimes }
779df8bae1dSRodney W. Grimes 
780d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
781df8bae1dSRodney W. Grimes struct setgroups_args {
782df8bae1dSRodney W. Grimes 	u_int	gidsetsize;
783df8bae1dSRodney W. Grimes 	gid_t	*gidset;
784df8bae1dSRodney W. Grimes };
785d2d3e875SBruce Evans #endif
786835a82eeSMatthew Dillon /*
787835a82eeSMatthew Dillon  * MPSAFE
788835a82eeSMatthew Dillon  */
789df8bae1dSRodney W. Grimes /* ARGSUSED */
79026f9a767SRodney W. Grimes int
791b40ce416SJulian Elischer setgroups(td, uap)
792b40ce416SJulian Elischer 	struct thread *td;
793df8bae1dSRodney W. Grimes 	struct setgroups_args *uap;
794df8bae1dSRodney W. Grimes {
795b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
796b1fc0ec1SRobert Watson 	struct ucred *newcred, *oldcred;
797b1fc0ec1SRobert Watson 	u_int ngrp;
798df8bae1dSRodney W. Grimes 	int error;
799df8bae1dSRodney W. Grimes 
800835a82eeSMatthew Dillon 	mtx_lock(&Giant);
801835a82eeSMatthew Dillon 
8023956a170SDavid Greenman 	ngrp = uap->gidsetsize;
803b1fc0ec1SRobert Watson 	oldcred = p->p_ucred;
804b1fc0ec1SRobert Watson 	if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
805835a82eeSMatthew Dillon 		goto done2;
806835a82eeSMatthew Dillon 	if (ngrp > NGROUPS) {
807835a82eeSMatthew Dillon 		error = EINVAL;
808835a82eeSMatthew Dillon 		goto done2;
809835a82eeSMatthew Dillon 	}
8108a5d815aSPeter Wemm 	/*
8118a5d815aSPeter Wemm 	 * XXX A little bit lazy here.  We could test if anything has
8128a5d815aSPeter Wemm 	 * changed before crcopy() and setting P_SUGID.
8138a5d815aSPeter Wemm 	 */
814b1fc0ec1SRobert Watson 	newcred = crdup(oldcred);
8158a5d815aSPeter Wemm 	if (ngrp < 1) {
8168a5d815aSPeter Wemm 		/*
8178a5d815aSPeter Wemm 		 * setgroups(0, NULL) is a legitimate way of clearing the
8188a5d815aSPeter Wemm 		 * groups vector on non-BSD systems (which generally do not
8198a5d815aSPeter Wemm 		 * have the egid in the groups[0]).  We risk security holes
8208a5d815aSPeter Wemm 		 * when running non-BSD software if we do not do the same.
8218a5d815aSPeter Wemm 		 */
822b1fc0ec1SRobert Watson 		newcred->cr_ngroups = 1;
8238a5d815aSPeter Wemm 	} else {
824bb56ec4aSPoul-Henning Kamp 		if ((error = copyin((caddr_t)uap->gidset,
825b1fc0ec1SRobert Watson 		    (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) {
826b1fc0ec1SRobert Watson 			crfree(newcred);
827835a82eeSMatthew Dillon 			goto done2;
828b1fc0ec1SRobert Watson 		}
829b1fc0ec1SRobert Watson 		newcred->cr_ngroups = ngrp;
8308a5d815aSPeter Wemm 	}
831d5f81602SSean Eric Fagan 	setsugid(p);
832b1fc0ec1SRobert Watson 	p->p_ucred = newcred;
833b1fc0ec1SRobert Watson 	crfree(oldcred);
834835a82eeSMatthew Dillon done2:
835835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
836835a82eeSMatthew Dillon 	return (error);
837df8bae1dSRodney W. Grimes }
838df8bae1dSRodney W. Grimes 
839d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
840df8bae1dSRodney W. Grimes struct setreuid_args {
84100999cd6SAndrey A. Chernov 	uid_t	ruid;
84200999cd6SAndrey A. Chernov 	uid_t	euid;
843df8bae1dSRodney W. Grimes };
844d2d3e875SBruce Evans #endif
845835a82eeSMatthew Dillon /*
846835a82eeSMatthew Dillon  * MPSAFE
847835a82eeSMatthew Dillon  */
848df8bae1dSRodney W. Grimes /* ARGSUSED */
84926f9a767SRodney W. Grimes int
850b40ce416SJulian Elischer setreuid(td, uap)
851b40ce416SJulian Elischer 	register struct thread *td;
852df8bae1dSRodney W. Grimes 	struct setreuid_args *uap;
853df8bae1dSRodney W. Grimes {
854b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
855b1fc0ec1SRobert Watson 	struct ucred *newcred, *oldcred;
856b1fc0ec1SRobert Watson 	uid_t ruid, euid;
857835a82eeSMatthew Dillon 	int error = 0;
858df8bae1dSRodney W. Grimes 
85900999cd6SAndrey A. Chernov 	ruid = uap->ruid;
86000999cd6SAndrey A. Chernov 	euid = uap->euid;
861835a82eeSMatthew Dillon 
862835a82eeSMatthew Dillon 	mtx_lock(&Giant);
863835a82eeSMatthew Dillon 
864b1fc0ec1SRobert Watson 	oldcred = p->p_ucred;
865b1fc0ec1SRobert Watson 	if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
866b1fc0ec1SRobert Watson 	      ruid != oldcred->cr_svuid) ||
867b1fc0ec1SRobert Watson 	     (euid != (uid_t)-1 && euid != oldcred->cr_uid &&
868b1fc0ec1SRobert Watson 	      euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
869835a82eeSMatthew Dillon 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) {
870835a82eeSMatthew Dillon 		goto done2;
871835a82eeSMatthew Dillon 	}
872b1fc0ec1SRobert Watson 	newcred = crdup(oldcred);
873b1fc0ec1SRobert Watson 	if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
874b1fc0ec1SRobert Watson 		change_euid(newcred, euid);
875d5f81602SSean Eric Fagan 		setsugid(p);
876a89a5370SPeter Wemm 	}
877b1fc0ec1SRobert Watson 	if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
878b1fc0ec1SRobert Watson 		change_ruid(newcred, ruid);
879d5f81602SSean Eric Fagan 		setsugid(p);
88000999cd6SAndrey A. Chernov 	}
881b1fc0ec1SRobert Watson 	if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) &&
882b1fc0ec1SRobert Watson 	    newcred->cr_svuid != newcred->cr_uid) {
883b1fc0ec1SRobert Watson 		change_svuid(newcred, newcred->cr_uid);
884d5f81602SSean Eric Fagan 		setsugid(p);
885a89a5370SPeter Wemm 	}
886b1fc0ec1SRobert Watson 	p->p_ucred = newcred;
887b1fc0ec1SRobert Watson 	crfree(oldcred);
888835a82eeSMatthew Dillon done2:
889835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
890835a82eeSMatthew Dillon 	return (error);
891df8bae1dSRodney W. Grimes }
892df8bae1dSRodney W. Grimes 
893d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
894df8bae1dSRodney W. Grimes struct setregid_args {
89500999cd6SAndrey A. Chernov 	gid_t	rgid;
89600999cd6SAndrey A. Chernov 	gid_t	egid;
897df8bae1dSRodney W. Grimes };
898d2d3e875SBruce Evans #endif
899835a82eeSMatthew Dillon /*
900835a82eeSMatthew Dillon  * MPSAFE
901835a82eeSMatthew Dillon  */
902df8bae1dSRodney W. Grimes /* ARGSUSED */
90326f9a767SRodney W. Grimes int
904b40ce416SJulian Elischer setregid(td, uap)
905b40ce416SJulian Elischer 	register struct thread *td;
906df8bae1dSRodney W. Grimes 	struct setregid_args *uap;
907df8bae1dSRodney W. Grimes {
908b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
909b1fc0ec1SRobert Watson 	struct ucred *newcred, *oldcred;
910b1fc0ec1SRobert Watson 	gid_t rgid, egid;
911835a82eeSMatthew Dillon 	int error = 0;
912df8bae1dSRodney W. Grimes 
91300999cd6SAndrey A. Chernov 	rgid = uap->rgid;
91400999cd6SAndrey A. Chernov 	egid = uap->egid;
915835a82eeSMatthew Dillon 
916835a82eeSMatthew Dillon 	mtx_lock(&Giant);
917835a82eeSMatthew Dillon 
918b1fc0ec1SRobert Watson 	oldcred = p->p_ucred;
919b1fc0ec1SRobert Watson 	if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
920b1fc0ec1SRobert Watson 	    rgid != oldcred->cr_svgid) ||
921b1fc0ec1SRobert Watson 	     (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] &&
922b1fc0ec1SRobert Watson 	     egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) &&
923835a82eeSMatthew Dillon 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) {
924835a82eeSMatthew Dillon 		goto done2;
925835a82eeSMatthew Dillon 	}
92600999cd6SAndrey A. Chernov 
927b1fc0ec1SRobert Watson 	newcred = crdup(oldcred);
928b1fc0ec1SRobert Watson 	if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
929b1fc0ec1SRobert Watson 		change_egid(newcred, egid);
930d5f81602SSean Eric Fagan 		setsugid(p);
931a89a5370SPeter Wemm 	}
932b1fc0ec1SRobert Watson 	if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
933b1fc0ec1SRobert Watson 		change_rgid(newcred, rgid);
934d5f81602SSean Eric Fagan 		setsugid(p);
935a89a5370SPeter Wemm 	}
936b1fc0ec1SRobert Watson 	if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) &&
937b1fc0ec1SRobert Watson 	    newcred->cr_svgid != newcred->cr_groups[0]) {
938b1fc0ec1SRobert Watson 		change_svgid(newcred, newcred->cr_groups[0]);
939d5f81602SSean Eric Fagan 		setsugid(p);
940a89a5370SPeter Wemm 	}
9414589be70SRuslan Ermilov 	p->p_ucred = newcred;
9424589be70SRuslan Ermilov 	crfree(oldcred);
943835a82eeSMatthew Dillon done2:
944835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
945835a82eeSMatthew Dillon 	return (error);
946df8bae1dSRodney W. Grimes }
947df8bae1dSRodney W. Grimes 
9488ccd6334SPeter Wemm /*
9498ccd6334SPeter Wemm  * setresuid(ruid, euid, suid) is like setreuid except control over the
9508ccd6334SPeter Wemm  * saved uid is explicit.
9518ccd6334SPeter Wemm  */
9528ccd6334SPeter Wemm 
9538ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_
9548ccd6334SPeter Wemm struct setresuid_args {
9558ccd6334SPeter Wemm 	uid_t	ruid;
9568ccd6334SPeter Wemm 	uid_t	euid;
9578ccd6334SPeter Wemm 	uid_t	suid;
9588ccd6334SPeter Wemm };
9598ccd6334SPeter Wemm #endif
960835a82eeSMatthew Dillon /*
961835a82eeSMatthew Dillon  * MPSAFE
962835a82eeSMatthew Dillon  */
9638ccd6334SPeter Wemm /* ARGSUSED */
9648ccd6334SPeter Wemm int
965b40ce416SJulian Elischer setresuid(td, uap)
966b40ce416SJulian Elischer 	register struct thread *td;
9678ccd6334SPeter Wemm 	struct setresuid_args *uap;
9688ccd6334SPeter Wemm {
969b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
970b1fc0ec1SRobert Watson 	struct ucred *newcred, *oldcred;
971b1fc0ec1SRobert Watson 	uid_t ruid, euid, suid;
9728ccd6334SPeter Wemm 	int error;
9738ccd6334SPeter Wemm 
9748ccd6334SPeter Wemm 	ruid = uap->ruid;
9758ccd6334SPeter Wemm 	euid = uap->euid;
9768ccd6334SPeter Wemm 	suid = uap->suid;
977835a82eeSMatthew Dillon 
978835a82eeSMatthew Dillon 	mtx_lock(&Giant);
979b1fc0ec1SRobert Watson 	oldcred = p->p_ucred;
980b1fc0ec1SRobert Watson 	if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
981b1fc0ec1SRobert Watson 	     ruid != oldcred->cr_svuid &&
982b1fc0ec1SRobert Watson 	      ruid != oldcred->cr_uid) ||
983b1fc0ec1SRobert Watson 	     (euid != (uid_t)-1 && euid != oldcred->cr_ruid &&
984b1fc0ec1SRobert Watson 	    euid != oldcred->cr_svuid &&
985b1fc0ec1SRobert Watson 	      euid != oldcred->cr_uid) ||
986b1fc0ec1SRobert Watson 	     (suid != (uid_t)-1 && suid != oldcred->cr_ruid &&
987b1fc0ec1SRobert Watson 	    suid != oldcred->cr_svuid &&
988b1fc0ec1SRobert Watson 	      suid != oldcred->cr_uid)) &&
989835a82eeSMatthew Dillon 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) {
990835a82eeSMatthew Dillon 		goto done2;
991835a82eeSMatthew Dillon 	}
992b1fc0ec1SRobert Watson 
993b1fc0ec1SRobert Watson 	newcred = crdup(oldcred);
994b1fc0ec1SRobert Watson 	if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
995b1fc0ec1SRobert Watson 		change_euid(newcred, euid);
9968ccd6334SPeter Wemm 		setsugid(p);
9978ccd6334SPeter Wemm 	}
998b1fc0ec1SRobert Watson 	if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
999b1fc0ec1SRobert Watson 		change_ruid(newcred, ruid);
10008ccd6334SPeter Wemm 		setsugid(p);
10018ccd6334SPeter Wemm 	}
1002b1fc0ec1SRobert Watson 	if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) {
1003b1fc0ec1SRobert Watson 		change_svuid(newcred, suid);
10048ccd6334SPeter Wemm 		setsugid(p);
10058ccd6334SPeter Wemm 	}
1006b1fc0ec1SRobert Watson 	p->p_ucred = newcred;
1007b1fc0ec1SRobert Watson 	crfree(oldcred);
1008835a82eeSMatthew Dillon 	error = 0;
1009835a82eeSMatthew Dillon done2:
1010835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
1011835a82eeSMatthew Dillon 	return (error);
10128ccd6334SPeter Wemm }
10138ccd6334SPeter Wemm 
10148ccd6334SPeter Wemm /*
10158ccd6334SPeter Wemm  * setresgid(rgid, egid, sgid) is like setregid except control over the
10168ccd6334SPeter Wemm  * saved gid is explicit.
10178ccd6334SPeter Wemm  */
10188ccd6334SPeter Wemm 
10198ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_
10208ccd6334SPeter Wemm struct setresgid_args {
10218ccd6334SPeter Wemm 	gid_t	rgid;
10228ccd6334SPeter Wemm 	gid_t	egid;
10238ccd6334SPeter Wemm 	gid_t	sgid;
10248ccd6334SPeter Wemm };
10258ccd6334SPeter Wemm #endif
1026835a82eeSMatthew Dillon /*
1027835a82eeSMatthew Dillon  * MPSAFE
1028835a82eeSMatthew Dillon  */
10298ccd6334SPeter Wemm /* ARGSUSED */
10308ccd6334SPeter Wemm int
1031b40ce416SJulian Elischer setresgid(td, uap)
1032b40ce416SJulian Elischer 	register struct thread *td;
10338ccd6334SPeter Wemm 	struct setresgid_args *uap;
10348ccd6334SPeter Wemm {
1035b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
1036b1fc0ec1SRobert Watson 	struct ucred *newcred, *oldcred;
1037b1fc0ec1SRobert Watson 	gid_t rgid, egid, sgid;
10388ccd6334SPeter Wemm 	int error;
10398ccd6334SPeter Wemm 
10408ccd6334SPeter Wemm 	rgid = uap->rgid;
10418ccd6334SPeter Wemm 	egid = uap->egid;
10428ccd6334SPeter Wemm 	sgid = uap->sgid;
1043835a82eeSMatthew Dillon 
1044835a82eeSMatthew Dillon 	mtx_lock(&Giant);
1045b1fc0ec1SRobert Watson 	oldcred = p->p_ucred;
1046b1fc0ec1SRobert Watson 	if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
1047b1fc0ec1SRobert Watson 	      rgid != oldcred->cr_svgid &&
1048b1fc0ec1SRobert Watson 	      rgid != oldcred->cr_groups[0]) ||
1049b1fc0ec1SRobert Watson 	     (egid != (gid_t)-1 && egid != oldcred->cr_rgid &&
1050b1fc0ec1SRobert Watson 	      egid != oldcred->cr_svgid &&
1051b1fc0ec1SRobert Watson 	      egid != oldcred->cr_groups[0]) ||
1052b1fc0ec1SRobert Watson 	     (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid &&
1053b1fc0ec1SRobert Watson 	      sgid != oldcred->cr_svgid &&
1054b1fc0ec1SRobert Watson 	      sgid != oldcred->cr_groups[0])) &&
1055835a82eeSMatthew Dillon 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) {
1056835a82eeSMatthew Dillon 		goto done2;
1057835a82eeSMatthew Dillon 	}
1058b1fc0ec1SRobert Watson 	newcred = crdup(oldcred);
1059b1fc0ec1SRobert Watson 	if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
1060b1fc0ec1SRobert Watson 		change_egid(newcred, egid);
10618ccd6334SPeter Wemm 		setsugid(p);
10628ccd6334SPeter Wemm 	}
1063b1fc0ec1SRobert Watson 	if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
1064b1fc0ec1SRobert Watson 		change_rgid(newcred, rgid);
10658ccd6334SPeter Wemm 		setsugid(p);
10668ccd6334SPeter Wemm 	}
1067b1fc0ec1SRobert Watson 	if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) {
1068b1fc0ec1SRobert Watson 		change_svgid(newcred, sgid);
10698ccd6334SPeter Wemm 		setsugid(p);
10708ccd6334SPeter Wemm 	}
1071b1fc0ec1SRobert Watson 	p->p_ucred = newcred;
1072b1fc0ec1SRobert Watson 	crfree(oldcred);
1073835a82eeSMatthew Dillon 	error = 0;
1074835a82eeSMatthew Dillon done2:
1075835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
1076835a82eeSMatthew Dillon 	return (error);
10778ccd6334SPeter Wemm }
10788ccd6334SPeter Wemm 
10798ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_
10808ccd6334SPeter Wemm struct getresuid_args {
10818ccd6334SPeter Wemm 	uid_t	*ruid;
10828ccd6334SPeter Wemm 	uid_t	*euid;
10838ccd6334SPeter Wemm 	uid_t	*suid;
10848ccd6334SPeter Wemm };
10858ccd6334SPeter Wemm #endif
1086835a82eeSMatthew Dillon /*
1087835a82eeSMatthew Dillon  * MPSAFE
1088835a82eeSMatthew Dillon  */
10898ccd6334SPeter Wemm /* ARGSUSED */
10908ccd6334SPeter Wemm int
1091b40ce416SJulian Elischer getresuid(td, uap)
1092b40ce416SJulian Elischer 	register struct thread *td;
10938ccd6334SPeter Wemm 	struct getresuid_args *uap;
10948ccd6334SPeter Wemm {
1095835a82eeSMatthew Dillon 	struct ucred *cred;
1096b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
10978ccd6334SPeter Wemm 	int error1 = 0, error2 = 0, error3 = 0;
10988ccd6334SPeter Wemm 
1099835a82eeSMatthew Dillon 	mtx_lock(&Giant);
1100835a82eeSMatthew Dillon 	cred = p->p_ucred;
1101835a82eeSMatthew Dillon 
11028ccd6334SPeter Wemm 	if (uap->ruid)
1103b1fc0ec1SRobert Watson 		error1 = copyout((caddr_t)&cred->cr_ruid,
1104b1fc0ec1SRobert Watson 		    (caddr_t)uap->ruid, sizeof(cred->cr_ruid));
11058ccd6334SPeter Wemm 	if (uap->euid)
1106b1fc0ec1SRobert Watson 		error2 = copyout((caddr_t)&cred->cr_uid,
1107b1fc0ec1SRobert Watson 		    (caddr_t)uap->euid, sizeof(cred->cr_uid));
11088ccd6334SPeter Wemm 	if (uap->suid)
1109b1fc0ec1SRobert Watson 		error3 = copyout((caddr_t)&cred->cr_svuid,
1110b1fc0ec1SRobert Watson 		    (caddr_t)uap->suid, sizeof(cred->cr_svuid));
1111835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
11128ccd6334SPeter Wemm 	return error1 ? error1 : (error2 ? error2 : error3);
11138ccd6334SPeter Wemm }
11148ccd6334SPeter Wemm 
11158ccd6334SPeter Wemm #ifndef _SYS_SYSPROTO_H_
11168ccd6334SPeter Wemm struct getresgid_args {
11178ccd6334SPeter Wemm 	gid_t	*rgid;
11188ccd6334SPeter Wemm 	gid_t	*egid;
11198ccd6334SPeter Wemm 	gid_t	*sgid;
11208ccd6334SPeter Wemm };
11218ccd6334SPeter Wemm #endif
1122835a82eeSMatthew Dillon /*
1123835a82eeSMatthew Dillon  * MPSAFE
1124835a82eeSMatthew Dillon  */
11258ccd6334SPeter Wemm /* ARGSUSED */
11268ccd6334SPeter Wemm int
1127b40ce416SJulian Elischer getresgid(td, uap)
1128b40ce416SJulian Elischer 	register struct thread *td;
11298ccd6334SPeter Wemm 	struct getresgid_args *uap;
11308ccd6334SPeter Wemm {
1131835a82eeSMatthew Dillon 	struct ucred *cred;
1132b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
11338ccd6334SPeter Wemm 	int error1 = 0, error2 = 0, error3 = 0;
11348ccd6334SPeter Wemm 
1135835a82eeSMatthew Dillon 	mtx_lock(&Giant);
1136835a82eeSMatthew Dillon 	cred = p->p_ucred;
1137835a82eeSMatthew Dillon 
11388ccd6334SPeter Wemm 	if (uap->rgid)
1139b1fc0ec1SRobert Watson 		error1 = copyout((caddr_t)&cred->cr_rgid,
1140b1fc0ec1SRobert Watson 		    (caddr_t)uap->rgid, sizeof(cred->cr_rgid));
11418ccd6334SPeter Wemm 	if (uap->egid)
1142b1fc0ec1SRobert Watson 		error2 = copyout((caddr_t)&cred->cr_groups[0],
1143b1fc0ec1SRobert Watson 		    (caddr_t)uap->egid, sizeof(cred->cr_groups[0]));
11448ccd6334SPeter Wemm 	if (uap->sgid)
1145b1fc0ec1SRobert Watson 		error3 = copyout((caddr_t)&cred->cr_svgid,
1146b1fc0ec1SRobert Watson 		    (caddr_t)uap->sgid, sizeof(cred->cr_svgid));
1147835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
11488ccd6334SPeter Wemm 	return error1 ? error1 : (error2 ? error2 : error3);
11498ccd6334SPeter Wemm }
11508ccd6334SPeter Wemm 
11518ccd6334SPeter Wemm 
1152b67cbc65SPeter Wemm #ifndef _SYS_SYSPROTO_H_
1153b67cbc65SPeter Wemm struct issetugid_args {
1154b67cbc65SPeter Wemm 	int dummy;
1155b67cbc65SPeter Wemm };
1156b67cbc65SPeter Wemm #endif
1157b67cbc65SPeter Wemm /* ARGSUSED */
1158b67cbc65SPeter Wemm int
1159b40ce416SJulian Elischer issetugid(td, uap)
1160b40ce416SJulian Elischer 	register struct thread *td;
1161b67cbc65SPeter Wemm 	struct issetugid_args *uap;
1162b67cbc65SPeter Wemm {
1163b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
1164b40ce416SJulian Elischer 
1165b67cbc65SPeter Wemm 	/*
1166b67cbc65SPeter Wemm 	 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
1167b67cbc65SPeter Wemm 	 * we use P_SUGID because we consider changing the owners as
1168b67cbc65SPeter Wemm 	 * "tainting" as well.
1169b67cbc65SPeter Wemm 	 * This is significant for procs that start as root and "become"
1170b67cbc65SPeter Wemm 	 * a user without an exec - programs cannot know *everything*
1171b67cbc65SPeter Wemm 	 * that libc *might* have put in their data segment.
1172b67cbc65SPeter Wemm 	 */
1173b40ce416SJulian Elischer 	td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
1174b67cbc65SPeter Wemm 	return (0);
1175b67cbc65SPeter Wemm }
1176b67cbc65SPeter Wemm 
1177835a82eeSMatthew Dillon /*
1178835a82eeSMatthew Dillon  * MPSAFE
1179835a82eeSMatthew Dillon  */
1180130d0157SRobert Watson int
1181b40ce416SJulian Elischer __setugid(td, uap)
1182b40ce416SJulian Elischer 	struct thread *td;
1183130d0157SRobert Watson 	struct __setugid_args *uap;
1184130d0157SRobert Watson {
1185130d0157SRobert Watson #ifdef REGRESSION
1186835a82eeSMatthew Dillon 	int error = 0;
1187835a82eeSMatthew Dillon 
1188835a82eeSMatthew Dillon 	mtx_lock(&Giant);
1189130d0157SRobert Watson 	switch (uap->flag) {
1190130d0157SRobert Watson 	case 0:
1191b40ce416SJulian Elischer 		td->td_proc->p_flag &= ~P_SUGID;
1192835a82eeSMatthew Dillon 		break;
1193130d0157SRobert Watson 	case 1:
1194b40ce416SJulian Elischer 		td->td_proc->p_flag |= P_SUGID;
1195835a82eeSMatthew Dillon 		break;
1196130d0157SRobert Watson 	default:
1197835a82eeSMatthew Dillon 		error = EINVAL;
1198835a82eeSMatthew Dillon 		break;
1199130d0157SRobert Watson 	}
1200835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
1201835a82eeSMatthew Dillon 	return (error);
1202130d0157SRobert Watson #else /* !REGRESSION */
1203130d0157SRobert Watson 	return (ENOSYS);
1204130d0157SRobert Watson #endif /* !REGRESSION */
1205130d0157SRobert Watson }
1206130d0157SRobert Watson 
1207df8bae1dSRodney W. Grimes /*
1208df8bae1dSRodney W. Grimes  * Check if gid is a member of the group set.
1209df8bae1dSRodney W. Grimes  */
121026f9a767SRodney W. Grimes int
1211df8bae1dSRodney W. Grimes groupmember(gid, cred)
1212df8bae1dSRodney W. Grimes 	gid_t gid;
1213b1fc0ec1SRobert Watson 	struct ucred *cred;
1214df8bae1dSRodney W. Grimes {
1215df8bae1dSRodney W. Grimes 	register gid_t *gp;
1216df8bae1dSRodney W. Grimes 	gid_t *egp;
1217df8bae1dSRodney W. Grimes 
1218df8bae1dSRodney W. Grimes 	egp = &(cred->cr_groups[cred->cr_ngroups]);
1219df8bae1dSRodney W. Grimes 	for (gp = cred->cr_groups; gp < egp; gp++)
1220df8bae1dSRodney W. Grimes 		if (*gp == gid)
1221df8bae1dSRodney W. Grimes 			return (1);
1222df8bae1dSRodney W. Grimes 	return (0);
1223df8bae1dSRodney W. Grimes }
1224df8bae1dSRodney W. Grimes 
12253b243b72SRobert Watson /*
122693f4fd1cSRobert Watson  * `suser_enabled' (which can be set by the kern.security.suser_enabled
12277fd6a959SRobert Watson  * sysctl) determines whether the system 'super-user' policy is in effect.
12287fd6a959SRobert Watson  * If it is nonzero, an effective uid of 0 connotes special privilege,
12297fd6a959SRobert Watson  * overriding many mandatory and discretionary protections.  If it is zero,
12307fd6a959SRobert Watson  * uid 0 is offered no special privilege in the kernel security policy.
12317fd6a959SRobert Watson  * Setting it to zero may seriously impact the functionality of many
12327fd6a959SRobert Watson  * existing userland programs, and should not be done without careful
12337fd6a959SRobert Watson  * consideration of the consequences.
12343b243b72SRobert Watson  */
123593f4fd1cSRobert Watson int	suser_enabled = 1;
123693f4fd1cSRobert Watson SYSCTL_INT(_kern_security, OID_AUTO, suser_enabled, CTLFLAG_RW,
123793f4fd1cSRobert Watson     &suser_enabled, 0, "processes with uid 0 have privilege");
1238579f4eb4SRobert Watson 
1239df8bae1dSRodney W. Grimes /*
12407fd6a959SRobert Watson  * Test whether the specified credentials imply "super-user" privilege.
12417fd6a959SRobert Watson  * Return 0 or EPERM.
1242df8bae1dSRodney W. Grimes  */
124326f9a767SRodney W. Grimes int
1244f711d546SPoul-Henning Kamp suser(p)
124591421ba2SRobert Watson 	struct proc *p;
1246f711d546SPoul-Henning Kamp {
124775c13541SPoul-Henning Kamp 	return suser_xxx(0, p, 0);
1248f711d546SPoul-Henning Kamp }
1249f711d546SPoul-Henning Kamp 
1250b40ce416SJulian Elischer /*
1251b40ce416SJulian Elischer  * version for when the thread pointer is available and not the proc.
1252b40ce416SJulian Elischer  * (saves having to include proc.h into every file that needs to do the change.)
1253b40ce416SJulian Elischer  */
1254b40ce416SJulian Elischer int
1255b40ce416SJulian Elischer suser_td(td)
1256b40ce416SJulian Elischer 
1257b40ce416SJulian Elischer 	struct thread *td;
1258b40ce416SJulian Elischer {
1259b40ce416SJulian Elischer 	return suser_xxx(0, td->td_proc, 0);
1260b40ce416SJulian Elischer }
1261b40ce416SJulian Elischer 
1262b40ce416SJulian Elischer /*
1263b40ce416SJulian Elischer  * wrapper to use if you have the thread on hand but not the proc.
1264b40ce416SJulian Elischer  */
1265b40ce416SJulian Elischer int
1266b40ce416SJulian Elischer suser_xxx_td(cred, td, flag)
1267b40ce416SJulian Elischer 	struct ucred *cred;
1268b40ce416SJulian Elischer 	struct thread *td;
1269b40ce416SJulian Elischer 	int flag;
1270b40ce416SJulian Elischer {
1271b40ce416SJulian Elischer 	return(suser_xxx(cred, td->td_proc, flag));
1272b40ce416SJulian Elischer }
1273b40ce416SJulian Elischer 
1274f711d546SPoul-Henning Kamp int
127575c13541SPoul-Henning Kamp suser_xxx(cred, proc, flag)
127691421ba2SRobert Watson 	struct ucred *cred;
127791421ba2SRobert Watson 	struct proc *proc;
127875c13541SPoul-Henning Kamp 	int flag;
1279df8bae1dSRodney W. Grimes {
128093f4fd1cSRobert Watson 	if (!suser_enabled)
128103095547SRobert Watson 		return (EPERM);
128275c13541SPoul-Henning Kamp 	if (!cred && !proc) {
128375c13541SPoul-Henning Kamp 		printf("suser_xxx(): THINK!\n");
1284df8bae1dSRodney W. Grimes 		return (EPERM);
1285df8bae1dSRodney W. Grimes 	}
128675c13541SPoul-Henning Kamp 	if (!cred)
128775c13541SPoul-Henning Kamp 		cred = proc->p_ucred;
128875c13541SPoul-Henning Kamp 	if (cred->cr_uid != 0)
128975c13541SPoul-Henning Kamp 		return (EPERM);
129091421ba2SRobert Watson 	if (jailed(cred) && !(flag & PRISON_ROOT))
129175c13541SPoul-Henning Kamp 		return (EPERM);
129275c13541SPoul-Henning Kamp 	return (0);
129375c13541SPoul-Henning Kamp }
1294df8bae1dSRodney W. Grimes 
12953ca719f1SRobert Watson /*
129687fce2bbSRobert Watson  * Test (local, globale) securelevel values against passed required
129787fce2bbSRobert Watson  * securelevel.  _gt implements (level > securelevel), and _ge implements
129875bc5b3fSRobert Watson  * (level >= securelevel).  Returns 0 oer EPERM.
12993ca719f1SRobert Watson  *
13003ca719f1SRobert Watson  * cr is permitted to be NULL for the time being, as there were some
13013ca719f1SRobert Watson  * existing securelevel checks that occurred without a process/credential
13023ca719f1SRobert Watson  * context.  In the future this will be disallowed, so a kernel
13033ca719f1SRobert Watson  * message is displayed.
13043ca719f1SRobert Watson  */
13053ca719f1SRobert Watson int
13063ca719f1SRobert Watson securelevel_gt(struct ucred *cr, int level)
13073ca719f1SRobert Watson {
13083ca719f1SRobert Watson 
13093ca719f1SRobert Watson 	if (cr == NULL) {
13103ca719f1SRobert Watson 		printf("securelevel_gt: cr is NULL\n");
131175bc5b3fSRobert Watson 		if (level > securelevel)
13123ca719f1SRobert Watson 			return (0);
13133ca719f1SRobert Watson 		else
13143ca719f1SRobert Watson 			return (EPERM);
131587fce2bbSRobert Watson 	} else if (cr->cr_prison == NULL) {
131675bc5b3fSRobert Watson 		if (level > securelevel)
13173ca719f1SRobert Watson 			return (0);
13183ca719f1SRobert Watson 		else
13193ca719f1SRobert Watson 			return (EPERM);
132087fce2bbSRobert Watson 	} else {
132187fce2bbSRobert Watson 		if (level > imax(cr->cr_prison->pr_securelevel, securelevel))
132287fce2bbSRobert Watson 			return (0);
132387fce2bbSRobert Watson 		else
132487fce2bbSRobert Watson 			return (EPERM);
13253ca719f1SRobert Watson 	}
132687fce2bbSRobert Watson 
13273ca719f1SRobert Watson }
13283ca719f1SRobert Watson 
13293ca719f1SRobert Watson int
13303ca719f1SRobert Watson securelevel_ge(struct ucred *cr, int level)
13313ca719f1SRobert Watson {
13323ca719f1SRobert Watson 
13333ca719f1SRobert Watson 	if (cr == NULL) {
13343ca719f1SRobert Watson 		printf("securelevel_ge: cr is NULL\n");
133575bc5b3fSRobert Watson 		if (level >= securelevel)
13363ca719f1SRobert Watson 			return (0);
13373ca719f1SRobert Watson 		else
13383ca719f1SRobert Watson 			return (EPERM);
133987fce2bbSRobert Watson 	} if (cr->cr_prison == NULL) {
134075bc5b3fSRobert Watson 		if (level >= securelevel)
13413ca719f1SRobert Watson 			return (0);
13423ca719f1SRobert Watson 		else
13433ca719f1SRobert Watson 			return (EPERM);
134487fce2bbSRobert Watson 	} else {
134587fce2bbSRobert Watson 		if (level >= imax(cr->cr_prison->pr_securelevel, securelevel))
134687fce2bbSRobert Watson 			return (0);
134787fce2bbSRobert Watson 		else
134887fce2bbSRobert Watson 			return (EPERM);
13493ca719f1SRobert Watson 	}
13503ca719f1SRobert Watson }
13513ca719f1SRobert Watson 
13528a7d8cc6SRobert Watson /*
13538a7d8cc6SRobert Watson  * kern_security_seeotheruids_permitted determines whether or not visibility
13548a7d8cc6SRobert Watson  * of processes and sockets with credentials holding different real uid's
13558a7d8cc6SRobert Watson  * is possible using a variety of system MIBs.
13568a7d8cc6SRobert Watson  */
13578a7d8cc6SRobert Watson static int	kern_security_seeotheruids_permitted = 1;
13588a7d8cc6SRobert Watson SYSCTL_INT(_kern_security, OID_AUTO, seeotheruids_permitted,
13598a7d8cc6SRobert Watson     CTLFLAG_RW, &kern_security_seeotheruids_permitted, 0,
13608a7d8cc6SRobert Watson     "Unprivileged processes may see subjects/objects with different real uid");
13618a7d8cc6SRobert Watson 
13627fd6a959SRobert Watson /*-
13637fd6a959SRobert Watson  * Determine if u1 "can see" the subject specified by u2.
1364ed639720SRobert Watson  * Returns: 0 for permitted, an errno value otherwise
1365ed639720SRobert Watson  * Locks: none
13667fd6a959SRobert Watson  * References: u1 and u2 must be immutable credentials
13677fd6a959SRobert Watson  *             u1 and u2 must be valid for the lifetime of the call
1368ed639720SRobert Watson  *             u1 may equal u2, in which case only one reference is required
1369ed639720SRobert Watson  */
1370ed639720SRobert Watson int
137194088977SRobert Watson cr_cansee(struct ucred *u1, struct ucred *u2)
1372a9e0361bSPoul-Henning Kamp {
137391421ba2SRobert Watson 	int error;
1374a9e0361bSPoul-Henning Kamp 
1375ed639720SRobert Watson 	if ((error = prison_check(u1, u2)))
137691421ba2SRobert Watson 		return (error);
13778a7d8cc6SRobert Watson 	if (!kern_security_seeotheruids_permitted &&
13788a7d8cc6SRobert Watson 	    u1->cr_ruid != u2->cr_ruid) {
1379f8e6ab29SRobert Watson 		if (suser_xxx(u1, NULL, PRISON_ROOT) != 0)
1380387d2c03SRobert Watson 			return (ESRCH);
1381c52396e3SRobert Watson 	}
1382387d2c03SRobert Watson 	return (0);
1383387d2c03SRobert Watson }
1384387d2c03SRobert Watson 
13857fd6a959SRobert Watson /*-
13867fd6a959SRobert Watson  * Determine if p1 "can see" the subject specified by p2.
13873b243b72SRobert Watson  * Returns: 0 for permitted, an errno value otherwise
13887fd6a959SRobert Watson  * Locks: Sufficient locks to protect p1->p_ucred and p2->p_ucred must
13893b243b72SRobert Watson  *        be held.  Normally, p1 will be curproc, and a lock must be held
13903b243b72SRobert Watson  *        for p2.
13913b243b72SRobert Watson  * References: p1 and p2 must be valid for the lifetime of the call
13923b243b72SRobert Watson  */
1393a0f75161SRobert Watson int
1394a0f75161SRobert Watson p_cansee(struct proc *p1, struct proc *p2)
1395ed639720SRobert Watson {
1396ed639720SRobert Watson 
139794088977SRobert Watson 	/* Wrap cr_cansee() for all functionality. */
139894088977SRobert Watson 	return (cr_cansee(p1->p_ucred, p2->p_ucred));
1399ed639720SRobert Watson }
1400ed639720SRobert Watson 
14017fd6a959SRobert Watson /*-
14027fd6a959SRobert Watson  * Determine whether p1 may deliver the specified signal to p2.
14037fd6a959SRobert Watson  * Returns: 0 for permitted, an errno value otherwise
14047fd6a959SRobert Watson  * Locks: Sufficient locks to protect various components of p1 and p2
14057fd6a959SRobert Watson  *        must be held.  Normally, p1 will be curproc, and a lock must
14067fd6a959SRobert Watson  *        be held for p2.
14073b243b72SRobert Watson  * References: p1 and p2 must be valid for the lifetime of the call
14084c5eb9c3SRobert Watson  */
14094c5eb9c3SRobert Watson int
14104c5eb9c3SRobert Watson p_cansignal(struct proc *p1, struct proc *p2, int signum)
1411387d2c03SRobert Watson {
141291421ba2SRobert Watson 	int error;
1413387d2c03SRobert Watson 
1414a9e0361bSPoul-Henning Kamp 	if (p1 == p2)
1415a9e0361bSPoul-Henning Kamp 		return (0);
1416387d2c03SRobert Watson 
14174c5eb9c3SRobert Watson 	/*
14184c5eb9c3SRobert Watson 	 * Jail semantics limit the scope of signalling to p2 in the same
14194c5eb9c3SRobert Watson 	 * jail as p1, if p1 is in jail.
14204c5eb9c3SRobert Watson 	 */
142191421ba2SRobert Watson 	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
142291421ba2SRobert Watson 		return (error);
1423387d2c03SRobert Watson 
1424387d2c03SRobert Watson 	/*
14254c5eb9c3SRobert Watson 	 * UNIX signalling semantics require that processes in the same
14264c5eb9c3SRobert Watson 	 * session always be able to deliver SIGCONT to one another,
14274c5eb9c3SRobert Watson 	 * overriding the remaining protections.
1428387d2c03SRobert Watson 	 */
14294c5eb9c3SRobert Watson 	if (signum == SIGCONT && p1->p_session == p2->p_session)
1430a9e0361bSPoul-Henning Kamp 		return (0);
1431387d2c03SRobert Watson 
14324c5eb9c3SRobert Watson 	/*
14333b243b72SRobert Watson 	 * UNIX signal semantics depend on the status of the P_SUGID
14343b243b72SRobert Watson 	 * bit on the target process.  If the bit is set, then additional
14353b243b72SRobert Watson 	 * restrictions are placed on the set of available signals.
14364c5eb9c3SRobert Watson 	 */
14374c5eb9c3SRobert Watson 	if (p2->p_flag & P_SUGID) {
14384c5eb9c3SRobert Watson 		switch (signum) {
14394c5eb9c3SRobert Watson 		case 0:
14404c5eb9c3SRobert Watson 		case SIGKILL:
14414c5eb9c3SRobert Watson 		case SIGINT:
14424c5eb9c3SRobert Watson 		case SIGTERM:
14434c5eb9c3SRobert Watson 		case SIGSTOP:
14444c5eb9c3SRobert Watson 		case SIGTTIN:
14454c5eb9c3SRobert Watson 		case SIGTTOU:
14464c5eb9c3SRobert Watson 		case SIGTSTP:
14474c5eb9c3SRobert Watson 		case SIGHUP:
14484c5eb9c3SRobert Watson 		case SIGUSR1:
14494c5eb9c3SRobert Watson 		case SIGUSR2:
14507fd6a959SRobert Watson 			/*
14517fd6a959SRobert Watson 			 * Generally, permit job and terminal control
14527fd6a959SRobert Watson 			 * signals.
14537fd6a959SRobert Watson 			 */
14544c5eb9c3SRobert Watson 			break;
14554c5eb9c3SRobert Watson 		default:
14563b243b72SRobert Watson 			/* Not permitted, privilege is required. */
14574c5eb9c3SRobert Watson 			error = suser_xxx(NULL, p1, PRISON_ROOT);
14584c5eb9c3SRobert Watson 			if (error)
14594c5eb9c3SRobert Watson 				return (error);
14604c5eb9c3SRobert Watson 		}
1461e9e7ff5bSRobert Watson 	}
1462e9e7ff5bSRobert Watson 
14634c5eb9c3SRobert Watson 	/*
14643b243b72SRobert Watson 	 * Generally, the target credential's ruid or svuid must match the
1465e9e7ff5bSRobert Watson 	 * subject credential's ruid or euid.
14664c5eb9c3SRobert Watson 	 */
1467b1fc0ec1SRobert Watson 	if (p1->p_ucred->cr_ruid != p2->p_ucred->cr_ruid &&
1468b1fc0ec1SRobert Watson 	    p1->p_ucred->cr_ruid != p2->p_ucred->cr_svuid &&
1469b1fc0ec1SRobert Watson 	    p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid &&
1470b1fc0ec1SRobert Watson 	    p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid) {
14714c5eb9c3SRobert Watson 		/* Not permitted, try privilege. */
14724c5eb9c3SRobert Watson 		error = suser_xxx(NULL, p1, PRISON_ROOT);
14734c5eb9c3SRobert Watson 		if (error)
14744c5eb9c3SRobert Watson 			return (error);
14754c5eb9c3SRobert Watson 	}
1476387d2c03SRobert Watson 
1477387d2c03SRobert Watson         return (0);
1478387d2c03SRobert Watson }
1479a9e0361bSPoul-Henning Kamp 
14807fd6a959SRobert Watson /*-
14817fd6a959SRobert Watson  * Determine whether p1 may reschedule p2
14827fd6a959SRobert Watson  * Returns: 0 for permitted, an errno value otherwise
14833b243b72SRobert Watson  * Locks: Sufficient locks to protect various components of p1 and p2
14843b243b72SRobert Watson  *        must be held.  Normally, p1 will be curproc, and a lock must
14857fd6a959SRobert Watson  *        be held for p2.
14863b243b72SRobert Watson  * References: p1 and p2 must be valid for the lifetime of the call
14873b243b72SRobert Watson  */
1488a0f75161SRobert Watson int
1489a0f75161SRobert Watson p_cansched(struct proc *p1, struct proc *p2)
1490387d2c03SRobert Watson {
149191421ba2SRobert Watson 	int error;
1492387d2c03SRobert Watson 
1493387d2c03SRobert Watson 	if (p1 == p2)
1494387d2c03SRobert Watson 		return (0);
149591421ba2SRobert Watson 	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
149691421ba2SRobert Watson 		return (error);
1497b1fc0ec1SRobert Watson 	if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid)
1498387d2c03SRobert Watson 		return (0);
1499b1fc0ec1SRobert Watson 	if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid)
1500387d2c03SRobert Watson 		return (0);
15017fd6a959SRobert Watson 	if (suser_xxx(0, p1, PRISON_ROOT) == 0)
1502387d2c03SRobert Watson 		return (0);
1503387d2c03SRobert Watson 
1504387d2c03SRobert Watson #ifdef CAPABILITIES
15054df571b1SRobert Watson 	if (!cap_check(NULL, p1, CAP_SYS_NICE, PRISON_ROOT))
1506387d2c03SRobert Watson 		return (0);
1507387d2c03SRobert Watson #endif
1508387d2c03SRobert Watson 
1509387d2c03SRobert Watson 	return (EPERM);
1510387d2c03SRobert Watson }
1511387d2c03SRobert Watson 
15123b243b72SRobert Watson /*
15137fd6a959SRobert Watson  * The kern_unprivileged_procdebug_permitted flag may be used to disable
15143b243b72SRobert Watson  * a variety of unprivileged inter-process debugging services, including
15153b243b72SRobert Watson  * some procfs functionality, ptrace(), and ktrace().  In the past,
15163b243b72SRobert Watson  * inter-process debugging has been involved in a variety of security
15173b243b72SRobert Watson  * problems, and sites not requiring the service might choose to disable it
15183b243b72SRobert Watson  * when hardening systems.
15193b243b72SRobert Watson  *
15203b243b72SRobert Watson  * XXX: Should modifying and reading this variable require locking?
15213b243b72SRobert Watson  */
15220ef5652eSRobert Watson static int	kern_unprivileged_procdebug_permitted = 1;
15230ef5652eSRobert Watson SYSCTL_INT(_kern_security, OID_AUTO, unprivileged_procdebug_permitted,
15240ef5652eSRobert Watson     CTLFLAG_RW, &kern_unprivileged_procdebug_permitted, 0,
15250ef5652eSRobert Watson     "Unprivileged processes may use process debugging facilities");
15260ef5652eSRobert Watson 
15277fd6a959SRobert Watson /*-
15287fd6a959SRobert Watson  * Determine whether p1 may debug p2.
15297fd6a959SRobert Watson  * Returns: 0 for permitted, an errno value otherwise
15307fd6a959SRobert Watson  * Locks: Sufficient locks to protect various components of p1 and p2
15317fd6a959SRobert Watson  *        must be held.  Normally, p1 will be curproc, and a lock must
15327fd6a959SRobert Watson  *        be held for p2.
15333b243b72SRobert Watson  * References: p1 and p2 must be valid for the lifetime of the call
15343b243b72SRobert Watson  */
1535a0f75161SRobert Watson int
1536a0f75161SRobert Watson p_candebug(struct proc *p1, struct proc *p2)
1537387d2c03SRobert Watson {
1538387d2c03SRobert Watson 	int error;
1539387d2c03SRobert Watson 
154032d18604SRobert Watson 	if (!kern_unprivileged_procdebug_permitted) {
154132d18604SRobert Watson 		error = suser_xxx(NULL, p1, PRISON_ROOT);
154232d18604SRobert Watson 		if (error)
154332d18604SRobert Watson 			return (error);
154432d18604SRobert Watson 	}
154532d18604SRobert Watson 
154623fad5b6SDag-Erling Smørgrav 	if (p1 == p2)
154723fad5b6SDag-Erling Smørgrav 		return (0);
154823fad5b6SDag-Erling Smørgrav 
154991421ba2SRobert Watson 	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
155091421ba2SRobert Watson 		return (error);
1551387d2c03SRobert Watson 
15527fd6a959SRobert Watson 	/*
15537fd6a959SRobert Watson 	 * Not owned by you, has done setuid (unless you're root).
15547fd6a959SRobert Watson 	 * XXX add a CAP_SYS_PTRACE here?
15557fd6a959SRobert Watson 	 */
1556b1fc0ec1SRobert Watson 	if (p1->p_ucred->cr_uid != p2->p_ucred->cr_uid ||
1557b1fc0ec1SRobert Watson 	    p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid ||
1558b1fc0ec1SRobert Watson 	    p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid ||
155932d18604SRobert Watson 	    p2->p_flag & P_SUGID) {
156032d18604SRobert Watson 		error = suser_xxx(NULL, p1, PRISON_ROOT);
156132d18604SRobert Watson 		if (error)
1562387d2c03SRobert Watson 			return (error);
15637fd6a959SRobert Watson 	}
1564387d2c03SRobert Watson 
15653ca719f1SRobert Watson 	/* can't trace init when securelevel > 0 */
15663ca719f1SRobert Watson 	if (p2->p_pid == 1) {
15673ca719f1SRobert Watson 		error = securelevel_gt(p1->p_ucred, 0);
15683ca719f1SRobert Watson 		if (error)
15693ca719f1SRobert Watson 			return (error);
15703ca719f1SRobert Watson 	}
1571387d2c03SRobert Watson 
15725fab7614SRobert Watson 	/*
15735fab7614SRobert Watson 	 * Can't trace a process that's currently exec'ing.
15745fab7614SRobert Watson 	 * XXX: Note, this is not a security policy decision, it's a
15755fab7614SRobert Watson 	 * basic correctness/functionality decision.  Therefore, this check
15765fab7614SRobert Watson 	 * should be moved to the caller's of p_candebug().
15775fab7614SRobert Watson 	 */
15789ca45e81SDag-Erling Smørgrav 	if ((p2->p_flag & P_INEXEC) != 0)
15799ca45e81SDag-Erling Smørgrav 		return (EAGAIN);
15809ca45e81SDag-Erling Smørgrav 
1581387d2c03SRobert Watson 	return (0);
1582387d2c03SRobert Watson }
1583387d2c03SRobert Watson 
1584a9e0361bSPoul-Henning Kamp /*
1585df8bae1dSRodney W. Grimes  * Allocate a zeroed cred structure.
1586df8bae1dSRodney W. Grimes  */
1587df8bae1dSRodney W. Grimes struct ucred *
1588df8bae1dSRodney W. Grimes crget()
1589df8bae1dSRodney W. Grimes {
1590df8bae1dSRodney W. Grimes 	register struct ucred *cr;
1591df8bae1dSRodney W. Grimes 
15921e5d626aSAlfred Perlstein 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK | M_ZERO);
1593df8bae1dSRodney W. Grimes 	cr->cr_ref = 1;
15941e5d626aSAlfred Perlstein 	mtx_init(&cr->cr_mtx, "ucred", MTX_DEF);
1595df8bae1dSRodney W. Grimes 	return (cr);
1596df8bae1dSRodney W. Grimes }
1597df8bae1dSRodney W. Grimes 
1598df8bae1dSRodney W. Grimes /*
15997fd6a959SRobert Watson  * Claim another reference to a ucred structure.
16005c3f70d7SAlfred Perlstein  */
1601bd78ceceSJohn Baldwin struct ucred *
16025c3f70d7SAlfred Perlstein crhold(cr)
16035c3f70d7SAlfred Perlstein 	struct ucred *cr;
16045c3f70d7SAlfred Perlstein {
16055c3f70d7SAlfred Perlstein 
16069ed346baSBosko Milekic 	mtx_lock(&cr->cr_mtx);
16075c3f70d7SAlfred Perlstein 	cr->cr_ref++;
1608bd78ceceSJohn Baldwin 	mtx_unlock(&cr->cr_mtx);
1609bd78ceceSJohn Baldwin 	return (cr);
16105c3f70d7SAlfred Perlstein }
16115c3f70d7SAlfred Perlstein 
16125c3f70d7SAlfred Perlstein 
16135c3f70d7SAlfred Perlstein /*
1614df8bae1dSRodney W. Grimes  * Free a cred structure.
1615df8bae1dSRodney W. Grimes  * Throws away space when ref count gets to 0.
1616df8bae1dSRodney W. Grimes  */
161726f9a767SRodney W. Grimes void
1618df8bae1dSRodney W. Grimes crfree(cr)
1619df8bae1dSRodney W. Grimes 	struct ucred *cr;
1620df8bae1dSRodney W. Grimes {
16211e5d626aSAlfred Perlstein 
16229ed346baSBosko Milekic 	mtx_lock(&cr->cr_mtx);
1623e04670b7SAlfred Perlstein 	KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
1624f535380cSDon Lewis 	if (--cr->cr_ref == 0) {
16251e5d626aSAlfred Perlstein 		mtx_destroy(&cr->cr_mtx);
1626f535380cSDon Lewis 		/*
1627f535380cSDon Lewis 		 * Some callers of crget(), such as nfs_statfs(),
1628f535380cSDon Lewis 		 * allocate a temporary credential, but don't
1629f535380cSDon Lewis 		 * allocate a uidinfo structure.
1630f535380cSDon Lewis 		 */
1631f535380cSDon Lewis 		if (cr->cr_uidinfo != NULL)
1632f535380cSDon Lewis 			uifree(cr->cr_uidinfo);
1633823c224eSRobert Watson 		if (cr->cr_ruidinfo != NULL)
1634823c224eSRobert Watson 			uifree(cr->cr_ruidinfo);
163591421ba2SRobert Watson 		/*
163691421ba2SRobert Watson 		 * Free a prison, if any.
163791421ba2SRobert Watson 		 */
163891421ba2SRobert Watson 		if (jailed(cr))
163991421ba2SRobert Watson 			prison_free(cr->cr_prison);
1640df8bae1dSRodney W. Grimes 		FREE((caddr_t)cr, M_CRED);
16411e5d626aSAlfred Perlstein 	} else {
16429ed346baSBosko Milekic 		mtx_unlock(&cr->cr_mtx);
1643df8bae1dSRodney W. Grimes 	}
1644f535380cSDon Lewis }
1645df8bae1dSRodney W. Grimes 
1646df8bae1dSRodney W. Grimes /*
1647bd78ceceSJohn Baldwin  * Check to see if this ucred is shared.
1648df8bae1dSRodney W. Grimes  */
1649bd78ceceSJohn Baldwin int
1650bd78ceceSJohn Baldwin crshared(cr)
1651df8bae1dSRodney W. Grimes 	struct ucred *cr;
1652df8bae1dSRodney W. Grimes {
1653bd78ceceSJohn Baldwin 	int shared;
1654df8bae1dSRodney W. Grimes 
16559ed346baSBosko Milekic 	mtx_lock(&cr->cr_mtx);
1656bd78ceceSJohn Baldwin 	shared = (cr->cr_ref > 1);
16579ed346baSBosko Milekic 	mtx_unlock(&cr->cr_mtx);
1658bd78ceceSJohn Baldwin 	return (shared);
16591e5d626aSAlfred Perlstein }
1660bd78ceceSJohn Baldwin 
1661bd78ceceSJohn Baldwin /*
1662bd78ceceSJohn Baldwin  * Copy a ucred's contents from a template.  Does not block.
1663bd78ceceSJohn Baldwin  */
1664bd78ceceSJohn Baldwin void
1665bd78ceceSJohn Baldwin crcopy(dest, src)
1666bd78ceceSJohn Baldwin 	struct ucred *dest, *src;
1667bd78ceceSJohn Baldwin {
1668bd78ceceSJohn Baldwin 
1669bd78ceceSJohn Baldwin 	KASSERT(crshared(dest) == 0, ("crcopy of shared ucred"));
1670bd78ceceSJohn Baldwin 	bcopy(&src->cr_startcopy, &dest->cr_startcopy,
1671bd78ceceSJohn Baldwin 	    (unsigned)((caddr_t)&src->cr_endcopy -
1672bd78ceceSJohn Baldwin 		(caddr_t)&src->cr_startcopy));
1673bd78ceceSJohn Baldwin 	uihold(dest->cr_uidinfo);
1674bd78ceceSJohn Baldwin 	uihold(dest->cr_ruidinfo);
1675bd78ceceSJohn Baldwin 	if (jailed(dest))
1676bd78ceceSJohn Baldwin 		prison_hold(dest->cr_prison);
1677df8bae1dSRodney W. Grimes }
1678df8bae1dSRodney W. Grimes 
1679df8bae1dSRodney W. Grimes /*
1680df8bae1dSRodney W. Grimes  * Dup cred struct to a new held one.
1681df8bae1dSRodney W. Grimes  */
1682df8bae1dSRodney W. Grimes struct ucred *
1683df8bae1dSRodney W. Grimes crdup(cr)
1684df8bae1dSRodney W. Grimes 	struct ucred *cr;
1685df8bae1dSRodney W. Grimes {
1686df8bae1dSRodney W. Grimes 	struct ucred *newcr;
1687df8bae1dSRodney W. Grimes 
1688bd78ceceSJohn Baldwin 	newcr = crget();
1689bd78ceceSJohn Baldwin 	crcopy(newcr, cr);
1690df8bae1dSRodney W. Grimes 	return (newcr);
1691df8bae1dSRodney W. Grimes }
1692df8bae1dSRodney W. Grimes 
1693df8bae1dSRodney W. Grimes /*
1694df8bae1dSRodney W. Grimes  * Get login name, if available.
1695df8bae1dSRodney W. Grimes  */
1696d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
1697df8bae1dSRodney W. Grimes struct getlogin_args {
1698df8bae1dSRodney W. Grimes 	char	*namebuf;
1699df8bae1dSRodney W. Grimes 	u_int	namelen;
1700df8bae1dSRodney W. Grimes };
1701d2d3e875SBruce Evans #endif
1702835a82eeSMatthew Dillon /*
1703835a82eeSMatthew Dillon  * MPSAFE
1704835a82eeSMatthew Dillon  */
1705df8bae1dSRodney W. Grimes /* ARGSUSED */
170626f9a767SRodney W. Grimes int
1707b40ce416SJulian Elischer getlogin(td, uap)
1708b40ce416SJulian Elischer 	struct thread *td;
1709df8bae1dSRodney W. Grimes 	struct getlogin_args *uap;
1710df8bae1dSRodney W. Grimes {
1711835a82eeSMatthew Dillon 	int error;
1712b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
1713df8bae1dSRodney W. Grimes 
1714835a82eeSMatthew Dillon 	mtx_lock(&Giant);
171530cf3ac4SAndrey A. Chernov 	if (uap->namelen > MAXLOGNAME)
171653490b76SAndrey A. Chernov 		uap->namelen = MAXLOGNAME;
1717835a82eeSMatthew Dillon 	error = copyout((caddr_t) p->p_pgrp->pg_session->s_login,
1718835a82eeSMatthew Dillon 	    (caddr_t) uap->namebuf, uap->namelen);
1719835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
1720835a82eeSMatthew Dillon 	return(error);
1721df8bae1dSRodney W. Grimes }
1722df8bae1dSRodney W. Grimes 
1723df8bae1dSRodney W. Grimes /*
1724df8bae1dSRodney W. Grimes  * Set login name.
1725df8bae1dSRodney W. Grimes  */
1726d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
1727df8bae1dSRodney W. Grimes struct setlogin_args {
1728df8bae1dSRodney W. Grimes 	char	*namebuf;
1729df8bae1dSRodney W. Grimes };
1730d2d3e875SBruce Evans #endif
1731835a82eeSMatthew Dillon /*
1732835a82eeSMatthew Dillon  * MPSAFE
1733835a82eeSMatthew Dillon  */
1734df8bae1dSRodney W. Grimes /* ARGSUSED */
173526f9a767SRodney W. Grimes int
1736b40ce416SJulian Elischer setlogin(td, uap)
1737b40ce416SJulian Elischer 	struct thread *td;
1738df8bae1dSRodney W. Grimes 	struct setlogin_args *uap;
1739df8bae1dSRodney W. Grimes {
1740b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
1741df8bae1dSRodney W. Grimes 	int error;
1742964ca0caSAndrey A. Chernov 	char logintmp[MAXLOGNAME];
1743df8bae1dSRodney W. Grimes 
1744835a82eeSMatthew Dillon 	mtx_lock(&Giant);
174575c13541SPoul-Henning Kamp 	if ((error = suser_xxx(0, p, PRISON_ROOT)))
1746835a82eeSMatthew Dillon 		goto done2;
1747184989c2SDavid Nugent 	error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
174810d4743fSDoug Rabson 	    sizeof(logintmp), (size_t *)0);
1749835a82eeSMatthew Dillon 	if (error == ENAMETOOLONG) {
1750df8bae1dSRodney W. Grimes 		error = EINVAL;
1751835a82eeSMatthew Dillon 	} else if (!error) {
1752184989c2SDavid Nugent 		(void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
1753964ca0caSAndrey A. Chernov 		    sizeof(logintmp));
1754835a82eeSMatthew Dillon 	}
1755835a82eeSMatthew Dillon done2:
1756835a82eeSMatthew Dillon 	mtx_unlock(&Giant);
1757df8bae1dSRodney W. Grimes 	return (error);
1758df8bae1dSRodney W. Grimes }
1759d5f81602SSean Eric Fagan 
1760d5f81602SSean Eric Fagan void
1761d5f81602SSean Eric Fagan setsugid(p)
1762d5f81602SSean Eric Fagan 	struct proc *p;
1763d5f81602SSean Eric Fagan {
1764d5f81602SSean Eric Fagan 	p->p_flag |= P_SUGID;
176589361835SSean Eric Fagan 	if (!(p->p_pfsflags & PF_ISUGID))
1766d5f81602SSean Eric Fagan 		p->p_stops = 0;
1767d5f81602SSean Eric Fagan }
1768f535380cSDon Lewis 
17697fd6a959SRobert Watson /*-
17707fd6a959SRobert Watson  * Change a process's effective uid.
1771b1fc0ec1SRobert Watson  * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified.
1772b1fc0ec1SRobert Watson  * References: newcred must be an exclusive credential reference for the
1773b1fc0ec1SRobert Watson  *             duration of the call.
1774f535380cSDon Lewis  */
1775f535380cSDon Lewis void
1776b1fc0ec1SRobert Watson change_euid(newcred, euid)
1777b1fc0ec1SRobert Watson 	struct ucred *newcred;
1778f535380cSDon Lewis 	uid_t euid;
1779f535380cSDon Lewis {
1780f535380cSDon Lewis 
1781b1fc0ec1SRobert Watson 	newcred->cr_uid = euid;
1782b1fc0ec1SRobert Watson 	uifree(newcred->cr_uidinfo);
1783b1fc0ec1SRobert Watson 	newcred->cr_uidinfo = uifind(euid);
1784f535380cSDon Lewis }
1785f535380cSDon Lewis 
17867fd6a959SRobert Watson /*-
17877fd6a959SRobert Watson  * Change a process's effective gid.
1788b1fc0ec1SRobert Watson  * Side effects: newcred->cr_gid will be modified.
1789b1fc0ec1SRobert Watson  * References: newcred must be an exclusive credential reference for the
1790b1fc0ec1SRobert Watson  *             duration of the call.
1791f535380cSDon Lewis  */
1792810bfc8eSAndrew Gallatin void
1793b1fc0ec1SRobert Watson change_egid(newcred, egid)
1794b1fc0ec1SRobert Watson 	struct ucred *newcred;
1795b1fc0ec1SRobert Watson 	gid_t egid;
1796b1fc0ec1SRobert Watson {
1797b1fc0ec1SRobert Watson 
1798b1fc0ec1SRobert Watson 	newcred->cr_groups[0] = egid;
1799b1fc0ec1SRobert Watson }
1800b1fc0ec1SRobert Watson 
18017fd6a959SRobert Watson /*-
18027fd6a959SRobert Watson  * Change a process's real uid.
1803b1fc0ec1SRobert Watson  * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo
1804b1fc0ec1SRobert Watson  *               will be updated, and the old and new cr_ruidinfo proc
1805b1fc0ec1SRobert Watson  *               counts will be updated.
1806b1fc0ec1SRobert Watson  * References: newcred must be an exclusive credential reference for the
1807b1fc0ec1SRobert Watson  *             duration of the call.
1808b1fc0ec1SRobert Watson  */
1809b1fc0ec1SRobert Watson void
1810b1fc0ec1SRobert Watson change_ruid(newcred, ruid)
1811b1fc0ec1SRobert Watson 	struct ucred *newcred;
1812f535380cSDon Lewis 	uid_t ruid;
1813f535380cSDon Lewis {
1814f535380cSDon Lewis 
1815b1fc0ec1SRobert Watson 	(void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
1816b1fc0ec1SRobert Watson 	newcred->cr_ruid = ruid;
1817b1fc0ec1SRobert Watson 	uifree(newcred->cr_ruidinfo);
1818b1fc0ec1SRobert Watson 	newcred->cr_ruidinfo = uifind(ruid);
1819b1fc0ec1SRobert Watson 	(void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
1820b1fc0ec1SRobert Watson }
1821b1fc0ec1SRobert Watson 
18227fd6a959SRobert Watson /*-
18237fd6a959SRobert Watson  * Change a process's real gid.
1824b1fc0ec1SRobert Watson  * Side effects: newcred->cr_rgid will be updated.
1825b1fc0ec1SRobert Watson  * References: newcred must be an exclusive credential reference for the
1826b1fc0ec1SRobert Watson  *             duration of the call.
1827b1fc0ec1SRobert Watson  */
1828b1fc0ec1SRobert Watson void
1829b1fc0ec1SRobert Watson change_rgid(newcred, rgid)
1830b1fc0ec1SRobert Watson 	struct ucred *newcred;
1831b1fc0ec1SRobert Watson 	gid_t rgid;
1832b1fc0ec1SRobert Watson {
1833b1fc0ec1SRobert Watson 
1834b1fc0ec1SRobert Watson 	newcred->cr_rgid = rgid;
1835b1fc0ec1SRobert Watson }
1836b1fc0ec1SRobert Watson 
18377fd6a959SRobert Watson /*-
18387fd6a959SRobert Watson  * Change a process's saved uid.
1839b1fc0ec1SRobert Watson  * Side effects: newcred->cr_svuid will be updated.
1840b1fc0ec1SRobert Watson  * References: newcred must be an exclusive credential reference for the
1841b1fc0ec1SRobert Watson  *             duration of the call.
1842b1fc0ec1SRobert Watson  */
1843b1fc0ec1SRobert Watson void
1844b1fc0ec1SRobert Watson change_svuid(newcred, svuid)
1845b1fc0ec1SRobert Watson 	struct ucred *newcred;
1846b1fc0ec1SRobert Watson 	uid_t svuid;
1847b1fc0ec1SRobert Watson {
1848b1fc0ec1SRobert Watson 
1849b1fc0ec1SRobert Watson 	newcred->cr_svuid = svuid;
1850b1fc0ec1SRobert Watson }
1851b1fc0ec1SRobert Watson 
18527fd6a959SRobert Watson /*-
18537fd6a959SRobert Watson  * Change a process's saved gid.
1854b1fc0ec1SRobert Watson  * Side effects: newcred->cr_svgid will be updated.
1855b1fc0ec1SRobert Watson  * References: newcred must be an exclusive credential reference for the
1856b1fc0ec1SRobert Watson  *             duration of the call.
1857b1fc0ec1SRobert Watson  */
1858b1fc0ec1SRobert Watson void
1859b1fc0ec1SRobert Watson change_svgid(newcred, svgid)
1860b1fc0ec1SRobert Watson 	struct ucred *newcred;
1861b1fc0ec1SRobert Watson 	gid_t svgid;
1862b1fc0ec1SRobert Watson {
1863b1fc0ec1SRobert Watson 
1864b1fc0ec1SRobert Watson 	newcred->cr_svgid = svgid;
1865f535380cSDon Lewis }
1866