add USL's copyright notice
[unix-history] / usr / src / sys / kern / kern_prot.c
index ef71ba5..668bd82 100644 (file)
@@ -1,24 +1,29 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University
- * of California.  All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
+ *     Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)kern_prot.c 7.25 (Berkeley) %G%
+ *     @(#)kern_prot.c 8.5 (Berkeley) %G%
  */
 
 /*
  * System calls related to processes and protection
  */
 
  */
 
 /*
  * System calls related to processes and protection
  */
 
-#include "param.h"
-#include "acct.h"
-#include "systm.h"
-#include "ucred.h"
-#include "proc.h"
-#include "timeb.h"
-#include "times.h"
-#include "malloc.h"
+#include <sys/param.h>
+#include <sys/acct.h>
+#include <sys/systm.h>
+#include <sys/ucred.h>
+#include <sys/proc.h>
+#include <sys/timeb.h>
+#include <sys/times.h>
+#include <sys/malloc.h>
 
 struct args {
        int     dummy;
 
 struct args {
        int     dummy;
@@ -117,7 +122,7 @@ getegid(p, uap, retval)
 
 struct getgroups_args {
        u_int   gidsetsize;
 
 struct getgroups_args {
        u_int   gidsetsize;
-       int     *gidset;                /* XXX not yet POSIX */
+       gid_t   *gidset;
 };
 getgroups(p, uap, retval)
        struct proc *p;
 };
 getgroups(p, uap, retval)
        struct proc *p;
@@ -125,10 +130,7 @@ getgroups(p, uap, retval)
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
-       register gid_t *gp;
-       register int *lp;
        register u_int ngrp;
        register u_int ngrp;
-       int groups[NGROUPS];
        int error;
 
        if ((ngrp = uap->gidsetsize) == 0) {
        int error;
 
        if ((ngrp = uap->gidsetsize) == 0) {
@@ -138,10 +140,8 @@ getgroups(p, uap, retval)
        if (ngrp < pc->pc_ucred->cr_ngroups)
                return (EINVAL);
        ngrp = pc->pc_ucred->cr_ngroups;
        if (ngrp < pc->pc_ucred->cr_ngroups)
                return (EINVAL);
        ngrp = pc->pc_ucred->cr_ngroups;
-       for (gp = pc->pc_ucred->cr_groups, lp = groups; lp < &groups[ngrp]; )
-               *lp++ = *gp++;
-       if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
-           ngrp * sizeof (groups[0])))
+       if (error = copyout((caddr_t)pc->pc_ucred->cr_groups,
+           (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))
                return (error);
        *retval = ngrp;
        return (0);
                return (error);
        *retval = ngrp;
        return (0);
@@ -157,7 +157,7 @@ setsid(p, uap, retval)
        if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
                return (EPERM);
        } else {
        if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
                return (EPERM);
        } else {
-               enterpgrp(p, p->p_pid, 1);
+               (void)enterpgrp(p, p->p_pid, 1);
                *retval = p->p_pid;
                return (0);
        }
                *retval = p->p_pid;
                return (0);
        }
@@ -194,7 +194,7 @@ setpgid(curp, uap, retval)
                        return (ESRCH);
                if (targp->p_session != curp->p_session)
                        return (EPERM);
                        return (ESRCH);
                if (targp->p_session != curp->p_session)
                        return (EPERM);
-               if (targp->p_flag&SEXEC)
+               if (targp->p_flag & P_EXEC)
                        return (EACCES);
        } else
                targp = curp;
                        return (EACCES);
        } else
                targp = curp;
@@ -206,12 +206,11 @@ setpgid(curp, uap, retval)
                if ((pgrp = pgfind(uap->pgid)) == 0 ||
                    pgrp->pg_session != curp->p_session)
                        return (EPERM);
                if ((pgrp = pgfind(uap->pgid)) == 0 ||
                    pgrp->pg_session != curp->p_session)
                        return (EPERM);
-       enterpgrp(targp, uap->pgid, 0);
-       return (0);
+       return (enterpgrp(targp, uap->pgid, 0));
 }
 
 struct setuid_args {
 }
 
 struct setuid_args {
-       int     uid;
+       uid_t   uid;
 };
 /* ARGSUSED */
 setuid(p, uap, retval)
 };
 /* ARGSUSED */
 setuid(p, uap, retval)
@@ -228,19 +227,22 @@ setuid(p, uap, retval)
            (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
        /*
            (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.
+        * Everything's okay, do it.
+        * Transfer proc count to new user.
+        * Copy credentials so other references do not see our changes.
         */
         */
+       (void)chgproccnt(pc->p_ruid, -1);
+       (void)chgproccnt(uid, 1);
        pc->pc_ucred = crcopy(pc->pc_ucred);
        pc->pc_ucred->cr_uid = uid;
        pc->p_ruid = uid;
        pc->p_svuid = uid;
        pc->pc_ucred = crcopy(pc->pc_ucred);
        pc->pc_ucred->cr_uid = uid;
        pc->p_ruid = uid;
        pc->p_svuid = uid;
-       p->p_flag |= SUGID;
+       p->p_flag |= P_SUGID;
        return (0);
 }
 
 struct seteuid_args {
        return (0);
 }
 
 struct seteuid_args {
-       int     euid;
+       uid_t   euid;
 };
 /* ARGSUSED */
 seteuid(p, uap, retval)
 };
 /* ARGSUSED */
 seteuid(p, uap, retval)
