]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_prot.c
xnu-517.9.4.tar.gz
[apple/xnu.git] / bsd / kern / kern_prot.c
index 5882e93cf0b07ab4799897d2ed76bb5542f2ff57..db25475d6b3081efefa90949b80fc97e4d0f4963 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <sys/times.h>
 #include <sys/malloc.h>
 
+#include <bsm/audit_kernel.h>
+
 #include <sys/mount.h>
 #include <mach/message.h>
+#include <mach/host_security.h>
+
 #include <kern/host.h>
 
 /*
@@ -90,6 +94,7 @@ setprivexec(p, uap, retval)
        register struct setprivexec_args *uap;
        register_t *retval;
 {
+       AUDIT_ARG(value, uap->flag);
        *retval = p->p_debugger;
        p->p_debugger = (uap->flag != 0);
        return(0);
@@ -131,6 +136,56 @@ getpgrp(p, uap, retval)
        return (0);
 }
 
+/* Get an arbitary pid's process group id */
+struct getpgid_args {
+       pid_t   pid;
+};
+
+int
+getpgid(p, uap, retval)
+       struct proc *p;
+       struct getpgid_args *uap;
+       register_t *retval;
+{
+       struct proc *pt;
+
+       pt = p;
+       if (uap->pid == 0)
+               goto found;
+
+       if ((pt = pfind(uap->pid)) == 0)
+               return (ESRCH);
+found:
+       *retval = pt->p_pgrp->pg_id;
+       return (0);
+}
+
+/*
+ * Get an arbitary pid's session id.
+ */
+struct getsid_args {
+       pid_t   pid;
+};
+
+int
+getsid(p, uap, retval)
+       struct proc *p;
+       struct getsid_args *uap;
+       register_t *retval;
+{
+       struct proc *pt;
+
+       pt = p;
+       if (uap->pid == 0)
+               goto found;
+
+       if ((pt = pfind(uap->pid)) == 0)
+               return (ESRCH);
+found:
+       *retval = pt->p_session->s_sid;
+       return (0);
+}
+
 /* ARGSUSED */
 getuid(p, uap, retval)
        struct proc *p;
@@ -224,7 +279,7 @@ setsid(p, uap, retval)
        register_t *retval;
 {
 
-       if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
+       if (p->p_pgid == p->p_pid || pgfind(p->p_pid) || p->p_flag & P_INVFORK) {
                return (EPERM);
        } else {
                (void)enterpgrp(p, p->p_pid, 1);
@@ -274,7 +329,7 @@ setpgid(curp, uap, retval)
                uap->pgid = targp->p_pid;
        else if (uap->pgid != targp->p_pid)
                if ((pgrp = pgfind(uap->pgid)) == 0 ||
-                   pgrp->pg_session != curp->p_session)
+                   pgrp->pg_session != curp->p_session)
                        return (EPERM);
        return (enterpgrp(targp, uap->pgid, 0));
 }
@@ -314,6 +369,7 @@ setuid(p, uap, retval)
        int error;
 
        uid = uap->uid;
