Merge from vendor branch LIBARCHIVE:
[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/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 }