Implement 4.4's SUGID flag, which keeps track of processes which
[unix-history] / sys / kern / kern_prot.c
index 867ff51..e2ba54a 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)kern_prot.c   7.21 (Berkeley) 5/3/91
  * SUCH DAMAGE.
  *
  *     from: @(#)kern_prot.c   7.21 (Berkeley) 5/3/91
- *     $Id$
+ *     $Id: kern_prot.c,v 1.5 1993/12/19 00:51:29 wollman Exp $
  */
 
 /*
  */
 
 /*
@@ -39,8 +39,8 @@
  */
 
 #include "param.h"
  */
 
 #include "param.h"
-#include "acct.h"
 #include "systm.h"
 #include "systm.h"
+#include "acct.h"
 #include "ucred.h"
 #include "proc.h"
 #include "timeb.h"
 #include "ucred.h"
 #include "proc.h"
 #include "timeb.h"
@@ -48,6 +48,7 @@
 #include "malloc.h"
 
 /* ARGSUSED */
 #include "malloc.h"
 
 /* ARGSUSED */
+int
 getpid(p, uap, retval)
        struct proc *p;
        void *uap;
 getpid(p, uap, retval)
        struct proc *p;
        void *uap;
@@ -62,6 +63,7 @@ getpid(p, uap, retval)
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
+int
 getppid(p, uap, retval)
        struct proc *p;
        void *uap;
 getppid(p, uap, retval)
        struct proc *p;
        void *uap;
@@ -73,6 +75,7 @@ getppid(p, uap, retval)
 }
 
 /* Get process group ID; note that POSIX getpgrp takes no parameter */
 }
 
 /* Get process group ID; note that POSIX getpgrp takes no parameter */
+int
 getpgrp(p, uap, retval)
        struct proc *p;
        void *uap;
 getpgrp(p, uap, retval)
        struct proc *p;
        void *uap;
@@ -84,6 +87,7 @@ getpgrp(p, uap, retval)
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
+int
 getuid(p, uap, retval)
        struct proc *p;
        void *uap;
 getuid(p, uap, retval)
        struct proc *p;
        void *uap;
@@ -98,6 +102,7 @@ getuid(p, uap, retval)
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
+int
 geteuid(p, uap, retval)
        struct proc *p;
        void *uap;
 geteuid(p, uap, retval)
        struct proc *p;
        void *uap;
@@ -109,6 +114,7 @@ geteuid(p, uap, retval)
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
+int
 getgid(p, uap, retval)
        struct proc *p;
        void *uap;
 getgid(p, uap, retval)
        struct proc *p;
        void *uap;
@@ -128,6 +134,7 @@ getgid(p, uap, retval)
  * correctly in a library function.
  */
 /* ARGSUSED */
  * correctly in a library function.
  */
 /* ARGSUSED */
+int
 getegid(p, uap, retval)
        struct proc *p;
        void *uap;
 getegid(p, uap, retval)
        struct proc *p;
        void *uap;
@@ -143,6 +150,7 @@ struct getgroups_args {
        int     *gidset;                /* XXX not yet POSIX */
 };
 
        int     *gidset;                /* XXX not yet POSIX */
 };
 
+int
 getgroups(p, uap, retval)
        struct proc *p;
        register struct getgroups_args *uap;
 getgroups(p, uap, retval)
        struct proc *p;
        register struct getgroups_args *uap;
@@ -172,6 +180,7 @@ getgroups(p, uap, retval)
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
+int
 setsid(p, uap, retval)
        register struct proc *p;
        void *uap;
 setsid(p, uap, retval)
        register struct proc *p;
        void *uap;
@@ -207,6 +216,7 @@ struct setpgid_args {
 };
 
 /* ARGSUSED */
 };
 
 /* ARGSUSED */
+int
 setpgid(curp, uap, retval)
        struct proc *curp;
        register struct setpgid_args *uap;
 setpgid(curp, uap, retval)
        struct proc *curp;
        register struct setpgid_args *uap;
@@ -241,6 +251,7 @@ struct setuid_args {
 };
 
 /* ARGSUSED */
 };
 
 /* ARGSUSED */
+int
 setuid(p, uap, retval)
        struct proc *p;
        struct setuid_args *uap;
 setuid(p, uap, retval)
        struct proc *p;
        struct setuid_args *uap;
@@ -262,6 +273,7 @@ setuid(p, uap, retval)
        pc->pc_ucred->cr_uid = uid;
        pc->p_ruid = uid;
        pc->p_svuid = uid;
        pc->pc_ucred->cr_uid = uid;
        pc->p_ruid = uid;
        pc->p_svuid = uid;
