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