xref: /dragonfly/sys/kern/kern_prot.c (revision 984263bc)
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: src/sys/kern/kern_prot.c,v 1.53.2.9 2002/03/09 05:20:26 dd Exp $
40  */
41 
42 /*
43  * System calls related to processes and protection
44  */
45 
46 #include "opt_compat.h"
47 
48 #include <sys/param.h>
49 #include <sys/acct.h>
50 #include <sys/systm.h>
51 #include <sys/sysproto.h>
52 #include <sys/kernel.h>
53 #include <sys/proc.h>
54 #include <sys/malloc.h>
55 #include <sys/pioctl.h>
56 #include <sys/resourcevar.h>
57 
58 static MALLOC_DEFINE(M_CRED, "cred", "credentials");
59 
60 #ifndef _SYS_SYSPROTO_H_
61 struct getpid_args {
62 	int	dummy;
63 };
64 #endif
65 
66 /*
67  * NOT MP SAFE due to p_pptr access
68  */
69 /* ARGSUSED */
70 int
71 getpid(p, uap)
72 	struct proc *p;
73 	struct getpid_args *uap;
74 {
75 
76 	p->p_retval[0] = p->p_pid;
77 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
78 	p->p_retval[1] = p->p_pptr->p_pid;
79 #endif
80 	return (0);
81 }
82 
83 #ifndef _SYS_SYSPROTO_H_
84 struct getppid_args {
85         int     dummy;
86 };
87 #endif
88 /* ARGSUSED */
89 int
90 getppid(p, uap)
91 	struct proc *p;
92 	struct getppid_args *uap;
93 {
94 
95 	p->p_retval[0] = p->p_pptr->p_pid;
96 	return (0);
97 }
98 
99 /*
100  * Get process group ID; note that POSIX getpgrp takes no parameter
101  *
102  * MP SAFE
103  */
104 #ifndef _SYS_SYSPROTO_H_
105 struct getpgrp_args {
106         int     dummy;
107 };
108 #endif
109 
110 int
111 getpgrp(p, uap)
112 	struct proc *p;
113 	struct getpgrp_args *uap;
114 {
115 
116 	p->p_retval[0] = p->p_pgrp->pg_id;
117 	return (0);
118 }
119 
120 /* Get an arbitary pid's process group id */
121 #ifndef _SYS_SYSPROTO_H_
122 struct getpgid_args {
123 	pid_t	pid;
124 };
125 #endif
126 
127 int
128 getpgid(p, uap)
129 	struct proc *p;
130 	struct getpgid_args *uap;
131 {
132 	struct proc *pt;
133 
134 	pt = p;
135 	if (uap->pid == 0)
136 		goto found;
137 
138 	if ((pt = pfind(uap->pid)) == 0)
139 		return ESRCH;
140 found:
141 	p->p_retval[0] = pt->p_pgrp->pg_id;
142 	return 0;
143 }
144 
145 /*
146  * Get an arbitary pid's session id.
147  */
148 #ifndef _SYS_SYSPROTO_H_
149 struct getsid_args {
150 	pid_t	pid;
151 };
152 #endif
153 
154 int
155 getsid(p, uap)
156 	struct proc *p;
157 	struct getsid_args *uap;
158 {
159 	struct proc *pt;
160 
161 	pt = p;
162 	if (uap->pid == 0)
163 		goto found;
164 
165 	if ((pt = pfind(uap->pid)) == 0)
166 		return ESRCH;
167 found:
168 	p->p_retval[0] = pt->p_session->s_sid;
169 	return 0;
170 }
171 
172 
173 /*
174  * getuid() - MP SAFE
175  */
176 #ifndef _SYS_SYSPROTO_H_
177 struct getuid_args {
178         int     dummy;
179 };
180 #endif
181 
182 /* ARGSUSED */
183 int
184 getuid(p, uap)
185 	struct proc *p;
186 	struct getuid_args *uap;
187 {
188 
189 	p->p_retval[0] = p->p_cred->p_ruid;
190 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
191 	p->p_retval[1] = p->p_ucred->cr_uid;
192 #endif
193 	return (0);
194 }
195 
196 /*
197  * geteuid() - MP SAFE
198  */
199 #ifndef _SYS_SYSPROTO_H_
200 struct geteuid_args {
201         int     dummy;
202 };
203 #endif
204 
205 /* ARGSUSED */
206 int
207 geteuid(p, uap)
208 	struct proc *p;
209 	struct geteuid_args *uap;
210 {
211 
212 	p->p_retval[0] = p->p_ucred->cr_uid;
213 	return (0);
214 }
215 
216 /*
217  * getgid() - MP SAFE
218  */
219 #ifndef _SYS_SYSPROTO_H_
220 struct getgid_args {
221         int     dummy;
222 };
223 #endif
224 
225 /* ARGSUSED */
226 int
227 getgid(p, uap)
228 	struct proc *p;
229 	struct getgid_args *uap;
230 {
231 
232 	p->p_retval[0] = p->p_cred->p_rgid;
233 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
234 	p->p_retval[1] = p->p_ucred->cr_groups[0];
235 #endif
236 	return (0);
237 }
238 
239 /*
240  * Get effective group ID.  The "egid" is groups[0], and could be obtained
241  * via getgroups.  This syscall exists because it is somewhat painful to do
242  * correctly in a library function.
243  */
244 #ifndef _SYS_SYSPROTO_H_
245 struct getegid_args {
246         int     dummy;
247 };
248 #endif
249 
250 /* ARGSUSED */
251 int
252 getegid(p, uap)
253 	struct proc *p;
254 	struct getegid_args *uap;
255 {
256 
257 	p->p_retval[0] = p->p_ucred->cr_groups[0];
258 	return (0);
259 }
260 
261 #ifndef _SYS_SYSPROTO_H_
262 struct getgroups_args {
263 	u_int	gidsetsize;
264 	gid_t	*gidset;
265 };
266 #endif
267 int
268 getgroups(p, uap)
269 	struct proc *p;
270 	register struct	getgroups_args *uap;
271 {
272 	register struct pcred *pc = p->p_cred;
273 	register u_int ngrp;
274 	int error;
275 
276 	if ((ngrp = uap->gidsetsize) == 0) {
277 		p->p_retval[0] = pc->pc_ucred->cr_ngroups;
278 		return (0);
279 	}
280 	if (ngrp < pc->pc_ucred->cr_ngroups)
281 		return (EINVAL);
282 	ngrp = pc->pc_ucred->cr_ngroups;
283 	if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups,
284 	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
285 		return (error);
286 	p->p_retval[0] = ngrp;
287 	return (0);
288 }
289 
290 #ifndef _SYS_SYSPROTO_H_
291 struct setsid_args {
292         int     dummy;
293 };
294 #endif
295 
296 /* ARGSUSED */
297 int
298 setsid(p, uap)
299 	register struct proc *p;
300 	struct setsid_args *uap;
301 {
302 
303 	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
304 		return (EPERM);
305 	} else {
306 		(void)enterpgrp(p, p->p_pid, 1);
307 		p->p_retval[0] = p->p_pid;
308 		return (0);
309 	}
310 }
311 
312 /*
313  * set process group (setpgid/old setpgrp)
314  *
315  * caller does setpgid(targpid, targpgid)
316  *
317  * pid must be caller or child of caller (ESRCH)
318  * if a child
319  *	pid must be in same session (EPERM)
320  *	pid can't have done an exec (EACCES)
321  * if pgid != pid
322  * 	there must exist some pid in same session having pgid (EPERM)
323  * pid must not be session leader (EPERM)
324  */
325 #ifndef _SYS_SYSPROTO_H_
326 struct setpgid_args {
327 	int	pid;	/* target process id */
328 	int	pgid;	/* target pgrp id */
329 };
330 #endif
331 /* ARGSUSED */
332 int
333 setpgid(curp, uap)
334 	struct proc *curp;
335 	register struct setpgid_args *uap;
336 {
337 	register struct proc *targp;		/* target process */
338 	register struct pgrp *pgrp;		/* target pgrp */
339 
340 	if (uap->pgid < 0)
341 		return (EINVAL);
342 	if (uap->pid != 0 && uap->pid != curp->p_pid) {
343 		if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
344 			return (ESRCH);
345 		if (targp->p_pgrp == NULL ||  targp->p_session != curp->p_session)
346 			return (EPERM);
347 		if (targp->p_flag & P_EXEC)
348 			return (EACCES);
349 	} else
350 		targp = curp;
351 	if (SESS_LEADER(targp))
352 		return (EPERM);
353 	if (uap->pgid == 0)
354 		uap->pgid = targp->p_pid;
355 	else if (uap->pgid != targp->p_pid)
356 		if ((pgrp = pgfind(uap->pgid)) == 0 ||
357 	            pgrp->pg_session != curp->p_session)
358 			return (EPERM);
359 	return (enterpgrp(targp, uap->pgid, 0));
360 }
361 
362 /*
363  * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD
364  * compatable.  It says that setting the uid/gid to euid/egid is a special
365  * case of "appropriate privilege".  Once the rules are expanded out, this
366  * basically means that setuid(nnn) sets all three id's, in all permitted
367  * cases unless _POSIX_SAVED_IDS is enabled.  In that case, setuid(getuid())
368  * does not set the saved id - this is dangerous for traditional BSD
369  * programs.  For this reason, we *really* do not want to set
370  * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2.
371  */
372 #define POSIX_APPENDIX_B_4_2_2
373 
374 #ifndef _SYS_SYSPROTO_H_
375 struct setuid_args {
376 	uid_t	uid;
377 };
378 #endif
379 /* ARGSUSED */
380 int
381 setuid(p, uap)
382 	struct proc *p;
383 	struct setuid_args *uap;
384 {
385 	register struct pcred *pc = p->p_cred;
386 	register uid_t uid;
387 	int error;
388 
389 	/*
390 	 * See if we have "permission" by POSIX 1003.1 rules.
391 	 *
392 	 * Note that setuid(geteuid()) is a special case of
393 	 * "appropriate privileges" in appendix B.4.2.2.  We need
394 	 * to use this clause to be compatable with traditional BSD
395 	 * semantics.  Basically, it means that "setuid(xx)" sets all
396 	 * three id's (assuming you have privs).
397 	 *
398 	 * Notes on the logic.  We do things in three steps.
399 	 * 1: We determine if the euid is going to change, and do EPERM
400 	 *    right away.  We unconditionally change the euid later if this
401 	 *    test is satisfied, simplifying that part of the logic.
402 	 * 2: We determine if the real and/or saved uid's are going to
403 	 *    change.  Determined by compile options.
404 	 * 3: Change euid last. (after tests in #2 for "appropriate privs")
405 	 */
406 	uid = uap->uid;
407 	if (uid != pc->p_ruid &&		/* allow setuid(getuid()) */
408 #ifdef _POSIX_SAVED_IDS
409 	    uid != pc->p_svuid &&		/* allow setuid(saved gid) */
410 #endif
411 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
412 	    uid != pc->pc_ucred->cr_uid &&	/* allow setuid(geteuid()) */
413 #endif
414 	    (error = suser_xxx(0, p, PRISON_ROOT)))
415 		return (error);
416 
417 #ifdef _POSIX_SAVED_IDS
418 	/*
419 	 * Do we have "appropriate privileges" (are we root or uid == euid)
420 	 * If so, we are changing the real uid and/or saved uid.
421 	 */
422 	if (
423 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use the clause from B.4.2.2 */
424 	    uid == pc->pc_ucred->cr_uid ||
425 #endif
426 	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
427 #endif
428 	{
429 		/*
430 		 * Set the real uid and transfer proc count to new user.
431 		 */
432 		if (uid != pc->p_ruid) {
433 			change_ruid(p, uid);
434 			setsugid(p);
435 		}
436 		/*
437 		 * Set saved uid
438 		 *
439 		 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as
440 		 * the security of seteuid() depends on it.  B.4.2.2 says it
441 		 * is important that we should do this.
442 		 */
443 		if (pc->p_svuid != uid) {
444 			pc->p_svuid = uid;
445 			setsugid(p);
446 		}
447 	}
448 
449 	/*
450 	 * In all permitted cases, we are changing the euid.
451 	 * Copy credentials so other references do not see our changes.
452 	 */
453 	if (pc->pc_ucred->cr_uid != uid) {
454 		change_euid(p, uid);
455 		setsugid(p);
456 	}
457 	return (0);
458 }
459 
460 #ifndef _SYS_SYSPROTO_H_
461 struct seteuid_args {
462 	uid_t	euid;
463 };
464 #endif
465 /* ARGSUSED */
466 int
467 seteuid(p, uap)
468 	struct proc *p;
469 	struct seteuid_args *uap;
470 {
471 	register struct pcred *pc = p->p_cred;
472 	register uid_t euid;
473 	int error;
474 
475 	euid = uap->euid;
476 	if (euid != pc->p_ruid &&		/* allow seteuid(getuid()) */
477 	    euid != pc->p_svuid &&		/* allow seteuid(saved uid) */
478 	    (error = suser_xxx(0, p, PRISON_ROOT)))
479 		return (error);
480 	/*
481 	 * Everything's okay, do it.  Copy credentials so other references do
482 	 * not see our changes.
483 	 */
484 	if (pc->pc_ucred->cr_uid != euid) {
485 		change_euid(p, euid);
486 		setsugid(p);
487 	}
488 	return (0);
489 }
490 
491 #ifndef _SYS_SYSPROTO_H_
492 struct setgid_args {
493 	gid_t	gid;
494 };
495 #endif
496 /* ARGSUSED */
497 int
498 setgid(p, uap)
499 	struct proc *p;
500 	struct setgid_args *uap;
501 {
502 	register struct pcred *pc = p->p_cred;
503 	register gid_t gid;
504 	int error;
505 
506 	/*
507 	 * See if we have "permission" by POSIX 1003.1 rules.
508 	 *
509 	 * Note that setgid(getegid()) is a special case of
510 	 * "appropriate privileges" in appendix B.4.2.2.  We need
511 	 * to use this clause to be compatable with traditional BSD
512 	 * semantics.  Basically, it means that "setgid(xx)" sets all
513 	 * three id's (assuming you have privs).
514 	 *
515 	 * For notes on the logic here, see setuid() above.
516 	 */
517 	gid = uap->gid;
518 	if (gid != pc->p_rgid &&		/* allow setgid(getgid()) */
519 #ifdef _POSIX_SAVED_IDS
520 	    gid != pc->p_svgid &&		/* allow setgid(saved gid) */
521 #endif
522 #ifdef POSIX_APPENDIX_B_4_2_2	/* Use BSD-compat clause from B.4.2.2 */
523 	    gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */
524 #endif
525 	    (error = suser_xxx(0, p, PRISON_ROOT)))
526 		return (error);
527 
528 #ifdef _POSIX_SAVED_IDS
529 	/*
530 	 * Do we have "appropriate privileges" (are we root or gid == egid)
531 	 * If so, we are changing the real uid and saved gid.
532 	 */
533 	if (
534 #ifdef POSIX_APPENDIX_B_4_2_2	/* use the clause from B.4.2.2 */
535 	    gid == pc->pc_ucred->cr_groups[0] ||
536 #endif
537 	    suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */
538 #endif
539 	{
540 		/*
541 		 * Set real gid
542 		 */
543 		if (pc->p_rgid != gid) {
544 			pc->p_rgid = gid;
545 			setsugid(p);
546 		}
547 		/*
548 		 * Set saved gid
549 		 *
550 		 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as
551 		 * the security of setegid() depends on it.  B.4.2.2 says it
552 		 * is important that we should do this.
553 		 */
554 		if (pc->p_svgid != gid) {
555 			pc->p_svgid = gid;
556 			setsugid(p);
557 		}
558 	}
559 	/*
560 	 * In all cases permitted cases, we are changing the egid.
561 	 * Copy credentials so other references do not see our changes.
562 	 */
563 	if (pc->pc_ucred->cr_groups[0] != gid) {
564 		pc->pc_ucred = crcopy(pc->pc_ucred);
565 		pc->pc_ucred->cr_groups[0] = gid;
566 		setsugid(p);
567 	}
568 	return (0);
569 }
570 
571 #ifndef _SYS_SYSPROTO_H_
572 struct setegid_args {
573 	gid_t	egid;
574 };
575 #endif
576 /* ARGSUSED */
577 int
578 setegid(p, uap)
579 	struct proc *p;
580 	struct setegid_args *uap;
581 {
582 	register struct pcred *pc = p->p_cred;
583 	register gid_t egid;
584 	int error;
585 
586 	egid = uap->egid;
587 	if (egid != pc->p_rgid &&		/* allow setegid(getgid()) */
588 	    egid != pc->p_svgid &&		/* allow setegid(saved gid) */
589 	    (error = suser_xxx(0, p, PRISON_ROOT)))
590 		return (error);
591 	if (pc->pc_ucred->cr_groups[0] != egid) {
592 		pc->pc_ucred = crcopy(pc->pc_ucred);
593 		pc->pc_ucred->cr_groups[0] = egid;
594 		setsugid(p);
595 	}
596 	return (0);
597 }
598 
599 #ifndef _SYS_SYSPROTO_H_
600 struct setgroups_args {
601 	u_int	gidsetsize;
602 	gid_t	*gidset;
603 };
604 #endif
605 /* ARGSUSED */
606 int
607 setgroups(p, uap)
608 	struct proc *p;
609 	struct setgroups_args *uap;
610 {
611 	register struct pcred *pc = p->p_cred;
612 	register u_int ngrp;
613 	int error;
614 
615 	if ((error = suser_xxx(0, p, PRISON_ROOT)))
616 		return (error);
617 	ngrp = uap->gidsetsize;
618 	if (ngrp > NGROUPS)
619 		return (EINVAL);
620 	/*
621 	 * XXX A little bit lazy here.  We could test if anything has
622 	 * changed before crcopy() and setting P_SUGID.
623 	 */
624 	pc->pc_ucred = crcopy(pc->pc_ucred);
625 	if (ngrp < 1) {
626 		/*
627 		 * setgroups(0, NULL) is a legitimate way of clearing the
628 		 * groups vector on non-BSD systems (which generally do not
629 		 * have the egid in the groups[0]).  We risk security holes
630 		 * when running non-BSD software if we do not do the same.
631 		 */
632 		pc->pc_ucred->cr_ngroups = 1;
633 	} else {
634 		if ((error = copyin((caddr_t)uap->gidset,
635 		    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t))))
636 			return (error);
637 		pc->pc_ucred->cr_ngroups = ngrp;
638 	}
639 	setsugid(p);
640 	return (0);
641 }
642 
643 #ifndef _SYS_SYSPROTO_H_
644 struct setreuid_args {
645 	uid_t	ruid;
646 	uid_t	euid;
647 };
648 #endif
649 /* ARGSUSED */
650 int
651 setreuid(p, uap)
652 	register struct proc *p;
653 	struct setreuid_args *uap;
654 {
655 	register struct pcred *pc = p->p_cred;
656 	register uid_t ruid, euid;
657 	int error;
658 
659 	ruid = uap->ruid;
660 	euid = uap->euid;
661 	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) ||
662 	     (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid &&
663 	     euid != pc->p_ruid && euid != pc->p_svuid)) &&
664 	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
665 		return (error);
666 
667 	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
668 		change_euid(p, euid);
669 		setsugid(p);
670 	}
671 	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
672 		change_ruid(p, ruid);
673 		setsugid(p);
674 	}
675 	if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) &&
676 	    pc->p_svuid != pc->pc_ucred->cr_uid) {
677 		pc->p_svuid = pc->pc_ucred->cr_uid;
678 		setsugid(p);
679 	}
680 	return (0);
681 }
682 
683 #ifndef _SYS_SYSPROTO_H_
684 struct setregid_args {
685 	gid_t	rgid;
686 	gid_t	egid;
687 };
688 #endif
689 /* ARGSUSED */
690 int
691 setregid(p, uap)
692 	register struct proc *p;
693 	struct setregid_args *uap;
694 {
695 	register struct pcred *pc = p->p_cred;
696 	register gid_t rgid, egid;
697 	int error;
698 
699 	rgid = uap->rgid;
700 	egid = uap->egid;
701 	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) ||
702 	     (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] &&
703 	     egid != pc->p_rgid && egid != pc->p_svgid)) &&
704 	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
705 		return (error);
706 
707 	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
708 		pc->pc_ucred = crcopy(pc->pc_ucred);
709 		pc->pc_ucred->cr_groups[0] = egid;
710 		setsugid(p);
711 	}
712 	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
713 		pc->p_rgid = rgid;
714 		setsugid(p);
715 	}
716 	if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) &&
717 	    pc->p_svgid != pc->pc_ucred->cr_groups[0]) {
718 		pc->p_svgid = pc->pc_ucred->cr_groups[0];
719 		setsugid(p);
720 	}
721 	return (0);
722 }
723 
724 /*
725  * setresuid(ruid, euid, suid) is like setreuid except control over the
726  * saved uid is explicit.
727  */
728 
729 #ifndef _SYS_SYSPROTO_H_
730 struct setresuid_args {
731 	uid_t	ruid;
732 	uid_t	euid;
733 	uid_t	suid;
734 };
735 #endif
736 /* ARGSUSED */
737 int
738 setresuid(p, uap)
739 	register struct proc *p;
740 	struct setresuid_args *uap;
741 {
742 	register struct pcred *pc = p->p_cred;
743 	register uid_t ruid, euid, suid;
744 	int error;
745 
746 	ruid = uap->ruid;
747 	euid = uap->euid;
748 	suid = uap->suid;
749 	if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid &&
750 	      ruid != pc->pc_ucred->cr_uid) ||
751 	     (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid &&
752 	      euid != pc->pc_ucred->cr_uid) ||
753 	     (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid &&
754 	      suid != pc->pc_ucred->cr_uid)) &&
755 	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
756 		return (error);
757 	if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) {
758 		change_euid(p, euid);
759 		setsugid(p);
760 	}
761 	if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
762 		change_ruid(p, ruid);
763 		setsugid(p);
764 	}
765 	if (suid != (uid_t)-1 && pc->p_svuid != suid) {
766 		pc->p_svuid = suid;
767 		setsugid(p);
768 	}
769 	return (0);
770 }
771 
772 /*
773  * setresgid(rgid, egid, sgid) is like setregid except control over the
774  * saved gid is explicit.
775  */
776 
777 #ifndef _SYS_SYSPROTO_H_
778 struct setresgid_args {
779 	gid_t	rgid;
780 	gid_t	egid;
781 	gid_t	sgid;
782 };
783 #endif
784 /* ARGSUSED */
785 int
786 setresgid(p, uap)
787 	register struct proc *p;
788 	struct setresgid_args *uap;
789 {
790 	register struct pcred *pc = p->p_cred;
791 	register gid_t rgid, egid, sgid;
792 	int error;
793 
794 	rgid = uap->rgid;
795 	egid = uap->egid;
796 	sgid = uap->sgid;
797 	if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid &&
798 	      rgid != pc->pc_ucred->cr_groups[0]) ||
799 	     (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid &&
800 	      egid != pc->pc_ucred->cr_groups[0]) ||
801 	     (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid &&
802 	      sgid != pc->pc_ucred->cr_groups[0])) &&
803 	    (error = suser_xxx(0, p, PRISON_ROOT)) != 0)
804 		return (error);
805 
806 	if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) {
807 		pc->pc_ucred = crcopy(pc->pc_ucred);
808 		pc->pc_ucred->cr_groups[0] = egid;
809 		setsugid(p);
810 	}
811 	if (rgid != (gid_t)-1 && pc->p_rgid != rgid) {
812 		pc->p_rgid = rgid;
813 		setsugid(p);
814 	}
815 	if (sgid != (gid_t)-1 && pc->p_svgid != sgid) {
816 		pc->p_svgid = sgid;
817 		setsugid(p);
818 	}
819 	return (0);
820 }
821 
822 #ifndef _SYS_SYSPROTO_H_
823 struct getresuid_args {
824 	uid_t	*ruid;
825 	uid_t	*euid;
826 	uid_t	*suid;
827 };
828 #endif
829 /* ARGSUSED */
830 int
831 getresuid(p, uap)
832 	register struct proc *p;
833 	struct getresuid_args *uap;
834 {
835 	struct pcred *pc = p->p_cred;
836 	int error1 = 0, error2 = 0, error3 = 0;
837 
838 	if (uap->ruid)
839 		error1 = copyout((caddr_t)&pc->p_ruid,
840 		    (caddr_t)uap->ruid, sizeof(pc->p_ruid));
841 	if (uap->euid)
842 		error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid,
843 		    (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid));
844 	if (uap->suid)
845 		error3 = copyout((caddr_t)&pc->p_svuid,
846 		    (caddr_t)uap->suid, sizeof(pc->p_svuid));
847 	return error1 ? error1 : (error2 ? error2 : error3);
848 }
849 
850 #ifndef _SYS_SYSPROTO_H_
851 struct getresgid_args {
852 	gid_t	*rgid;
853 	gid_t	*egid;
854 	gid_t	*sgid;
855 };
856 #endif
857 /* ARGSUSED */
858 int
859 getresgid(p, uap)
860 	register struct proc *p;
861 	struct getresgid_args *uap;
862 {
863 	struct pcred *pc = p->p_cred;
864 	int error1 = 0, error2 = 0, error3 = 0;
865 
866 	if (uap->rgid)
867 		error1 = copyout((caddr_t)&pc->p_rgid,
868 		    (caddr_t)uap->rgid, sizeof(pc->p_rgid));
869 	if (uap->egid)
870 		error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0],
871 		    (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0]));
872 	if (uap->sgid)
873 		error3 = copyout((caddr_t)&pc->p_svgid,
874 		    (caddr_t)uap->sgid, sizeof(pc->p_svgid));
875 	return error1 ? error1 : (error2 ? error2 : error3);
876 }
877 
878 
879 #ifndef _SYS_SYSPROTO_H_
880 struct issetugid_args {
881 	int dummy;
882 };
883 #endif
884 /* ARGSUSED */
885 int
886 issetugid(p, uap)
887 	register struct proc *p;
888 	struct issetugid_args *uap;
889 {
890 	/*
891 	 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
892 	 * we use P_SUGID because we consider changing the owners as
893 	 * "tainting" as well.
894 	 * This is significant for procs that start as root and "become"
895 	 * a user without an exec - programs cannot know *everything*
896 	 * that libc *might* have put in their data segment.
897 	 */
898 	p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
899 	return (0);
900 }
901 
902 /*
903  * Check if gid is a member of the group set.
904  */
905 int
906 groupmember(gid, cred)
907 	gid_t gid;
908 	register struct ucred *cred;
909 {
910 	register gid_t *gp;
911 	gid_t *egp;
912 
913 	egp = &(cred->cr_groups[cred->cr_ngroups]);
914 	for (gp = cred->cr_groups; gp < egp; gp++)
915 		if (*gp == gid)
916 			return (1);
917 	return (0);
918 }
919 
920 /*
921  * Test whether the specified credentials imply "super-user"
922  * privilege; if so, and we have accounting info, set the flag
923  * indicating use of super-powers.
924  * Returns 0 or error.
925  */
926 int
927 suser(p)
928 	struct proc *p;
929 {
930 	return suser_xxx(0, p, 0);
931 }
932 
933 int
934 suser_xxx(cred, proc, flag)
935 	struct ucred *cred;
936 	struct proc *proc;
937 	int flag;
938 {
939 	if (!cred && !proc) {
940 		printf("suser_xxx(): THINK!\n");
941 		return (EPERM);
942 	}
943 	if (!cred)
944 		cred = proc->p_ucred;
945 	if (cred->cr_uid != 0)
946 		return (EPERM);
947 	if (proc && proc->p_prison && !(flag & PRISON_ROOT))
948 		return (EPERM);
949 	if (proc)
950 		proc->p_acflag |= ASU;
951 	return (0);
952 }
953 
954 /*
955  * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise.
956  */
957 
958 int
959 p_trespass(struct proc *p1, struct proc *p2)
960 {
961 
962 	if (p1 == p2)
963 		return (0);
964 	if (!PRISON_CHECK(p1, p2))
965 		return (ESRCH);
966 	if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
967 		return (0);
968 	if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid)
969 		return (0);
970 	if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid)
971 		return (0);
972 	if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid)
973 		return (0);
974 	if (!suser_xxx(0, p1, PRISON_ROOT))
975 		return (0);
976 	return (EPERM);
977 }
978 
979 /*
980  * Allocate a zeroed cred structure.
981  */
982 struct ucred *
983 crget()
984 {
985 	register struct ucred *cr;
986 
987 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
988 	bzero((caddr_t)cr, sizeof(*cr));
989 	cr->cr_ref = 1;
990 	return (cr);
991 }
992 
993 /*
994  * Claim another reference to a ucred structure
995  */
996 void
997 crhold(cr)
998         struct ucred *cr;
999 {
1000 	cr->cr_ref++;
1001 }
1002 
1003 /*
1004  * Free a cred structure.
1005  * Throws away space when ref count gets to 0.
1006  */
1007 void
1008 crfree(cr)
1009 	struct ucred *cr;
1010 {
1011 	if (cr->cr_ref == 0)
1012 		panic("Freeing already free credential! %p", cr);
1013 
1014 	if (--cr->cr_ref == 0) {
1015 		/*
1016 		 * Some callers of crget(), such as nfs_statfs(),
1017 		 * allocate a temporary credential, but don't
1018 		 * allocate a uidinfo structure.
1019 		 */
1020 		if (cr->cr_uidinfo != NULL)
1021 			uifree(cr->cr_uidinfo);
1022 		FREE((caddr_t)cr, M_CRED);
1023 	}
1024 }
1025 
1026 /*
1027  * Copy cred structure to a new one and free the old one.
1028  */
1029 struct ucred *
1030 crcopy(cr)
1031 	struct ucred *cr;
1032 {
1033 	struct ucred *newcr;
1034 
1035 	if (cr->cr_ref == 1)
1036 		return (cr);
1037 	newcr = crget();
1038 	*newcr = *cr;
1039 	uihold(newcr->cr_uidinfo);
1040 	crfree(cr);
1041 	newcr->cr_ref = 1;
1042 	return (newcr);
1043 }
1044 
1045 /*
1046  * Dup cred struct to a new held one.
1047  */
1048 struct ucred *
1049 crdup(cr)
1050 	struct ucred *cr;
1051 {
1052 	struct ucred *newcr;
1053 
1054 	newcr = crget();
1055 	*newcr = *cr;
1056 	uihold(newcr->cr_uidinfo);
1057 	newcr->cr_ref = 1;
1058 	return (newcr);
1059 }
1060 
1061 /*
1062  * Fill in a struct xucred based on a struct ucred.
1063  */
1064 void
1065 cru2x(cr, xcr)
1066 	struct ucred *cr;
1067 	struct xucred *xcr;
1068 {
1069 
1070 	bzero(xcr, sizeof(*xcr));
1071 	xcr->cr_version = XUCRED_VERSION;
1072 	xcr->cr_uid = cr->cr_uid;
1073 	xcr->cr_ngroups = cr->cr_ngroups;
1074 	bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups));
1075 }
1076 
1077 /*
1078  * Get login name, if available.
1079  */
1080 #ifndef _SYS_SYSPROTO_H_
1081 struct getlogin_args {
1082 	char	*namebuf;
1083 	u_int	namelen;
1084 };
1085 #endif
1086 /* ARGSUSED */
1087 int
1088 getlogin(p, uap)
1089 	struct proc *p;
1090 	struct getlogin_args *uap;
1091 {
1092 
1093 	if (uap->namelen > MAXLOGNAME)
1094 		uap->namelen = MAXLOGNAME;
1095 	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
1096 	    (caddr_t) uap->namebuf, uap->namelen));
1097 }
1098 
1099 /*
1100  * Set login name.
1101  */
1102 #ifndef _SYS_SYSPROTO_H_
1103 struct setlogin_args {
1104 	char	*namebuf;
1105 };
1106 #endif
1107 /* ARGSUSED */
1108 int
1109 setlogin(p, uap)
1110 	struct proc *p;
1111 	struct setlogin_args *uap;
1112 {
1113 	int error;
1114 	char logintmp[MAXLOGNAME];
1115 
1116 	if ((error = suser_xxx(0, p, PRISON_ROOT)))
1117 		return (error);
1118 	error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
1119 	    sizeof(logintmp), (size_t *)0);
1120 	if (error == ENAMETOOLONG)
1121 		error = EINVAL;
1122 	else if (!error)
1123 		(void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
1124 		    sizeof(logintmp));
1125 	return (error);
1126 }
1127 
1128 void
1129 setsugid(p)
1130 	struct proc *p;
1131 {
1132 	p->p_flag |= P_SUGID;
1133 	if (!(p->p_pfsflags & PF_ISUGID))
1134 		p->p_stops = 0;
1135 }
1136 
1137 /*
1138  * Helper function to change the effective uid of a process
1139  */
1140 void
1141 change_euid(p, euid)
1142 	struct	proc *p;
1143 	uid_t	euid;
1144 {
1145 	struct	pcred *pc;
1146 	struct	uidinfo *uip;
1147 
1148 	pc = p->p_cred;
1149 	/*
1150 	 * crcopy is essentially a NOP if ucred has a reference count
1151 	 * of 1, which is true if it has already been copied.
1152 	 */
1153 	pc->pc_ucred = crcopy(pc->pc_ucred);
1154 	uip = pc->pc_ucred->cr_uidinfo;
1155 	pc->pc_ucred->cr_uid = euid;
1156 	pc->pc_ucred->cr_uidinfo = uifind(euid);
1157 	uifree(uip);
1158 }
1159 
1160 /*
1161  * Helper function to change the real uid of a process
1162  *
1163  * The per-uid process count for this process is transfered from
1164  * the old uid to the new uid.
1165  */
1166 void
1167 change_ruid(p, ruid)
1168 	struct	proc *p;
1169 	uid_t	ruid;
1170 {
1171 	struct	pcred *pc;
1172 	struct	uidinfo *uip;
1173 
1174 	pc = p->p_cred;
1175 	(void)chgproccnt(pc->p_uidinfo, -1, 0);
1176 	uip = pc->p_uidinfo;
1177 	/* It is assumed that pcred is not shared between processes */
1178 	pc->p_ruid = ruid;
1179 	pc->p_uidinfo = uifind(ruid);
1180 	(void)chgproccnt(pc->p_uidinfo, 1, 0);
1181 	uifree(uip);
1182 }
1183