from shannon
[unix-history] / usr / src / sys / kern / kern_prot.c
index 018aaaa..1df99f2 100644 (file)
@@ -1,18 +1,17 @@
-/*     kern_prot.c     5.1     82/07/15        */
+/*     kern_prot.c     5.15    83/02/20        */
 
 /*
 
 /*
- * System calls related to protection
+ * System calls related to processes and protection
  */
 
  */
 
+#include "../machine/reg.h"
+
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/dir.h"
 #include "../h/user.h"
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/dir.h"
 #include "../h/user.h"
-#include "../h/reg.h"
 #include "../h/inode.h"
 #include "../h/proc.h"
 #include "../h/inode.h"
 #include "../h/proc.h"
-#include "../h/clock.h"
-#include "../h/mtpr.h"
 #include "../h/timeb.h"
 #include "../h/times.h"
 #include "../h/reboot.h"
 #include "../h/timeb.h"
 #include "../h/times.h"
 #include "../h/reboot.h"
 #include "../h/conf.h"
 #include "../h/buf.h"
 #include "../h/mount.h"
 #include "../h/conf.h"
 #include "../h/buf.h"
 #include "../h/mount.h"
+#include "../h/quota.h"
+
+getpid()
+{
+
+       u.u_r.r_val1 = u.u_procp->p_pid;
+       u.u_r.r_val2 = u.u_procp->p_ppid;
+}
+
+getpgrp()
+{
+       register struct a {
+               int     pid;
+       } *uap = (struct a *)u.u_ap;
+       register struct proc *p;
+
+       if (uap->pid == 0)
+               uap->pid = u.u_procp->p_pid;
+       p = pfind(uap->pid);
+       if (p == 0) {
+               u.u_error = ESRCH;
+               return;
+       }
+       u.u_r.r_val1 = p->p_pgrp;
+}
 
 getuid()
 {
 
 getuid()
 {
@@ -28,7 +52,94 @@ getuid()
        u.u_r.r_val2 = u.u_uid;
 }
 
        u.u_r.r_val2 = u.u_uid;
 }
 