+       p->p_flag |= SUGID;
        return (0);
 }
 
        return (0);
 }
 
@@ -270,6 +282,7 @@ struct seteuid_args {
 };
 
 /* ARGSUSED */
 };
 
 /* ARGSUSED */
+int
 seteuid(p, uap, retval)
        struct proc *p;
        struct seteuid_args *uap;
 seteuid(p, uap, retval)
        struct proc *p;
        struct seteuid_args *uap;
@@ -289,6 +302,7 @@ seteuid(p, uap, retval)
         */
        pc->pc_ucred = crcopy(pc->pc_ucred);
        pc->pc_ucred->cr_uid = euid;
         */
        pc->pc_ucred = crcopy(pc->pc_ucred);
        pc->pc_ucred->cr_uid = euid;
+       p->p_flag |= SUGID;
        return (0);
 }
 
        return (0);
 }
 
@@ -297,6 +311,7 @@ struct setgid_args {
 };
 
 /* ARGSUSED */
 };
 
 /* ARGSUSED */
+int
 setgid(p, uap, retval)
        struct proc *p;
        struct setgid_args *uap;
 setgid(p, uap, retval)
        struct proc *p;
        struct setgid_args *uap;
@@ -312,7 +327,8 @@ setgid(p, uap, retval)
        pc->pc_ucred = crcopy(pc->pc_ucred);
        pc->pc_ucred->cr_groups[0] = gid;
        pc->p_rgid = gid;
        pc->pc_ucred = crcopy(pc->pc_ucred);
        pc->pc_ucred->cr_groups[0] = gid;
        pc->p_rgid = gid;
-       pc->p_svgid = gid;              /* ??? */
+       pc->p_svgid = gid;
+       p->p_flag |= SUGID;
        return (0);
 }
 
        return (0);
 }
 
@@ -321,6 +337,7 @@ struct setegid_args {
 };
 
 /* ARGSUSED */
 };
 
 /* ARGSUSED */
+int
 setegid(p, uap, retval)
        struct proc *p;
        struct setegid_args *uap;
 setegid(p, uap, retval)
        struct proc *p;
        struct setegid_args *uap;
@@ -336,6 +353,7 @@ setegid(p, uap, retval)
                return (error);
        pc->pc_ucred = crcopy(pc->pc_ucred);
        pc->pc_ucred->cr_groups[0] = egid;
                return (error);
        pc->pc_ucred = crcopy(pc->pc_ucred);
        pc->pc_ucred->cr_groups[0] = egid;
+       p->p_flag |= SUGID;
        return (0);
 }
 
        return (0);
 }
 
@@ -347,44 +365,37 @@ struct osetreuid_args {
 };
 
 /* ARGSUSED */
 };
 
 /* ARGSUSED */
+int
 osetreuid(p, uap, retval)
        register struct proc *p;
        struct osetreuid_args *uap;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
 osetreuid(p, uap, retval)
        register struct proc *p;
        struct osetreuid_args *uap;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
-       register uid_t ruid, euid;
-       int error;
+       struct seteuid_args e_args;
 
 
-       if (uap->ruid == -1)
-               ruid = pc->p_ruid;
-       else
-               ruid = uap->ruid;
        /*
        /*
-        * Allow setting real uid to previous effective, for swapping real and
-        * effective.  This should be:
-        *
-        * if (ruid != pc->p_ruid &&
-        *     (error = suser(pc->pc_ucred, &p->p_acflag)))
+        * Most calls to setreuid() are done in order to swap real and
+        * effective uids.  In old versions of BSD, this was the only
+        * way to temporarily renounce privileges and be able to get
+        * them back.  In the presence of the POSIX saved id, however,
+        * we can do this without modifying the real uid, which could have
+        * opened up a security hole.  So, we implement this: when the user
+        * attempts to set its real uid, we just check to make sure
+        * that they will be able to seteuid() back to that id at some
+        * later time, but don't actually change the real uid.
+        * Logic taken from 4.4BSD.
         */
         */
-       if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
-           (error = suser(pc->pc_ucred, &p->p_acflag)))
-               return (error);
-       if (uap->euid == -1)
-               euid = pc->pc_ucred->cr_uid;
-       else
-               euid = uap->euid;
-       if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
-           euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag)))
-               return (error);
-       /*
-        * Everything's okay, do it.  Copy credentials so other references do
-        * not see our changes.
-        */
-       pc->pc_ucred = crcopy(pc->pc_ucred);
-       pc->pc_ucred->cr_uid = euid;
-       pc->p_ruid = ruid;
-       return (0);
+       if(uap->ruid != -1 && uap->ruid != pc->p_ruid
+          && uap->ruid != pc->p_svuid) {
+               return EPERM;
+       }
+
+       if(uap->euid == -1) {
+               return 0;
+       }
+       e_args.euid = uap->euid;
+       return seteuid(p, &e_args, retval);
 }
 
 struct osetregid_args {
 }
 
 struct osetregid_args {
@@ -393,41 +404,29 @@ struct osetregid_args {
 };
 
 /* ARGSUSED */
 };
 
 /* ARGSUSED */
