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