-setuid()
+getgid()
+{
+
+       u.u_r.r_val1 = u.u_rgid;
+       u.u_r.r_val2 = u.u_gid;
+}
+
+getgroups()
+{
+       register struct a {
+               u_int   gidsetsize;
+               int     *gidset;
+       } *uap = (struct a *)u.u_ap;
+       register int *gp;
+
+       for (gp = &u.u_groups[NGROUPS]; gp > u.u_groups; gp--)
+               if (gp[-1] >= 0)
+                       break;
+       if (uap->gidsetsize < gp - u.u_groups) {
+               u.u_error = EINVAL;
+               return;
+       }
+       uap->gidsetsize = gp - u.u_groups;
+       u.u_error = copyout((caddr_t)u.u_groups, (caddr_t)uap->gidset,
+           uap->gidsetsize * sizeof (u.u_groups[0]));
+       if (u.u_error)
+               return;
+       u.u_r.r_val1 = uap->gidsetsize;
+}
+
+setpgrp()
+{
+       register struct proc *p;
+       register struct a {
+               int     pid;
+               int     pgrp;
+       } *uap = (struct a *)u.u_ap;
+
+       if (uap->pid == 0)
+               uap->pid = u.u_procp->p_pid;
+       p = pfind(uap->pid);
+       if (p == 0) {
+               u.u_error = ESRCH;
+               return;
+       }
+/* need better control mechanisms for process groups */
+       if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) {
+               u.u_error = EPERM;
+               return;
+       }
+       p->p_pgrp = uap->pgrp;
+}
+
+setreuid()
+{
+       struct a {
+               int     ruid;
+               int     euid;
+       } *uap;
+       register int ruid, euid;
+
+       uap = (struct a *)u.u_ap;
+       ruid = uap->ruid;
+       if (ruid == -1)
+               ruid = u.u_ruid;
+       if (u.u_ruid != ruid && u.u_uid != ruid && !suser())
+               return;
+       euid = uap->euid;
+       if (euid == -1)
+               euid = u.u_uid;
+       if (u.u_ruid != euid && u.u_uid != euid && !suser())
+               return;
+       /*
+        * Everything's okay, do it.
+        */
+#ifdef QUOTA
+       if (u.u_quota->q_uid != ruid) {
+               qclean();
+               qstart(getquota(ruid, 0, 0));
+       }
+#endif
+       u.u_procp->p_uid = ruid;
+       u.u_ruid = ruid;
+       u.u_uid = euid;
+}
+
+#ifndef NOCOMPAT
+osetuid()
 {
        register uid;
        register struct a {
 {
        register uid;
        register struct a {
@@ -38,20 +149,48 @@ setuid()
        uap = (struct a *)u.u_ap;
        uid = uap->uid;
        if (u.u_ruid == uid || u.u_uid == uid || suser()) {
        uap = (struct a *)u.u_ap;
        uid = uap->uid;
        if (u.u_ruid == uid || u.u_uid == uid || suser()) {
+#ifdef QUOTA
+               if (u.u_quota->q_uid != uid) {
+                       qclean();
+                       qstart(getquota(uid, 0, 0));
+               }
+#endif
                u.u_uid = uid;
                u.u_procp->p_uid = uid;
                u.u_ruid = uid;
        }
 }
                u.u_uid = uid;
                u.u_procp->p_uid = uid;
                u.u_ruid = uid;
        }
 }
+#endif
 
 
-getgid()
+setregid()
 {
 {
+       register struct a {
+               int     rgid;
+               int     egid;
+       } *uap;
+       register int rgid, egid;
 
 
-       u.u_r.r_val1 = u.u_rgid;
-       u.u_r.r_val2 = u.u_gid;
+       uap = (struct a *)u.u_ap;
+       rgid = uap->rgid;
+       if (rgid == -1)
+               rgid = u.u_rgid;
+       if (u.u_rgid != rgid && u.u_gid != rgid && !suser())
+               return;
+       egid = uap->egid;
+       if (egid == -1)
+               egid = u.u_gid;
+       if (u.u_rgid != egid && u.u_gid != egid && !suser())
+               return;
+       if (u.u_rgid != rgid) {
+               leavegroup(u.u_rgid);
+               (void) entergroup(rgid);
+               u.u_rgid = rgid;
+       }
+       u.u_gid = egid;
 }
 
 }
 
-setgid()
+#ifndef NOCOMPAT
+osetgid()
 {
        register gid;
        register struct a {
 {
        register gid;
        register struct a {
@@ -61,7 +200,97 @@ setgid()
        uap = (struct a *)u.u_ap;
        gid = uap->gid;
        if (u.u_rgid == gid || u.u_gid == gid || suser()) {
        uap = (struct a *)u.u_ap;
        gid = uap->gid;
        if (u.u_rgid == gid || u.u_gid == gid || suser()) {
+               leavegroup(u.u_rgid);
+               (void) entergroup(gid);
                u.u_gid = gid;
                u.u_rgid = gid;
        }
 }
                u.u_gid = gid;
                u.u_rgid = gid;
        }
 }
+
+setgroups()
+{
+       register struct a {
+               u_int   gidsetsize;
+               int     *gidset;
+       } *uap = (struct a *)u.u_ap;
+       register int *gp;
+
+       if (!suser())
+               return;
+       if (uap->gidsetsize > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
+               u.u_error = EINVAL;
+               return;
+       }
+       u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)u.u_groups,
+           uap->gidsetsize * sizeof (u.u_groups[0]));
+       if (u.u_error)
+               return;
+       for (gp = &u.u_groups[uap->gidsetsize]; gp < &u.u_groups[NGROUPS]; gp++)
+               *gp = -1;
+}
+
+/*
+ * Pid of zero implies current process.
+ * Pgrp -1 is getpgrp system call returning
+ * current process group.
+ */
+osetpgrp()
+{
+       register struct proc *p;
+       register struct a {
+               int     pid;
+               int     pgrp;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       if (uap->pid == 0)
+               p = u.u_procp;
+       else {
+               p = pfind(uap->pid);
+               if (p == 0) {
+                       u.u_error = ESRCH;
+                       return;
+               }
+       }
+       if (uap->pgrp <= 0) {
+               u.u_r.r_val1 = p->p_pgrp;
+               return;
+       }
+       if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) {
+               u.u_error = EPERM;
+               return;
+       }
+       p->p_pgrp = uap->pgrp;
+}
+/* END DEFUNCT */
+
+leavegroup(gid)
+       int gid;
+{
+       register int *gp;
+
+       for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
+               if (*gp == gid)
+                       goto found;
+       return;
+found:
+       for (; gp < &u.u_groups[NGROUPS-1]; gp++)
+               *gp = *(gp+1);
+       *gp = -1;
+}
+
+entergroup(gid)
+       int gid;
+{
+       register int *gp;
+
+       for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
+               if (*gp == gid)
+                       return (0);
+       for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
+               if (*gp < 0) {
+                       *gp = gid;
+                       return (0);
+               }
+       return (-1);
+}