merge in vnode changes
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Tue, 2 May 1989 13:27:34 +0000 (05:27 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Tue, 2 May 1989 13:27:34 +0000 (05:27 -0800)
SCCS-vsn: sys/kern/kern_prot.c 7.1.1.1

usr/src/sys/kern/kern_prot.c

index 91a9782..e17d510 100644 (file)
@@ -1,9 +1,20 @@
 /*
 /*
- * Copyright (c) 1982, 1986 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
  *
  *
- *     @(#)kern_prot.c 7.5 (Berkeley) %G%
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     @(#)kern_prot.c 7.1.1.1 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
  */
 
 #include "param.h"
  */
 
 #include "param.h"
+#include "acct.h"
 #include "systm.h"
 #include "systm.h"
-#include "dir.h"
 #include "user.h"
 #include "user.h"
-#include "inode.h"
 #include "proc.h"
 #include "timeb.h"
 #include "times.h"
 #include "reboot.h"
 #include "proc.h"
 #include "timeb.h"
 #include "times.h"
 #include "reboot.h"
-#include "fs.h"
-#include "buf.h"
 #include "mount.h"
 #include "mount.h"
-#include "quota.h"
+#include "buf.h"
+#include "../ufs/quota.h"
+#include "malloc.h"
+#define GRPSTART 0
 
 #include "machine/reg.h"
 
 
 #include "machine/reg.h"
 
@@ -73,15 +84,17 @@ getgroups()
        register int *lp;
        int groups[NGROUPS];
 
        register int *lp;
        int groups[NGROUPS];
 
-       for (gp = &u.u_groups[NGROUPS]; gp > u.u_groups; gp--)
-               if (gp[-1] != NOGROUP)
-                       break;
-       if (uap->gidsetsize < gp - u.u_groups) {
+       if (uap->gidsetsize == 0) {
+               u.u_r.r_val1 = u.u_ngroups - GRPSTART;
+               return;
+       }
+       if (uap->gidsetsize < u.u_ngroups - GRPSTART) {
                u.u_error = EINVAL;
                return;
        }
                u.u_error = EINVAL;
                return;
        }
-       uap->gidsetsize = gp - u.u_groups;
-       for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; )
+       uap->gidsetsize = u.u_ngroups - GRPSTART;
+       gp = &u.u_groups[GRPSTART];
+       for (lp = groups; lp < &groups[uap->gidsetsize]; )
                *lp++ = *gp++;
        u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
            uap->gidsetsize * sizeof (groups[0]));
                *lp++ = *gp++;
        u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
            uap->gidsetsize * sizeof (groups[0]));
@@ -180,6 +193,8 @@ setreuid()
                return;
        /*
         * Everything's okay, do it.
                return;
        /*
         * Everything's okay, do it.
+        * Copy credentials so other references do not
+        * see our changes.
         */
 #ifdef QUOTA
        if (u.u_quota->q_uid != ruid) {
         */
 #ifdef QUOTA
        if (u.u_quota->q_uid != ruid) {
@@ -187,6 +202,8 @@ setreuid()
                qstart(getquota((uid_t)ruid, 0, 0));
        }
 #endif
                qstart(getquota((uid_t)ruid, 0, 0));
        }
 #endif
+       if (u.u_cred->cr_ref > 1)
+               u.u_cred = crcopy(u.u_cred);
        u.u_procp->p_uid = euid;
        u.u_ruid = ruid;
        u.u_uid = euid;
        u.u_procp->p_uid = euid;
        u.u_ruid = ruid;
        u.u_uid = euid;
@@ -213,11 +230,9 @@ setregid()
        if (u.u_rgid != egid && u.u_gid != egid &&
            (u.u_error = suser(u.u_cred, &u.u_acflag)))
                return;
        if (u.u_rgid != egid && u.u_gid != egid &&
            (u.u_error = suser(u.u_cred, &u.u_acflag)))
                return;
-       if (u.u_rgid != rgid) {
-               leavegroup(u.u_rgid);
-               (void) entergroup((gid_t)rgid);
-               u.u_rgid = rgid;
-       }
+       if (u.u_cred->cr_ref > 1)
+               u.u_cred = crcopy(u.u_cred);
+       u.u_rgid = rgid;
        u.u_gid = egid;
 }
 
        u.u_gid = egid;
 }
 
@@ -229,11 +244,12 @@ setgroups()
        } *uap = (struct a *)u.u_ap;
        register gid_t *gp;
        register int *lp;
        } *uap = (struct a *)u.u_ap;
        register gid_t *gp;
        register int *lp;
