xref: /freebsd/sys/kern/kern_prot.c (revision 6adf353a56a161443406b44a45d00c688ca7b857)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)kern_prot.c	8.6 (Berkeley) 1/21/94
39  * $FreeBSD$
40  */
41 
42 /*
43  * System calls related to processes and protection
44  */
45 
46 #include "opt_compat.h"
47 #include "opt_global.h"
48 
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/acct.h>
52 #include <sys/kernel.h>
53 #include <sys/lock.h>
54 #include <sys/mutex.h>
55 #include <sys/proc.h>
56 #include <sys/sysproto.h>
57 #include <sys/malloc.h>
58 #include <sys/pioctl.h>
59 #include <sys/resourcevar.h>
60 #include <sys/sysctl.h>
61 #include <sys/jail.h>
62 
63 static MALLOC_DEFINE(M_CRED, "cred", "credentials");
64 
65 SYSCTL_NODE(_kern, OID_AUTO, security, CTLFLAG_RW, 0,
66     "Kernel security policy");
67 
68 #ifndef _SYS_SYSPROTO_H_
69 struct getpid_args {
70 	int	dummy;
71 };
72 #endif
73 
74 /*
75  * getpid - MP SAFE
76  */
77 
78 /* ARGSUSED */
79 int
80 getpid(p, uap)
81 	struct proc *p;
82 	struct getpid_args *uap;
83 {
84 
85 	p->p_retval[0] = p->p_pid;
86 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
87 	PROC_LOCK(p);
88 	p->p_retval[1] = p->p_pptr->p_pid;
89 	PROC_UNLOCK(p);
90 #endif
91 	return (0);
92 }
93 
94 /*
95  * getppid - MP SAFE
96  */
97 
98 #ifndef _SYS_SYSPROTO_H_
99 struct getppid_args {
100         int     dummy;
101 };
102 #endif
103 /* ARGSUSED */
104 int
105 getppid(p, uap)
106 	struct proc *p;
107 	struct getppid_args *uap;
108 {
109 
110 	PROC_LOCK(p);
111 	p->p_retval[0] = p->p_pptr->p_pid;
112 	PROC_UNLOCK(p);
113 	return (0);
114 }
115 
116 /*
117  * Get process group ID; note that POSIX getpgrp takes no parameter
118  *
119  * MP SAFE
120  */
121 #ifndef _SYS_SYSPROTO_H_
122 struct getpgrp_args {
123         int     dummy;
124 };
125 #endif
126 
127 int
128 getpgrp(p, uap)
129 	struct proc *p;
130 	struct getpgrp_args *uap;
131 {
132 
133 	p->p_retval[0] = p->p_pgrp->pg_id;
134 	return (0);
135 }
136 
137 /* Get an arbitary pid's process group id */
138 #ifndef _SYS_SYSPROTO_H_
139 struct getpgid_args {
140 	pid_t	pid;
141 };
142 #endif
143 
144 int
145 getpgid(p, uap)
146 	struct proc *p;
147 	struct getpgid_args *uap;
148 {
149 	struct proc *pt;
150 	int error;
151 
152 	if (uap->pid == 0)
153 		p->p_retval[0] = p->p_pgrp->pg_id;
154 	else {
155 		if ((pt = pfind(uap->pid)) == NULL)
156 			return ESRCH;
157 		if ((error = p_cansee(p, pt))) {
158 			PROC_UNLOCK(pt);
159 			return (error);
160 		}
161 		p->p_retval[0] = pt->p_pgrp->pg_id;
162 		PROC_UNLOCK(pt);
163 	}
164 	return 0;
165 }
166 
167 /*
168  * Get an arbitary pid's session id.
169  */
170 #ifndef _SYS_SYSPROTO_H_
171 struct getsid_args {
172 	pid_t	pid;
173 };
174 #endif
175 
176 int
177 getsid(p, uap)
178 	struct proc *p;
179 	struct getsid_args *uap;
180 {
181 	struct proc *pt;
182 	int error;
183 
184 	if (uap->pid == 0)
185 		p->p_retval[0] = p->p_session->s_sid;
186 	else {
187 		if ((pt = pfind(uap->pid)) == NULL)
188 			return ESRCH;
189 		if ((error = p_cansee(p, pt))) {
190 			PROC_UNLOCK(pt);
191 			return (error);
192 		}
193 		p->p_retval[0] = pt->p_session->s_sid;
194 		PROC_UNLOCK(pt);
195 	}
196 	return 0;
197 }
198 
199 
200 /*
201  * getuid() - MP SAFE
202  */
203 #ifndef _SYS_SYSPROTO_H_
204 struct getuid_args {
205         int     dummy;
206 };
207 #endif
208 
209 /* ARGSUSED */
210 int
211 getuid(p, uap)
212 	struct proc *p;
213 	struct getuid_args *uap;
214 {
215 
216 	p->p_retval[0] = p->p_ucred->cr_ruid;
217 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
218 	p->p_retval[1] = p->p_ucred->cr_uid;
219 #endif
220 	return (0);
221 }
222 
223 /*
224  * geteuid() - MP SAFE
225  */
226 #ifndef _SYS_SYSPROTO_H_
227 struct geteuid_args {
228         int     dummy;
229 };
230 #endif
231 
232 /* ARGSUSED */
233 int
234 geteuid(p, uap)
235 	struct proc *p;
236 	struct geteuid_args *uap;
237 {
238 
239 	p->p_retval[0] = p->p_ucred->cr_uid;
240 	return (0);
241 }
242 
243 /*
244  * getgid() - MP SAFE
245  */
246 #ifndef _SYS_SYSPROTO_H_
247 struct getgid_args {
248         int     dummy;
249 };
250 #endif
251 
252 /* ARGSUSED */
253 int
254 getgid(p, uap)
255 	struct proc *p;
256 	struct getgid_args *uap;
257 {
258 
259 	p->p_retval[0] = p->p_ucred->cr_rgid;
260 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
261 	p->p_retval[1] = p->p_ucred->cr_groups[0];
262 #endif
263 	return (0);
264 }
265 
266 /*
267  * Get effective group ID.  The "egid" is groups[0], and could be obtained
268  * via getgroups.  This syscall exists because it is somewhat painful to do
269  * correctly in a library function.
270  */
271 #ifndef _SYS_SYSPROTO_H_
272 struct getegid_args {
273         int     dummy;
274 };
275 #endif
276 
277 /* ARGSUSED */
278 int
279 getegid(p, uap)
280 	struct proc *p;
281 	struct getegid_args *uap;
282 {
283 
284 	p->p_retval[0] = p->p_ucred->cr_groups[0];
285 	return (0);
286 }
287 
288 #ifndef _SYS_SYSPROTO_H_
289 struct getgroups_args {
290 	u_int	gidsetsize;
291 	gid_t	*gidset;
292 };
293 #endif
294 int
295 getgroups(p, uap)
296 	struct proc *p;
297 	register struct	getgroups_args *uap;
298 {
299 	struct ucred *cred = p->p_ucred;
300 	u_int ngrp;
301 	int error;
302 
303 	if ((ngrp = uap->gidsetsize) == 0) {
304 		p->p_retval[0] = cred->cr_ngroups;
305 		return (0);
306 	}
307 	if (ngrp < cred->cr_ngroups)
308 		return (EINVAL);
309 	ngrp = cred->cr_ngroups;
310 	if ((error = copyout((caddr_t)cred->cr_groups,
311 	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
312 		return (error);
313 	p->p_retval[0] = ngrp;
314 	return (0);
315 }
316 
317 #ifndef _SYS_SYSPROTO_H_
318 struct setsid_args {
319         int     dummy;
320 };
321 #endif
322 
323 /* ARGSUSED */
324 int
325 setsid(p, uap)
326 	register struct proc *p;
327 	struct setsid_args *uap;
328 {
329 
330 	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
331 		return (EPERM);
332 	} else {
333 		(void)enterpgrp(p, p->p_pid, 1);
334 		p->p_retval[0] = p->p_pid;
335 		return (0);
336 	}
337 }
338 
339 /*
340  * set process group (setpgid/old setpgrp)
341  *
342  * caller does setpgid(targpid, targpgid)
343  *
344  * pid must be caller or child of caller (ESRCH)
345  * if a child
346  *	pid must be in same session (EPERM)
347  *	pid can't have done an exec (EACCES)
348  * if pgid != pid
349  * 	there must exist some pid in same session having pgid (EPERM)
350  * pid must not be session leader (EPERM)
351  */
352 #ifndef _SYS_SYSPROTO_H_
353 struct setpgid_args {
354 	int	pid;	/* target process id */
355 	int	pgid;	/* target pgrp id */
356 };
357 #endif
358 /* ARGSUSED */
359 int
360 setpgid(curp, uap)
361 	struct proc *curp;
362 	register struct setpgid_args *uap;
363 {
364 	register struct proc *targp;		/* target process */
365 	register struct pgrp *pgrp;		/* target pgrp */
366 	int error;
367 
368 	if (uap->pgid < 0)
369 		return (EINVAL);
370 	if (uap->pid != 0 && uap->pid != curp->p_pid) {
371 		if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) {
372 			if (targp)
373 				PROC_UNLOCK(targp);
374 			return (ESRCH);
375 		}
376 		if ((error = p_cansee(curproc, targp))) {
377 			PROC_UNLOCK(targp);
378 			return (error);
379 		}
380 		if (targp->p_pgrp == NULL ||
381 		    targp->p_session != curp->p_session) {
382 			PROC_UNLOCK(targp);
383 			return (EPERM);
384 		}
385 		if (targp->p_flag & P_EXEC) {
386 			PROC_UNLOCK(targp);
387 			return (EACCES);
388 		}
389 	} else {
390 		targp = curp;
391 		PROC_LOCK(curp);	/* XXX: not needed */
392 	}
393 	if (SESS_LEADER(targp)) {
394 		PROC_UNLOCK(targp);
395 		return (EPERM);
396 	}
397 	if (uap->pgid == 0)
398 		uap->pgid = targp->p_pid;
399 	else if (uap->pgid != targp->p_pid)
400 		if ((pgrp = pgfind(uap->pgid)) == 0 ||
401 	            pgrp->pg_session != curp->p_session) {
402 			PROC_UNLOCK(targp);
403 			return (EPERM);
404 		}
405 	/* XXX: We should probably hold the lock across enterpgrp. */
406 	PROC_UNLOCK(targp);
407 	return (enterpgrp(targp, uap->pgid, 0));
408 }
409 
410 /*
411  * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
412  * compatible.  It says that setting the uid/gid to euid/egid is a special
413  * case of "appropriate privilege".  Once the rules are expanded out, this
414  * basically means that setuid(nnn) sets all three id's, in all permitted
415  * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
416  * does not set the saved id - this is dangerous for traditional BSD
417  * programs.  For this reason, we *really* do not want to set
418  * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
419  */
420 #define POSIX_APPENDIX_B_4_2_2
421 
422 #ifndef _SYS_SYSPROTO_H_
423 struct setuid_args {
424 	uid_t	uid;
425 };
426 #endif
427 /* ARGSUSED */
428 int
429 setuid(p, uap)
430 	struct proc *p;
431 	struct setuid_args *uap;
432 {
433 	struct ucred *newcred, *oldcred;
434 	uid_t uid;
435 	int error;
436 
437 	uid = uap->uid;
438 	oldcred = p->p_ucred;
439 	/*
440 	 * See if we have "permission" by POSIX 1003.1 rules.
441 	 *
442 	 * Note that setuid(geteuid()) is a special case of
443 	 * "appropriate privileges" in appendix B.4.2.2.  We need
444 	 * to use this clause to be compatible with traditional BSD
445 	 * semantics.  Basically, it means that "setuid(xx)" sets all
446 	 * three id's (assuming you have privs).
447 	 *
448 	 * Notes on the logic.  We do things in three steps.
449 	 * 1: We determine if the euid is going to change, and do EPERM
450 	 *    right away.  We unconditionally change the euid later if this
451 	 *    test is satisfied, simplifying that part of the logic.
452 	 * 2: We determine if the real and/or saved uid's are going to
453 	 *    change.  Determined by compile options.
454 	 * 3: Change euid last. (after tests in #2 for "appropriate privs")
455 	 */
456 	if (uid != oldcred->cr_ruid &&		/* allow setuid(getuid()) */
457 #ifdef _POSIX_SAVED_IDS
458 	    uid != oldcred->cr_svuid &&		/* allow setuid(saved gid) */
459 #endif
460 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
461 	    uid != oldcred->cr_uid &&		/* allow setuid(geteuid()) */
462 #endif
463 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
464 		return (error);
465 
466 	newcred = crdup(oldcred);
467 #ifdef _POSIX_SAVED_IDS
468 	/*
469 	 * Do we have "appropriate privileges" (are we root or uid == euid)
470 	 * If so, we are changing the real uid and/or saved uid.
471 	 */
472 	if (
473 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use the clause from B.4.2.2 */
474 	    uid == oldcred->cr_uid ||
475 #endif
476 	    suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
477 #endif
478 	{
479 		/*
480 		 * Set the real uid and transfer proc count to new user.
481 		 */
482 		if (uid != oldcred->cr_ruid) {
483 			change_ruid(newcred, uid);
484 			setsugid(p);
485 		}
486 		/*
487 		 * Set saved uid
488 		 *
489 		 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
490 		 * the security of seteuid() depends on it.  B.4.2.2 says it
491 		 * is important that we should do this.
492 		 */
493 		if (uid != oldcred->cr_svuid) {
494 			change_svuid(newcred, uid);
495 			setsugid(p);
496 		}
497 	}
498 
499 	/*
500 	 * In all permitted cases, we are changing the euid.
501 	 * Copy credentials so other references do not see our changes.
502 	 */
503 	if (uid != oldcred->cr_uid) {
504 		change_euid(newcred, uid);
505 		setsugid(p);
506 	}
507 	p->p_ucred = newcred;
508 	crfree(oldcred);
509 	return (0);
510 }
511 
512 #ifndef _SYS_SYSPROTO_H_
513 struct seteuid_args {
514 	uid_t	euid;
515 };
516 #endif
517 /* ARGSUSED */
518 int
519 seteuid(p, uap)
520 	struct proc *p;
521 	struct seteuid_args *uap;
522 {
523 	struct ucred *newcred, *oldcred;
524 	uid_t euid;
525 	int error;
526 
527 	euid = uap->euid;
528 	oldcred = p->p_ucred;
529 	if (euid != oldcred->cr_ruid &&		/* allow seteuid(getuid()) */
530 	    euid != oldcred->cr_svuid &&	/* allow seteuid(saved uid) */
531 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
532 		return (error);
533 	/*
534 	 * Everything's okay, do it.  Copy credentials so other references do
535 	 * not see our changes.
536 	 */
537 	newcred = crdup(oldcred);
538 	if (oldcred->cr_uid != euid) {
539 		change_euid(newcred, euid);
540 		setsugid(p);
541 	}
542 	p->p_ucred = newcred;
543 	crfree(oldcred);
544 	return (0);
545 }
546 
547 #ifndef _SYS_SYSPROTO_H_
548 struct setgid_args {
549 	gid_t	gid;
550 };
551 #endif
552 /* ARGSUSED */
553 int
554 setgid(p, uap)
555 	struct proc *p;
556 	struct setgid_args *uap;
557 {
558 	struct ucred *newcred, *oldcred;
559 	gid_t gid;
560 	int error;
561 
562 	gid = uap->gid;
563 	oldcred = p->p_ucred;
564 	/*
565 	 * See if we have "permission" by POSIX 1003.1 rules.
566 	 *
567 	 * Note that setgid(getegid()) is a special case of
568 	 * "appropriate privileges" in appendix B.4.2.2.  We need
569 	 * to use this clause to be compatible with traditional BSD
570 	 * semantics.  Basically, it means that "setgid(xx)" sets all
571 	 * three id's (assuming you have privs).
572 	 *
573 	 * For notes on the logic here, see setuid() above.
574 	 */
575 	if (gid != oldcred->cr_rgid &&		/* allow setgid(getgid()) */
576 #ifdef _POSIX_SAVED_IDS
577 	    gid != oldcred->cr_svgid &&		/* allow setgid(saved gid) */
578 #endif
579 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
580 	    gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */
581 #endif
582 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
583 		return (error);
584 
585 	newcred = crdup(oldcred);
586 #ifdef _POSIX_SAVED_IDS
587 	/*
588 	 * Do we have "appropriate privileges" (are we root or gid == egid)
589 	 * If so, we are changing the real uid and saved gid.
590 	 */
591 	if (
592 #ifdef POSIX_APPENDIX_B_4_2_2	/* use the clause from B.4.2.2 */
593 	    gid == oldcred->cr_groups[0] ||
594 #endif
595 	    suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */
596 #endif
597 	{
598 		/*
599 		 * Set real gid
600 		 */
601 		if (oldcred->cr_rgid != gid) {
602 			change_rgid(newcred, gid);
603 			setsugid(p);
604 		}
605 		/*
606 		 * Set saved gid
607 		 *
608 		 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
609 		 * the security of setegid() depends on it.  B.4.2.2 says it
610 		 * is important that we should do this.
611 		 */
612 		if (oldcred->cr_svgid != gid) {
613 			change_svgid(newcred, gid);
614 			setsugid(p);
615 		}
616 	}
617 	/*
618 	 * In all cases permitted cases, we are changing the egid.
619 	 * Copy credentials so other references do not see our changes.
620 	 */
621 	if (oldcred->cr_groups[0] != gid) {
622 		change_egid(newcred, gid);
623 		setsugid(p);
624 	}
625 	p->p_ucred = newcred;
626 	crfree(oldcred);
627 	return (0);
628 }
629 
630 #ifndef _SYS_SYSPROTO_H_
631 struct setegid_args {
632 	gid_t	egid;
633 };
634 #endif
635 /* ARGSUSED */
636 int
637 setegid(p, uap)
638 	struct proc *p;
639 	struct setegid_args *uap;
640 {
641 	struct ucred *newcred, *oldcred;
642 	gid_t egid;
643 	int error;
644 
645 	egid = uap->egid;
646 	oldcred = p->p_ucred;
647 	if (egid != oldcred->cr_rgid &&		/* allow setegid(getgid()) */
648 	    egid != oldcred->cr_svgid &&	/* allow setegid(saved gid) */
649 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
650 		return (error);
651 	newcred = crdup(oldcred);
652 	if (oldcred->cr_groups[0] != egid) {
653 		change_egid(newcred, egid);
654 		setsugid(p);
655 	}
656 	p->p_ucred = newcred;
657 	crfree(oldcred);
658 	return (0);
659 }
660 
661 #ifndef _SYS_SYSPROTO_H_
662 struct setgroups_args {
663 	u_int	gidsetsize;
664 	gid_t	*gidset;
665 };
666 #endif
667 /* ARGSUSED */
668 int
669 setgroups(p, uap)
670 	struct proc *p;
671 	struct setgroups_args *uap;
672 {
673 	struct ucred *newcred, *oldcred;
674 	u_int ngrp;
675 	int error;
676 
677 	ngrp = uap->gidsetsize;
678 	oldcred = p->p_ucred;
679 	if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
680 		return (error);
681 	if (ngrp > NGROUPS)
682 		return (EINVAL);
683 	/*
684 	 * XXX A little bit lazy here.  We could test if anything has
685 	 * changed before crcopy() and setting P_SUGID.
686 	 */
687 	newcred = crdup(oldcred);
688 	if (ngrp < 1) {
689 		/*
690 		 * setgroups(0, NULL) is a legitimate way of clearing the
691 		 * groups vector on non-BSD systems (which generally do not
692 		 * have the egid in the groups[0]).  We risk security holes
693 		 * when running non-BSD software if we do not do the same.
694 		 */
695 		newcred->cr_ngroups = 1;
696 	} else {
697 		if ((error = copyin((caddr_t)uap->gidset,
698 		    (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) {
699 			crfree(newcred);
700 			return (error);
701 		}
702 		newcred->cr_ngroups = ngrp;
703 	}
704 	setsugid(p);
705 	p->p_ucred = newcred;
706 	crfree(oldcred);
707 	return (0);
708 }
709 
710 #ifndef _SYS_SYSPROTO_H_
711 struct setreuid_args {
712 	uid_t	ruid;
713 	uid_t	euid;
714 };
715 #endif
716 /* ARGSUSED */
717 int
718 setreuid(p, uap)
719 	register struct proc *p;
720 	struct setreuid_args *uap;
721 {
722 	struct ucred *newcred, *oldcred;
723 	uid_t ruid, euid;
724 	int error;
725 
726 	ruid = uap->ruid;
727 	euid = uap->euid;
728 	oldcred = p->p_ucred;
729 	if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
730 	      ruid != oldcred->cr_svuid) ||
731 	     (euid != (uid_t)-1 && euid != oldcred->cr_uid &&
732 	      euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
733 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
734 		return (error);
735 	newcred = crdup(oldcred);
736 	if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
737 		change_euid(newcred, euid);
738 		setsugid(p);
739 	}
740 	if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
741 		change_ruid(newcred, ruid);
742 		setsugid(p);
743 	}
744 	if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) &&
745 	    newcred->cr_svuid != newcred->cr_uid) {
746 		change_svuid(newcred, newcred->cr_uid);
747 		setsugid(p);
748 	}
749 	p->p_ucred = newcred;
750 	crfree(oldcred);
751 	return (0);
752 }
753 
754 #ifndef _SYS_SYSPROTO_H_
755 struct setregid_args {
756 	gid_t	rgid;
757 	gid_t	egid;
758 };
759 #endif
760 /* ARGSUSED */
761 int
762 setregid(p, uap)
763 	register struct proc *p;
764 	struct setregid_args *uap;
765 {
766 	struct ucred *newcred, *oldcred;
767 	gid_t rgid, egid;
768 	int error;
769 
770 	rgid = uap->rgid;
771 	egid = uap->egid;
772 	oldcred = p->p_ucred;
773 	if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
774 	    rgid != oldcred->cr_svgid) ||
775 	     (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] &&
776 	     egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) &&
777 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
778 		return (error);
779 
780 	newcred = crdup(oldcred);
781 	if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
782 		change_egid(newcred, egid);
783 		setsugid(p);
784 	}
785 	if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
786 		change_rgid(newcred, rgid);
787 		setsugid(p);
788 	}
789 	if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) &&
790 	    newcred->cr_svgid != newcred->cr_groups[0]) {
791 		change_svgid(newcred, newcred->cr_groups[0]);
792 		setsugid(p);
793 	}
794 	p->p_ucred = newcred;
795 	crfree(oldcred);
796 	return (0);
797 }
798 
799 /*
800  * setresuid(ruid, euid, suid) is like setreuid except control over the
801  * saved uid is explicit.
802  */
803 
804 #ifndef _SYS_SYSPROTO_H_
805 struct setresuid_args {
806 	uid_t	ruid;
807 	uid_t	euid;
808 	uid_t	suid;
809 };
810 #endif
811 /* ARGSUSED */
812 int
813 setresuid(p, uap)
814 	register struct proc *p;
815 	struct setresuid_args *uap;
816 {
817 	struct ucred *newcred, *oldcred;
818 	uid_t ruid, euid, suid;
819 	int error;
820 
821 	ruid = uap->ruid;
822 	euid = uap->euid;
823 	suid = uap->suid;
824 	oldcred = p->p_ucred;
825 	if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
826 	     ruid != oldcred->cr_svuid &&
827 	      ruid != oldcred->cr_uid) ||
828 	     (euid != (uid_t)-1 && euid != oldcred->cr_ruid &&
829 	    euid != oldcred->cr_svuid &&
830 	      euid != oldcred->cr_uid) ||
831 	     (suid != (uid_t)-1 && suid != oldcred->cr_ruid &&
832 	    suid != oldcred->cr_svuid &&
833 	      suid != oldcred->cr_uid)) &&
834 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
835 		return (error);
836 
837 	newcred = crdup(oldcred);
838 	if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
839 		change_euid(newcred, euid);
840 		setsugid(p);
841 	}
842 	if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
843 		change_ruid(newcred, ruid);
844 		setsugid(p);
845 	}
846 	if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) {
847 		change_svuid(newcred, suid);
848 		setsugid(p);
849 	}
850 	p->p_ucred = newcred;
851 	crfree(oldcred);
852 	return (0);
853 }
854 
855 /*
856  * setresgid(rgid, egid, sgid) is like setregid except control over the
857  * saved gid is explicit.
858  */
859 
860 #ifndef _SYS_SYSPROTO_H_
861 struct setresgid_args {
862 	gid_t	rgid;
863 	gid_t	egid;
864 	gid_t	sgid;
865 };
866 #endif
867 /* ARGSUSED */
868 int
869 setresgid(p, uap)
870 	register struct proc *p;
871 	struct setresgid_args *uap;
872 {
873 	struct ucred *newcred, *oldcred;
874 	gid_t rgid, egid, sgid;
875 	int error;
876 
877 	rgid = uap->rgid;
878 	egid = uap->egid;
879 	sgid = uap->sgid;
880 	oldcred = p->p_ucred;
881 	if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
882 	      rgid != oldcred->cr_svgid &&
883 	      rgid != oldcred->cr_groups[0]) ||
884 	     (egid != (gid_t)-1 && egid != oldcred->cr_rgid &&
885 	      egid != oldcred->cr_svgid &&
886 	      egid != oldcred->cr_groups[0]) ||
887 	     (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid &&
888 	      sgid != oldcred->cr_svgid &&
889 	      sgid != oldcred->cr_groups[0])) &&
890 	    (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
891 		return (error);
892 
893 	newcred = crdup(oldcred);
894 	if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
895 		change_egid(newcred, egid);
896 		setsugid(p);
897 	}
898 	if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) {
899 		change_rgid(newcred, rgid);
900 		setsugid(p);
901 	}
902 	if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) {
903 		change_svgid(newcred, sgid);
904 		setsugid(p);
905 	}
906 	p->p_ucred = newcred;
907 	crfree(oldcred);
908 	return (0);
909 }
910 
911 #ifndef _SYS_SYSPROTO_H_
912 struct getresuid_args {
913 	uid_t	*ruid;
914 	uid_t	*euid;
915 	uid_t	*suid;
916 };
917 #endif
918 /* ARGSUSED */
919 int
920 getresuid(p, uap)
921 	register struct proc *p;
922 	struct getresuid_args *uap;
923 {
924 	struct ucred *cred = p->p_ucred;
925 	int error1 = 0, error2 = 0, error3 = 0;
926 
927 	if (uap->ruid)
928 		error1 = copyout((caddr_t)&cred->cr_ruid,
929 		    (caddr_t)uap->ruid, sizeof(cred->cr_ruid));
930 	if (uap->euid)
931 		error2 = copyout((caddr_t)&cred->cr_uid,
932 		    (caddr_t)uap->euid, sizeof(cred->cr_uid));
933 	if (uap->suid)
934 		error3 = copyout((caddr_t)&cred->cr_svuid,
935 		    (caddr_t)uap->suid, sizeof(cred->cr_svuid));
936 	return error1 ? error1 : (error2 ? error2 : error3);
937 }
938 
939 #ifndef _SYS_SYSPROTO_H_
940 struct getresgid_args {
941 	gid_t	*rgid;
942 	gid_t	*egid;
943 	gid_t	*sgid;
944 };
945 #endif
946 /* ARGSUSED */
947 int
948 getresgid(p, uap)
949 	register struct proc *p;
950 	struct getresgid_args *uap;
951 {
952 	struct ucred *cred = p->p_ucred;
953 	int error1 = 0, error2 = 0, error3 = 0;
954 
955 	if (uap->rgid)
956 		error1 = copyout((caddr_t)&cred->cr_rgid,
957 		    (caddr_t)uap->rgid, sizeof(cred->cr_rgid));
958 	if (uap->egid)
959 		error2 = copyout((caddr_t)&cred->cr_groups[0],
960 		    (caddr_t)uap->egid, sizeof(cred->cr_groups[0]));
961 	if (uap->sgid)
962 		error3 = copyout((caddr_t)&cred->cr_svgid,
963 		    (caddr_t)uap->sgid, sizeof(cred->cr_svgid));
964 	return error1 ? error1 : (error2 ? error2 : error3);
965 }
966 
967 
968 #ifndef _SYS_SYSPROTO_H_
969 struct issetugid_args {
970 	int dummy;
971 };
972 #endif
973 /* ARGSUSED */
974 int
975 issetugid(p, uap)
976 	register struct proc *p;
977 	struct issetugid_args *uap;
978 {
979 	/*
980 	 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
981 	 * we use P_SUGID because we consider changing the owners as
982 	 * "tainting" as well.
983 	 * This is significant for procs that start as root and "become"
984 	 * a user without an exec - programs cannot know *everything*
985 	 * that libc *might* have put in their data segment.
986 	 */
987 	p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
988 	return (0);
989 }
990 
991 int
992 __setugid(p, uap)
993 	struct proc *p;
994 	struct __setugid_args *uap;
995 {
996 
997 #ifdef REGRESSION
998 	switch (uap->flag) {
999 	case 0:
1000 		p->p_flag &= ~P_SUGID;
1001 		return (0);
1002 	case 1:
1003 		p->p_flag |= P_SUGID;
1004 		return (0);
1005 	default:
1006 		return (EINVAL);
1007 	}
1008 #else /* !REGRESSION */
1009 	return (ENOSYS);
1010 #endif /* !REGRESSION */
1011 }
1012 
1013 /*
1014  * Check if gid is a member of the group set.
1015  */
1016 int
1017 groupmember(gid, cred)
1018 	gid_t gid;
1019 	struct ucred *cred;
1020 {
1021 	register gid_t *gp;
1022 	gid_t *egp;
1023 
1024 	egp = &(cred->cr_groups[cred->cr_ngroups]);
1025 	for (gp = cred->cr_groups; gp < egp; gp++)
1026 		if (*gp == gid)
1027 			return (1);
1028 	return (0);
1029 }
1030 
1031 static int suser_permitted = 1;
1032 
1033 SYSCTL_INT(_kern_security, OID_AUTO, suser_permitted, CTLFLAG_RW,
1034     &suser_permitted, 0, "processes with uid 0 have privilege");
1035 
1036 /*
1037  * Test whether the specified credentials imply "super-user"
1038  * privilege; if so, and we have accounting info, set the flag
1039  * indicating use of super-powers.
1040  * Returns 0 or error.
1041  */
1042 int
1043 suser(p)
1044 	struct proc *p;
1045 {
1046 	return suser_xxx(0, p, 0);
1047 }
1048 
1049 int
1050 suser_xxx(cred, proc, flag)
1051 	struct ucred *cred;
1052 	struct proc *proc;
1053 	int flag;
1054 {
1055 	if (!suser_permitted)
1056 		return (EPERM);
1057 	if (!cred && !proc) {
1058 		printf("suser_xxx(): THINK!\n");
1059 		return (EPERM);
1060 	}
1061 	if (!cred)
1062 		cred = proc->p_ucred;
1063 	if (cred->cr_uid != 0)
1064 		return (EPERM);
1065 	if (jailed(cred) && !(flag & PRISON_ROOT))
1066 		return (EPERM);
1067 	return (0);
1068 }
1069 
1070 /*
1071  * u_cansee(u1, u2): determine if u1 "can see" the subject specified by u2
1072  * Arguments: imutable credentials u1, u2
1073  * Returns: 0 for permitted, an errno value otherwise
1074  * Locks: none
1075  * References: u1 and u2 must be valid for the lifetime of the call
1076  *             u1 may equal u2, in which case only one reference is required
1077  */
1078 int
1079 u_cansee(struct ucred *u1, struct ucred *u2)
1080 {
1081 	int error;
1082 
1083 	if ((error = prison_check(u1, u2)))
1084 		return (error);
1085 	if (!ps_showallprocs && u1->cr_ruid != u2->cr_ruid) {
1086 		if (suser_xxx(u1, NULL, PRISON_ROOT) != 0)
1087 			return (ESRCH);
1088 	}
1089 	return (0);
1090 }
1091 
1092 int
1093 p_cansee(struct proc *p1, struct proc *p2)
1094 {
1095 
1096 	/* Wrap u_cansee() for all functionality. */
1097 	return (u_cansee(p1->p_ucred, p2->p_ucred));
1098 }
1099 
1100 /*
1101  * Can process p1 send the signal signum to process p2?
1102  */
1103 int
1104 p_cansignal(struct proc *p1, struct proc *p2, int signum)
1105 {
1106 	int	error;
1107 
1108 	if (p1 == p2)
1109 		return (0);
1110 
1111 	/*
1112 	 * Jail semantics limit the scope of signalling to p2 in the same
1113 	 * jail as p1, if p1 is in jail.
1114 	 */
1115 	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1116 		return (error);
1117 
1118 	/*
1119 	 * UNIX signalling semantics require that processes in the same
1120 	 * session always be able to deliver SIGCONT to one another,
1121 	 * overriding the remaining protections.
1122 	 */
1123 	if (signum == SIGCONT && p1->p_session == p2->p_session)
1124 		return (0);
1125 
1126 	/*
1127 	 * UNIX uid semantics depend on the status of the P_SUGID
1128 	 * bit on the target process.  If the bit is set, then more
1129 	 * restricted signal sets are permitted.
1130 	 */
1131 	if (p2->p_flag & P_SUGID) {
1132 		switch (signum) {
1133 		case 0:
1134 		case SIGKILL:
1135 		case SIGINT:
1136 		case SIGTERM:
1137 		case SIGSTOP:
1138 		case SIGTTIN:
1139 		case SIGTTOU:
1140 		case SIGTSTP:
1141 		case SIGHUP:
1142 		case SIGUSR1:
1143 		case SIGUSR2:
1144 			break;
1145 		default:
1146 			/* Not permitted, try privilege. */
1147 			error = suser_xxx(NULL, p1, PRISON_ROOT);
1148 			if (error)
1149 				return (error);
1150 		}
1151 	}
1152 
1153 	/*
1154 	 * Generally, the object credential's ruid or svuid must match the
1155 	 * subject credential's ruid or euid.
1156 	 */
1157 	if (p1->p_ucred->cr_ruid != p2->p_ucred->cr_ruid &&
1158 	    p1->p_ucred->cr_ruid != p2->p_ucred->cr_svuid &&
1159 	    p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid &&
1160 	    p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid) {
1161 		/* Not permitted, try privilege. */
1162 		error = suser_xxx(NULL, p1, PRISON_ROOT);
1163 		if (error)
1164 			return (error);
1165 	}
1166 
1167         return (0);
1168 }
1169 
1170 int
1171 p_cansched(struct proc *p1, struct proc *p2)
1172 {
1173 	int error;
1174 
1175 	if (p1 == p2)
1176 		return (0);
1177 
1178 	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1179 		return (error);
1180 
1181 	if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid)
1182 		return (0);
1183 	if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid)
1184 		return (0);
1185 
1186 	if (!suser_xxx(0, p1, PRISON_ROOT))
1187 		return (0);
1188 
1189 #ifdef CAPABILITIES
1190 	if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT))
1191 		return (0);
1192 #endif
1193 
1194 	return (EPERM);
1195 }
1196 
1197 static int	kern_unprivileged_procdebug_permitted = 1;
1198 SYSCTL_INT(_kern_security, OID_AUTO, unprivileged_procdebug_permitted,
1199     CTLFLAG_RW, &kern_unprivileged_procdebug_permitted, 0,
1200     "Unprivileged processes may use process debugging facilities");
1201 
1202 int
1203 p_candebug(struct proc *p1, struct proc *p2)
1204 {
1205 	int error;
1206 
1207 	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
1208 		return (error);
1209 
1210 	/* not owned by you, has done setuid (unless you're root) */
1211 	/* add a CAP_SYS_PTRACE here? */
1212 	if (p1->p_ucred->cr_uid != p2->p_ucred->cr_uid ||
1213 	    p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid ||
1214 	    p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid ||
1215 	    p2->p_flag & P_SUGID || !kern_unprivileged_procdebug_permitted)
1216 		if ((error = suser_xxx(0, p1, PRISON_ROOT)))
1217 			return (error);
1218 
1219 	/* can't trace init when securelevel > 0 */
1220 	if (securelevel > 0 && p2->p_pid == 1)
1221 		return (EPERM);
1222 
1223 	return (0);
1224 }
1225 
1226 /*
1227  * Allocate a zeroed cred structure.
1228  */
1229 struct ucred *
1230 crget()
1231 {
1232 	register struct ucred *cr;
1233 
1234 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK|M_ZERO);
1235 	cr->cr_ref = 1;
1236 	mtx_init(&cr->cr_mtx, "ucred", MTX_DEF);
1237 	return (cr);
1238 }
1239 
1240 /*
1241  * Claim another reference to a ucred structure
1242  */
1243 void
1244 crhold(cr)
1245 	struct ucred *cr;
1246 {
1247 
1248 	mtx_lock(&cr->cr_mtx);
1249 	cr->cr_ref++;
1250 	mtx_unlock(&(cr)->cr_mtx);
1251 }
1252 
1253 
1254 /*
1255  * Free a cred structure.
1256  * Throws away space when ref count gets to 0.
1257  */
1258 void
1259 crfree(cr)
1260 	struct ucred *cr;
1261 {
1262 
1263 	mtx_lock(&cr->cr_mtx);
1264 	KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
1265 	if (--cr->cr_ref == 0) {
1266 		mtx_destroy(&cr->cr_mtx);
1267 		/*
1268 		 * Some callers of crget(), such as nfs_statfs(),
1269 		 * allocate a temporary credential, but don't
1270 		 * allocate a uidinfo structure.
1271 		 */
1272 		if (cr->cr_uidinfo != NULL)
1273 			uifree(cr->cr_uidinfo);
1274 		if (cr->cr_ruidinfo != NULL)
1275 			uifree(cr->cr_ruidinfo);
1276 		/*
1277 		 * Free a prison, if any.
1278 		 */
1279 		if (jailed(cr))
1280 			prison_free(cr->cr_prison);
1281 		FREE((caddr_t)cr, M_CRED);
1282 	} else {
1283 		mtx_unlock(&cr->cr_mtx);
1284 	}
1285 }
1286 
1287 /*
1288  * Copy cred structure to a new one and free the old one.
1289  */
1290 struct ucred *
1291 crcopy(cr)
1292 	struct ucred *cr;
1293 {
1294 	struct ucred *newcr;
1295 
1296 	mtx_lock(&cr->cr_mtx);
1297 	if (cr->cr_ref == 1) {
1298 		mtx_unlock(&cr->cr_mtx);
1299 		return (cr);
1300 	}
1301 	mtx_unlock(&cr->cr_mtx);
1302 	newcr = crdup(cr);
1303 	crfree(cr);
1304 	return (newcr);
1305 }
1306 
1307 /*
1308  * Dup cred struct to a new held one.
1309  */
1310 struct ucred *
1311 crdup(cr)
1312 	struct ucred *cr;
1313 {
1314 	struct ucred *newcr;
1315 
1316 	MALLOC(newcr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
1317 	*newcr = *cr;
1318 	mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF);
1319 	uihold(newcr->cr_uidinfo);
1320 	uihold(newcr->cr_ruidinfo);
1321 	if (jailed(newcr))
1322 		prison_hold(newcr->cr_prison);
1323 	newcr->cr_ref = 1;
1324 	return (newcr);
1325 }
1326 
1327 /*
1328  * Get login name, if available.
1329  */
1330 #ifndef _SYS_SYSPROTO_H_
1331 struct getlogin_args {
1332 	char	*namebuf;
1333 	u_int	namelen;
1334 };
1335 #endif
1336 /* ARGSUSED */
1337 int
1338 getlogin(p, uap)
1339 	struct proc *p;
1340 	struct getlogin_args *uap;
1341 {
1342 
1343 	if (uap->namelen > MAXLOGNAME)
1344 		uap->namelen = MAXLOGNAME;
1345 	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
1346 	    (caddr_t) uap->namebuf, uap->namelen));
1347 }
1348 
1349 /*
1350  * Set login name.
1351  */
1352 #ifndef _SYS_SYSPROTO_H_
1353 struct setlogin_args {
1354 	char	*namebuf;
1355 };
1356 #endif
1357 /* ARGSUSED */
1358 int
1359 setlogin(p, uap)
1360 	struct proc *p;
1361 	struct setlogin_args *uap;
1362 {
1363 	int error;
1364 	char logintmp[MAXLOGNAME];
1365 
1366 	if ((error = suser_xxx(0, p, PRISON_ROOT)))
1367 		return (error);
1368 	error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
1369 	    sizeof(logintmp), (size_t *)0);
1370 	if (error == ENAMETOOLONG)
1371 		error = EINVAL;
1372 	else if (!error)
1373 		(void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
1374 		    sizeof(logintmp));
1375 	return (error);
1376 }
1377 
1378 void
1379 setsugid(p)
1380 	struct proc *p;
1381 {
1382 	p->p_flag |= P_SUGID;
1383 	if (!(p->p_pfsflags & PF_ISUGID))
1384 		p->p_stops = 0;
1385 }
1386 
1387 /*
1388  * change_euid(): Change a process's effective uid.
1389  * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified.
1390  * References: newcred must be an exclusive credential reference for the
1391  *             duration of the call.
1392  */
1393 void
1394 change_euid(newcred, euid)
1395 	struct ucred *newcred;
1396 	uid_t euid;
1397 {
1398 
1399 	newcred->cr_uid = euid;
1400 	uifree(newcred->cr_uidinfo);
1401 	newcred->cr_uidinfo = uifind(euid);
1402 }
1403 
1404 /*
1405  * change_egid(): Change a process's effective gid.
1406  * Side effects: newcred->cr_gid will be modified.
1407  * References: newcred must be an exclusive credential reference for the
1408  *             duration of the call.
1409  */
1410 void
1411 change_egid(newcred, egid)
1412 	struct ucred *newcred;
1413 	gid_t egid;
1414 {
1415 
1416 	newcred->cr_groups[0] = egid;
1417 }
1418 
1419 /*
1420  * change_ruid(): Change a process's real uid.
1421  * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo
1422  *               will be updated, and the old and new cr_ruidinfo proc
1423  *               counts will be updated.
1424  * References: newcred must be an exclusive credential reference for the
1425  *             duration of the call.
1426  */
1427 void
1428 change_ruid(newcred, ruid)
1429 	struct ucred *newcred;
1430 	uid_t ruid;
1431 {
1432 
1433 	(void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
1434 	newcred->cr_ruid = ruid;
1435 	uifree(newcred->cr_ruidinfo);
1436 	newcred->cr_ruidinfo = uifind(ruid);
1437 	(void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
1438 }
1439 
1440 /*
1441  * change_rgid(): Change a process's real gid.
1442  * Side effects: newcred->cr_rgid will be updated.
1443  * References: newcred must be an exclusive credential reference for the
1444  *             duration of the call.
1445  */
1446 void
1447 change_rgid(newcred, rgid)
1448 	struct ucred *newcred;
1449 	gid_t rgid;
1450 {
1451 
1452 	newcred->cr_rgid = rgid;
1453 }
1454 
1455 /*
1456  * change_svuid(): Change a process's saved uid.
1457  * Side effects: newcred->cr_svuid will be updated.
1458  * References: newcred must be an exclusive credential reference for the
1459  *             duration of the call.
1460  */
1461 void
1462 change_svuid(newcred, svuid)
1463 	struct ucred *newcred;
1464 	uid_t svuid;
1465 {
1466 
1467 	newcred->cr_svuid = svuid;
1468 }
1469 
1470 /*
1471  * change_svgid(): Change a process's saved gid.
1472  * Side effects: newcred->cr_svgid will be updated.
1473  * References: newcred must be an exclusive credential reference for the
1474  *             duration of the call.
1475  */
1476 void
1477 change_svgid(newcred, svgid)
1478 	struct ucred *newcred;
1479 	gid_t svgid;
1480 {
1481 
1482 	newcred->cr_svgid = svgid;
1483 }
1484