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