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