@@ -262,12 +264,12 @@ 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;
+       p->p_flag |= P_SUGID;
        return (0);
 }
 
 struct setgid_args {
        return (0);
 }
 
 struct setgid_args {
-       int     gid;
+       gid_t   gid;
 };
 /* ARGSUSED */
 setgid(p, uap, retval)
 };
 /* ARGSUSED */
 setgid(p, uap, retval)
@@ -286,12 +288,12 @@ setgid(p, uap, retval)
        pc->pc_ucred->cr_groups[0] = gid;
        pc->p_rgid = gid;
        pc->p_svgid = gid;              /* ??? */
        pc->pc_ucred->cr_groups[0] = gid;
        pc->p_rgid = gid;
        pc->p_svgid = gid;              /* ??? */
-       p->p_flag |= SUGID;
+       p->p_flag |= P_SUGID;
        return (0);
 }
 
 struct setegid_args {
        return (0);
 }
 
 struct setegid_args {
-       int     egid;
+       gid_t   egid;
 };
 /* ARGSUSED */
 setegid(p, uap, retval)
 };
 /* ARGSUSED */
 setegid(p, uap, retval)
@@ -309,13 +311,13 @@ 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;
+       p->p_flag |= P_SUGID;
        return (0);
 }
 
 struct setgroups_args {
        u_int   gidsetsize;
        return (0);
 }
 
 struct setgroups_args {
        u_int   gidsetsize;
-       int     *gidset;
+       gid_t   *gidset;
 };
 /* ARGSUSED */
 setgroups(p, uap, retval)
 };
 /* ARGSUSED */
 setgroups(p, uap, retval)
@@ -324,27 +326,78 @@ setgroups(p, uap, retval)
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
-       register gid_t *gp;
        register u_int ngrp;
        register u_int ngrp;
-       register int *lp;
-       int error, groups[NGROUPS];
+       int error;
 
        if (error = suser(pc->pc_ucred, &p->p_acflag))
                return (error);
        if ((ngrp = uap->gidsetsize) > NGROUPS)
                return (EINVAL);
 
        if (error = suser(pc->pc_ucred, &p->p_acflag))
                return (error);
        if ((ngrp = uap->gidsetsize) > NGROUPS)
                return (EINVAL);
-       if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
-           ngrp * sizeof (groups[0])))
-               return (error);
        pc->pc_ucred = crcopy(pc->pc_ucred);
        pc->pc_ucred = crcopy(pc->pc_ucred);
+       if (error = copyin((caddr_t)uap->gidset,
+           (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))
+               return (error);
        pc->pc_ucred->cr_ngroups = ngrp;
        pc->pc_ucred->cr_ngroups = ngrp;
-       /* convert from int's to gid_t's */
-       for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
-               *gp++ = *lp++;
-       p->p_flag |= SUGID;
+       p->p_flag |= P_SUGID;
        return (0);
 }
 
        return (0);
 }
 
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
+struct setreuid_args {
+       int     ruid;
+       int     euid;
+};
+/* ARGSUSED */
+osetreuid(p, uap, retval)
+       register struct proc *p;
+       struct setreuid_args *uap;
+       int *retval;
+{
+       register struct pcred *pc = p->p_cred;
+       struct seteuid_args args;
+
+       /*
+        * we assume that the intent of setting ruid is to be able to get
+        * back ruid priviledge. So we make sure that we will be able to
+        * do so, but do not actually set the ruid.
+        */
+       if (uap->ruid != (uid_t)-1 && uap->ruid != pc->p_ruid &&
+           uap->ruid != pc->p_svuid)
+               return (EPERM);
+       if (uap->euid == (uid_t)-1)
+               return (0);
+       args.euid = uap->euid;
+       return (seteuid(p, &args, retval));
+}
+
+struct setregid_args {
+       int     rgid;
+       int     egid;
+};
+/* ARGSUSED */
+osetregid(p, uap, retval)
+       register struct proc *p;
+       struct setregid_args *uap;
+       int *retval;
+{
+       register struct pcred *pc = p->p_cred;
+       struct setegid_args args;
+
+       /*
+        * we assume that the intent of setting rgid is to be able to get
+        * back rgid priviledge. So we make sure that we will be able to
+        * do so, but do not actually set the rgid.
+        */
+       if (uap->rgid != (gid_t)-1 && uap->rgid != pc->p_rgid &&
+           uap->rgid != pc->p_svgid)
+               return (EPERM);
+       if (uap->egid == (gid_t)-1)
+               return (0);
+       args.egid = uap->egid;
+       return (setegid(p, &args, retval));
+}
+#endif /* defined(COMPAT_43) || defined(COMPAT_SUNOS) */
+
 /*
  * Check if gid is a member of the group set.
  */
 /*
  * Check if gid is a member of the group set.
  */
@@ -401,13 +454,11 @@ crget()
 crfree(cr)
        struct ucred *cr;
 {
 crfree(cr)
        struct ucred *cr;
 {
-       int s = splimp();                       /* ??? */
+       int s;
 
 
-       if (--cr->cr_ref != 0) {
-               (void) splx(s);
-               return;
-       }
-       FREE((caddr_t)cr, M_CRED);
+       s = splimp();                           /* ??? */
+       if (--cr->cr_ref == 0)
+               FREE((caddr_t)cr, M_CRED);
        (void) splx(s);
 }
 
        (void) splx(s);
 }