add USL's copyright notice
[unix-history] / usr / src / sys / kern / kern_prot.c
index 3704465..668bd82 100644 (file)
@@ -1,34 +1,43 @@
 /*
 /*
- * 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.19 (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;
+};
 
 /* ARGSUSED */
 getpid(p, uap, retval)
        struct proc *p;
 
 /* ARGSUSED */
 getpid(p, uap, retval)
        struct proc *p;
-       void *uap;
+       struct args *uap;
        int *retval;
 {
 
        *retval = p->p_pid;
        int *retval;
 {
 
        *retval = p->p_pid;
-#ifdef COMPAT_43
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
        retval[1] = p->p_pptr->p_pid;
 #endif
        return (0);
        retval[1] = p->p_pptr->p_pid;
 #endif
        return (0);
@@ -37,7 +46,7 @@ getpid(p, uap, retval)
 /* ARGSUSED */
 getppid(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 getppid(p, uap, retval)
        struct proc *p;
-       void *uap;
+       struct args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -48,7 +57,7 @@ getppid(p, uap, retval)
 /* Get process group ID; note that POSIX getpgrp takes no parameter */
 getpgrp(p, uap, retval)
        struct proc *p;
 /* Get process group ID; note that POSIX getpgrp takes no parameter */
 getpgrp(p, uap, retval)
        struct proc *p;
-       void *uap;
+       struct args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -59,12 +68,12 @@ getpgrp(p, uap, retval)
 /* ARGSUSED */
 getuid(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 getuid(p, uap, retval)
        struct proc *p;
-       void *uap;
+       struct args *uap;
        int *retval;
 {
 
        *retval = p->p_cred->p_ruid;
        int *retval;
 {
 
        *retval = p->p_cred->p_ruid;
-#ifdef COMPAT_43
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
        retval[1] = p->p_ucred->cr_uid;
 #endif
        return (0);
        retval[1] = p->p_ucred->cr_uid;
 #endif
        return (0);
@@ -73,7 +82,7 @@ getuid(p, uap, retval)
 /* ARGSUSED */
 geteuid(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 geteuid(p, uap, retval)
        struct proc *p;
-       void *uap;
+       struct args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -84,12 +93,12 @@ geteuid(p, uap, retval)
 /* ARGSUSED */
 getgid(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 getgid(p, uap, retval)
        struct proc *p;
-       void *uap;
+       struct args *uap;
        int *retval;
 {
 
        *retval = p->p_cred->p_rgid;
        int *retval;
 {
 
        *retval = p->p_cred->p_rgid;
-#ifdef COMPAT_43
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
        retval[1] = p->p_ucred->cr_groups[0];
 #endif
        return (0);
        retval[1] = p->p_ucred->cr_groups[0];
 #endif
        return (0);
@@ -103,7 +112,7 @@ getgid(p, uap, retval)
 /* ARGSUSED */
 getegid(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 getegid(p, uap, retval)
        struct proc *p;
-       void *uap;
+       struct args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -111,19 +120,17 @@ getegid(p, uap, retval)
        return (0);
 }
 
        return (0);
 }
 
+struct getgroups_args {
+       u_int   gidsetsize;
+       gid_t   *gidset;
+};
 getgroups(p, uap, retval)
        struct proc *p;
 getgroups(p, uap, retval)
        struct proc *p;
-       register struct arg {
-               u_int   gidsetsize;
-               int     *gidset;                /* XXX not yet POSIX */
-       } *uap;
+       register struct getgroups_args *uap;
        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) {
@@ -133,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);
@@ -145,14 +150,14 @@ getgroups(p, uap, retval)
 /* ARGSUSED */
 setsid(p, uap, retval)
        register struct proc *p;
 /* ARGSUSED */
 setsid(p, uap, retval)
        register struct proc *p;
-       void *uap;
+       struct args *uap;
        int *retval;
 {
 
        if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
                return (EPERM);
        } else {
        int *retval;
 {
 
        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);
        }
@@ -161,7 +166,7 @@ setsid(p, uap, retval)
 /*
  * set process group (setpgid/old setpgrp)
  *
 /*
  * set process group (setpgid/old setpgrp)
  *
- * caller does setpgid(pid, pgid)
+ * caller does setpgid(targpid, targpgid)
  *
  * pid must be caller or child of caller (ESRCH)
  * if a child
  *
  * pid must be caller or child of caller (ESRCH)
  * if a child
@@ -171,46 +176,46 @@ setsid(p, uap, retval)
  *     there must exist some pid in same session having pgid (EPERM)
  * pid must not be session leader (EPERM)
  */
  *     there must exist some pid in same session having pgid (EPERM)
  * pid must not be session leader (EPERM)
  */
+struct setpgid_args {
+       int     pid;    /* target process id */
+       int     pgid;   /* target pgrp id */
+};
 /* ARGSUSED */
 /* ARGSUSED */
-setpgid(cp, uap, retval)
-       struct proc *cp;
-       register struct args {
-               int     pid;
-               int     pgid;
-       } *uap;
+setpgid(curp, uap, retval)
+       struct proc *curp;
+       register struct setpgid_args *uap;
        int *retval;
 {
        int *retval;
 {
-       register struct proc *p;
-       register struct pgrp *pgrp;
+       register struct proc *targp;            /* target process */
+       register struct pgrp *pgrp;             /* target pgrp */
 
 
-       if (uap->pid != 0) {
-               if ((p = pfind(uap->pid)) == 0 || !inferior(p))
+       if (uap->pid != 0 && uap->pid != curp->p_pid) {
+               if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
                        return (ESRCH);
                        return (ESRCH);
-               if (p->p_session != cp->p_session)
+               if (targp->p_session != curp->p_session)
                        return (EPERM);
                        return (EPERM);
-               if (p->p_flag&SEXEC)
+               if (targp->p_flag & P_EXEC)
                        return (EACCES);
        } else
                        return (EACCES);
        } else
-               p = cp;
-       if (SESS_LEADER(p))
+               targp = curp;
+       if (SESS_LEADER(targp))
                return (EPERM);
        if (uap->pgid == 0)
                return (EPERM);
        if (uap->pgid == 0)
-               uap->pgid = p->p_pid;
-       else if (uap->pgid != p->p_pid)
+               uap->pgid = targp->p_pid;
+       else if (uap->pgid != targp->p_pid)
                if ((pgrp = pgfind(uap->pgid)) == 0 ||
                if ((pgrp = pgfind(uap->pgid)) == 0 ||
-                   pgrp->pg_mem == NULL ||
-                   pgrp->pg_session != cp->p_session)
+                   pgrp->pg_session != curp->p_session)
                        return (EPERM);
                        return (EPERM);
-       enterpgrp(p, uap->pgid, 0);
-       return (0);
+       return (enterpgrp(targp, uap->pgid, 0));
 }
 
 }
 
+struct setuid_args {
+       uid_t   uid;
+};
 /* ARGSUSED */
 setuid(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 setuid(p, uap, retval)
        struct proc *p;
-       struct args {
-               int     uid;
-       } *uap;
+       struct setuid_args *uap;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
@@ -222,22 +227,27 @@ 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 |= P_SUGID;
        return (0);
 }
 
        return (0);
 }
 
+struct seteuid_args {
+       uid_t   euid;
+};
 /* ARGSUSED */
 seteuid(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 seteuid(p, uap, retval)
        struct proc *p;
-       struct args {
-               int     euid;
-       } *uap;
+       struct seteuid_args *uap;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
@@ -254,15 +264,17 @@ 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 |= P_SUGID;
        return (0);
 }
 
        return (0);
 }
 
+struct setgid_args {
+       gid_t   gid;
+};
 /* ARGSUSED */
 setgid(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 setgid(p, uap, retval)
        struct proc *p;
-       struct args {
-               int     gid;
-       } *uap;
+       struct setgid_args *uap;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
@@ -276,15 +288,17 @@ 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 |= P_SUGID;
        return (0);
 }
 
        return (0);
 }
 
+struct setegid_args {
+       gid_t   egid;
+};
 /* ARGSUSED */
 setegid(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 setegid(p, uap, retval)
        struct proc *p;
-       struct args {
-               int     egid;
-       } *uap;
+       struct setegid_args *uap;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
@@ -297,98 +311,92 @@ 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 |= P_SUGID;
        return (0);
 }
 
        return (0);
 }
 
-#ifdef COMPAT_43
+struct setgroups_args {
+       u_int   gidsetsize;
+       gid_t   *gidset;
+};
 /* ARGSUSED */
 /* ARGSUSED */
-osetreuid(p, uap, retval)
-       register struct proc *p;
-       struct args {
-               int     ruid;
-               int     euid;
-       } *uap;
+setgroups(p, uap, retval)
+       struct proc *p;
+       struct setgroups_args *uap;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
        int *retval;
 {
        register struct pcred *pc = p->p_cred;
-       register uid_t ruid, euid;
+       register u_int ngrp;
        int error;
 
        int error;
 
-       if (uap->ruid == -1)
-       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)
-       if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
-           euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag)))
+       if (error = suser(pc->pc_ucred, &p->p_acflag))
                return (error);
                return (error);
-       /*
-        * Everything's okay, do it.  Copy credentials so other references do
-        * not see our changes.
-        */
+       if ((ngrp = uap->gidsetsize) > NGROUPS)
+               return (EINVAL);
        pc->pc_ucred = crcopy(pc->pc_ucred);
        pc->pc_ucred = crcopy(pc->pc_ucred);
-       pc->pc_ucred->cr_uid = euid;
-       pc->p_ruid = ruid;
+       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;
+       p->p_flag |= P_SUGID;
        return (0);
 }
 
        return (0);
 }
 
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
+struct setreuid_args {
+       int     ruid;
+       int     euid;
+};
 /* ARGSUSED */
 /* ARGSUSED */