+int
 osetregid(p, uap, retval)
        register struct proc *p;
        struct osetregid_args *uap;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
 osetregid(p, uap, retval)
        register struct proc *p;
        struct osetregid_args *uap;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
-       register gid_t rgid, egid;
-       int error;
+       struct setegid_args e_args;
 
 
-       if (uap->rgid == -1)
-               rgid = pc->p_rgid;
-       else
-               rgid = uap->rgid;
        /*
        /*
-        * Allow setting real gid to previous effective, for swapping real and
-        * effective.  This didn't really work correctly in 4.[23], but is
-        * preserved so old stuff doesn't fail.  This should be:
-        *
-        * if (rgid != pc->p_rgid &&
-        *     (error = suser(pc->pc_ucred, &p->p_acflag)))
+        * Same comments as for setreuid() apply here.
         */
         */
-       if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ &&
-           (error = suser(pc->pc_ucred, &p->p_acflag)))
-               return (error);
-       if (uap->egid == -1)
-               egid = pc->pc_ucred->cr_groups[0];
-       else
-               egid = uap->egid;
-       if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid &&
-           egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
-               return (error);
-       pc->pc_ucred = crcopy(pc->pc_ucred);
-       pc->pc_ucred->cr_groups[0] = egid;
-       pc->p_rgid = rgid;
-       return (0);
+       if(uap->rgid != -1
+          && uap->rgid != pc->p_rgid
+          && uap->rgid != pc->p_svgid) {
+               return EPERM;
+       }
+
+       if(uap->egid == -1) {
+               return 0;
+       }
+       e_args.egid = uap->egid;
+       return setegid(p, &e_args, retval);
 }
 #endif
 
 }
 #endif
 
@@ -437,6 +436,7 @@ struct setgroups_args {
 };
 
 /* ARGSUSED */
 };
 
 /* ARGSUSED */
+int
 setgroups(p, uap, retval)
        struct proc *p;
        struct setgroups_args *uap;
 setgroups(p, uap, retval)
        struct proc *p;
        struct setgroups_args *uap;
@@ -466,6 +466,7 @@ setgroups(p, uap, retval)
 /*
  * Check if gid is a member of the group set.
  */
 /*
  * Check if gid is a member of the group set.
  */
+int
 groupmember(gid, cred)
        gid_t gid;
        register struct ucred *cred;
 groupmember(gid, cred)
        gid_t gid;
        register struct ucred *cred;
@@ -486,6 +487,7 @@ groupmember(gid, cred)
  * indicating use of super-powers.
  * Returns 0 or error.
  */
  * indicating use of super-powers.
  * Returns 0 or error.
  */
+int
 suser(cred, acflag)
        struct ucred *cred;
        u_short *acflag;
 suser(cred, acflag)
        struct ucred *cred;
        u_short *acflag;
@@ -516,10 +518,11 @@ crget()
  * Free a cred structure.
  * Throws away space when ref count gets to 0.
  */
  * Free a cred structure.
  * Throws away space when ref count gets to 0.
  */
+void
 crfree(cr)
        struct ucred *cr;
 {
 crfree(cr)
        struct ucred *cr;
 {
-       int s = splimp();                       /* ??? */
+       int s = splimp();                       /* ??? XXX FIXME */
 
        if (--cr->cr_ref != 0) {
                (void) splx(s);
 
        if (--cr->cr_ref != 0) {
                (void) splx(s);
@@ -572,6 +575,7 @@ struct getlogin_args {
 };
 
 /* ARGSUSED */
 };
 
 /* ARGSUSED */
+int
 getlogin(p, uap, retval)
        struct proc *p;
        struct getlogin_args *uap;
 getlogin(p, uap, retval)
        struct proc *p;
        struct getlogin_args *uap;
@@ -593,6 +597,7 @@ struct setlogin_args {
 };
 
 /* ARGSUSED */
 };
 
 /* ARGSUSED */
+int
 setlogin(p, uap, retval)
        struct proc *p;
        struct setlogin_args *uap;
 setlogin(p, uap, retval)
        struct proc *p;
        struct setlogin_args *uap;