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