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