-osetregid(p, uap, retval)
+osetreuid(p, uap, retval)
        register struct proc *p;
        register struct proc *p;
-       struct args {
-               int     rgid;
-               int     egid;
-       } *uap;
+       struct setreuid_args *uap;
        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 seteuid_args args;
 
 
-       if (uap->rgid == -1)
-       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)
-       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);
+       /*
+        * 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));
 }
 }
-#endif
 
 
+struct setregid_args {
+       int     rgid;
+       int     egid;
+};
 /* ARGSUSED */
 /* ARGSUSED */
-setgroups(p, uap, retval)
-       struct proc *p;
-       struct args {
-               u_int   gidsetsize;
-               int     *gidset;
-       } *uap;
+osetregid(p, uap, retval)
+       register struct proc *p;
+       struct setregid_args *uap;
        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 int *lp;
-       int error, groups[NGROUPS];
+       struct setegid_args args;
 
 
-       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->cr_ngroups = ngrp;
-       /* convert from int's to gid_t's */
-       for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
-               *gp++ = *lp++;
-       return (0);
+       /*
+        * 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.
@@ -446,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);
 }
 
@@ -492,13 +498,14 @@ crdup(cr)
 /*
  * Get login name, if available.
  */
 /*
  * Get login name, if available.
  */
+struct getlogin_args {
+       char    *namebuf;
+       u_int   namelen;
+};
 /* ARGSUSED */
 getlogin(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 getlogin(p, uap, retval)
        struct proc *p;
-       struct args {
-               char    *namebuf;
-               u_int   namelen;
-       } *uap;
+       struct getlogin_args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -511,12 +518,13 @@ getlogin(p, uap, retval)
 /*
  * Set login name.
  */
 /*
  * Set login name.
  */
+struct setlogin_args {
+       char    *namebuf;
+};
 /* ARGSUSED */
 setlogin(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 setlogin(p, uap, retval)
        struct proc *p;
-       struct args {
-               char    *namebuf;
-       } *uap;
+       struct setlogin_args *uap;
        int *retval;
 {
        int error;
        int *retval;
 {
        int error;