-       int groups[NGROUPS];
+       int ngrp, groups[NGROUPS];
 
        if (u.u_error = suser(u.u_cred, &u.u_acflag))
                return;
 
        if (u.u_error = suser(u.u_cred, &u.u_acflag))
                return;
-       if (uap->gidsetsize > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
+       ngrp = uap->gidsetsize + GRPSTART;
+       if (ngrp > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
                u.u_error = EINVAL;
                return;
        }
                u.u_error = EINVAL;
                return;
        }
@@ -241,67 +257,105 @@ setgroups()
            uap->gidsetsize * sizeof (groups[0]));
        if (u.u_error)
                return;
            uap->gidsetsize * sizeof (groups[0]));
        if (u.u_error)
                return;
-       for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; )
+       gp = &u.u_groups[GRPSTART];
+       for (lp = groups; lp < &groups[uap->gidsetsize]; )
                *gp++ = *lp++;
                *gp++ = *lp++;
-       for ( ; gp < &u.u_groups[NGROUPS]; gp++)
-               *gp = NOGROUP;
+       u.u_ngroups = ngrp;
 }
 
 /*
 }
 
 /*
- * Group utility functions.
- */
-
-/*
- * Delete gid from the group set.
+ * Check if gid is a member of the group set.
  */
  */
-leavegroup(gid)
+groupmember(gid, cred)
        gid_t gid;
        gid_t gid;
+       register struct ucred *cred;
 {
        register gid_t *gp;
 {
        register gid_t *gp;
+       gid_t *egp;
 
 
-       for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
+       egp = &(cred->cr_groups[cred->cr_ngroups]);
+       for (gp = cred->cr_groups; gp < egp; gp++)
                if (*gp == gid)
                if (*gp == gid)
-                       goto found;
-       return;
-found:
-       for (; gp < &u.u_groups[NGROUPS-1]; gp++)
-               *gp = *(gp+1);
-       *gp = NOGROUP;
+                       return (1);
+       return (0);
 }
 
 /*
 }
 
 /*
- * Add gid to the group set.
+ * Test if the current user is the super user.
  */
  */
-entergroup(gid)
-       gid_t gid;
+suser(cred, acflag)
+       struct ucred *cred;
+       short *acflag;
 {
 {
-       register gid_t *gp;
 
 
-       for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) {
-               if (*gp == gid)
-                       return (0);
-               if (*gp == NOGROUP) {
-                       *gp = gid;
-                       return (0);
-               }
+       if (cred->cr_uid == 0) {
+               if (acflag)
+                       *acflag |= ASU;
+               return (0);
        }
        }
-       return (-1);
+       return (EPERM);
 }
 
 /*
 }
 
 /*
- * Check if gid is a member of the group set.
+ * Allocate a zeroed cred structure.
  */
  */
-groupmember(gid)
-       gid_t gid;
+struct ucred *
+crget()
 {
 {
-       register gid_t *gp;
+       register struct ucred *cr;
 
 
-       if (u.u_gid == gid)
-               return (1);
-       for (gp = u.u_groups; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++)
-               if (*gp == gid)
-                       return (1);
-       return (0);
+       MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
+       bzero((caddr_t)cr, sizeof(*cr));
+       cr->cr_ref = 1;
+       return(cr);
+}
+
+/*
+ * Free a cred structure.
+ * Throws away space when ref count gets to 0.
+ */
+crfree(cr)
+       struct ucred *cr;
+{
+       int     s = splimp();
+
+       if (--cr->cr_ref != 0) {
+               (void) splx(s);
+               return;
+       }
+       FREE((caddr_t)cr, M_CRED);
+       (void) splx(s);
+}
+
+/*
+ * Copy cred structure to a new one and free the old one.
+ */
+struct ucred *
+crcopy(cr)
+       struct ucred *cr;
+{
+       struct ucred *newcr;
+
+       newcr = crget();
+       *newcr = *cr;
+       crfree(cr);
+       newcr->cr_ref = 1;
+       return(newcr);
+}
+
+/*
+ * Dup cred struct to a new held one.
+ */
+struct ucred *
+crdup(cr)
+       struct ucred *cr;
+{
+       struct ucred *newcr;
+
+       newcr = crget();
+       *newcr = *cr;
+       newcr->cr_ref = 1;
+       return(newcr);
 }
 
 /*
 }
 
 /*