Implement 4.4's SUGID flag, which keeps track of processes which
[unix-history] / sys / kern / kern_prot.c
index d660280..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: kern_prot.c,v 1.3 1993/10/16 15:24:24 rgrimes Exp $
+ *     $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"
@@ -273,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);
 }
 
@@ -301,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);
 }
 
@@ -325,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);
 }
 
@@ -350,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);
 }
 
@@ -368,38 +372,30 @@ osetreuid(p, uap, retval)
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
        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 {
@@ -415,35 +411,22 @@ osetregid(p, uap, retval)
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
        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