+       AUDIT_ARG(uid, uid, 0, 0, 0);
        if (uid != pc->p_ruid &&
            (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
@@ -322,6 +378,9 @@ setuid(p, uap, retval)
         * Transfer proc count to new user.
         * Copy credentials so other references do not see our changes.
         */
+
+       /* prepare app access profile files */
+       prepare_profile_database(uap->uid);
        pcred_writelock(p);
        (void)chgproccnt(pc->p_ruid, -1);
        (void)chgproccnt(uid, 1);
@@ -349,6 +408,7 @@ seteuid(p, uap, retval)
        int error;
 
        euid = uap->euid;
+       AUDIT_ARG(uid, 0, euid, 0, 0);
        if (euid != pc->p_ruid && euid != pc->p_svuid &&
            (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
@@ -379,6 +439,7 @@ setgid(p, uap, retval)
        int error;
 
        gid = uap->gid;
+       AUDIT_ARG(gid, gid, 0, 0, 0);
        if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
        pcred_writelock(p);
@@ -406,6 +467,7 @@ setegid(p, uap, retval)
        int error;
 
        egid = uap->egid;
+       AUDIT_ARG(gid, 0, egid, 0, 0);
        if (egid != pc->p_rgid && egid != pc->p_svgid &&
            (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
@@ -437,16 +499,23 @@ setgroups(p, uap, retval)
        if (error = suser(pc->pc_ucred, &p->p_acflag))
                return (error);
        ngrp = uap->gidsetsize;
-       if (ngrp < 1 || ngrp > NGROUPS)
+       if (ngrp > NGROUPS)
                return (EINVAL);
        new = crget();
-       error = copyin((caddr_t)uap->gidset,
-           (caddr_t)new->cr_groups, ngrp * sizeof(gid_t));
-       if (error) {
-               crfree(new);
-               return (error);
+       
+       if ( ngrp < 1 ) {
+               ngrp = 1;
+       }
+       else {
+               error = copyin((caddr_t)uap->gidset,
+                       (caddr_t)new->cr_groups, ngrp * sizeof(gid_t));
+               if (error) {
+                       crfree(new);
+                       return (error);
+               }
        }
        new->cr_ngroups = ngrp;
+       AUDIT_ARG(groupset, new->cr_groups, ngrp);
        pcred_writelock(p);
        old = pc->pc_ucred;
        new->cr_uid = old->cr_uid;
@@ -664,6 +733,32 @@ crdup(cr)
        return (newcr);
 }
 
+/*
+ * compare two cred structs
+ */
+int
+crcmp(cr1, cr2)
+       struct ucred *cr1;
+       struct ucred *cr2;
+{
+       int i;
+
+       if (cr1 == cr2)
+               return 0;
+       if (cr1 == NOCRED || cr1 == FSCRED ||
+           cr2 == NOCRED || cr2 == FSCRED)
+               return 1;
+       if (cr1->cr_uid != cr2->cr_uid)
+               return 1;
+       if (cr1->cr_ngroups != cr2->cr_ngroups)
+               return 1;
+       // XXX assumes groups will always be listed in some order
+       for (i=0; i < cr1->cr_ngroups; i++)
+               if (cr1->cr_groups[i] != cr2->cr_groups[i])
+                       return 1;
+       return (0);
+}
+
 /*
  * Get login name, if available.
  */
@@ -705,24 +800,63 @@ setlogin(p, uap, retval)
        error = copyinstr((caddr_t) uap->namebuf,
            (caddr_t) p->p_pgrp->pg_session->s_login,
            sizeof (p->p_pgrp->pg_session->s_login) - 1, (size_t *)&dummy);
-       if (error == ENAMETOOLONG)
+       if(!error)
+               AUDIT_ARG(text, p->p_pgrp->pg_session->s_login);
+       else if (error == ENAMETOOLONG)
                error = EINVAL;
        return (error);
 }
 
 
 /* Set the secrity token of the task with current euid and eguid */
-void
+kern_return_t
 set_security_token(struct proc * p)
 {
        security_token_t sec_token;
+       audit_token_t    audit_token;
 
        sec_token.val[0] = p->p_ucred->cr_uid;
-       sec_token.val[1] = p->p_ucred->cr_gid;
-       (void)host_security_set_task_token(host_security_self(),
+       sec_token.val[1] = p->p_ucred->cr_gid;
+
+       /*
+        * The current layout of the Mach audit token explicitly
+        * adds these fields.  But nobody should rely on such
+        * a literal representation.  Instead, the BSM library
+        * provides a function to convert an audit token into
+        * a BSM subject.  Use of that mechanism will isolate
+        * the user of the trailer from future representation
+        * changes.
+        */
+       audit_token.val[0] = p->p_au->ai_auid;
+       audit_token.val[1] = p->p_ucred->cr_uid;
+       audit_token.val[2] = p->p_ucred->cr_gid;
+       audit_token.val[3] = p->p_cred->p_ruid;
+        audit_token.val[4] = p->p_cred->p_rgid;
+       audit_token.val[5] = p->p_pid;
+       audit_token.val[6] = p->p_au->ai_asid;
+       audit_token.val[7] = p->p_au->ai_termid.port;
+
+       return host_security_set_task_token(host_security_self(),
                                           p->task,
                                           sec_token,
+                                          audit_token,
                                           (sec_token.val[0]) ?
-                                               HOST_PRIV_NULL :
+                                               HOST_PRIV_NULL :
                                                host_priv_self());
 }
+
+
+/*
+ * Fill in a struct xucred based on a struct ucred.
+ */
+__private_extern__
+void
+cru2x(struct ucred *cr, struct xucred *xcr)
+{
+
+       bzero(xcr, sizeof(*xcr));
+       xcr->cr_version = XUCRED_VERSION;
+       xcr->cr_uid = cr->cr_uid;
+       xcr->cr_ngroups = cr->cr_ngroups;
+       bcopy(cr->cr_groups, xcr->cr_groups, sizeof(xcr->cr_groups));
+}