]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_prot.c
xnu-7195.81.3.tar.gz
[apple/xnu.git] / bsd / kern / kern_prot.c
index 7840d8a4bf700d4faa067e995d076fbace9e7be7..d689b70d57533a8fb2aa594c69b82f37823c3fef 100644 (file)
@@ -501,6 +501,27 @@ getwgroups(__unused proc_t p, __unused struct getwgroups_args *uap, __unused int
        return ENOTSUP;
 }
 
+/*
+ * setsid_internal
+ *
+ * Description:        Core implementation of setsid().
+ */
+int
+setsid_internal(proc_t p)
+{
+       struct pgrp * pg = PGRP_NULL;
+
+       if (p->p_pgrpid == p->p_pid || (pg = pgfind(p->p_pid)) || p->p_lflag & P_LINVFORK) {
+               if (pg != PGRP_NULL) {
+                       pg_rele(pg);
+               }
+               return EPERM;
+       } else {
+               /* enter pgrp works with its own pgrp refcount */
+               (void)enterpgrp(p, p->p_pid, 1);
+               return 0;
+       }
+}
 
 /*
  * setsid
@@ -529,19 +550,11 @@ getwgroups(__unused proc_t p, __unused struct getwgroups_args *uap, __unused int
 int
 setsid(proc_t p, __unused struct setsid_args *uap, int32_t *retval)
 {
-       struct pgrp * pg = PGRP_NULL;
-
-       if (p->p_pgrpid == p->p_pid || (pg = pgfind(p->p_pid)) || p->p_lflag & P_LINVFORK) {
-               if (pg != PGRP_NULL) {
-                       pg_rele(pg);
-               }
-               return EPERM;
-       } else {
-               /* enter pgrp works with its own pgrp refcount */
-               (void)enterpgrp(p, p->p_pid, 1);
+       int rc = setsid_internal(p);
+       if (rc == 0) {
                *retval = p->p_pid;
-               return 0;
        }
+       return rc;
 }
 
 
@@ -1640,30 +1653,34 @@ settid_with_pid(proc_t p, struct settid_with_pid_args *uap, __unused int32_t *re
  *             flag the process as having set privilege since the last exec.
  */
 static int
-setgroups1(proc_t p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __unused int32_t *retval)
+setgroups1(proc_t p, u_int ngrp, user_addr_t gidset, uid_t gmuid, __unused int32_t *retval)
 {
-       u_int ngrp;
        gid_t   newgroups[NGROUPS] = { 0 };
        int     error;
-       kauth_cred_t my_cred, my_new_cred;
-       struct uthread *uthread = get_bsdthread_info(current_thread());
 
-       DEBUG_CRED_ENTER("setgroups1 (%d/%d): %d 0x%016x %d\n", p->p_pid, (p->p_pptr ? p->p_pptr->p_pid : 0), gidsetsize, gidset, gmuid);
+       DEBUG_CRED_ENTER("setgroups1 (%d/%d): %d 0x%016x %d\n", p->p_pid,
+           (p->p_pptr ? p->p_pptr->p_pid : 0), ngrp, gidset, gmuid);
 
-       ngrp = gidsetsize;
        if (ngrp > NGROUPS) {
                return EINVAL;
        }
 
-       if (ngrp < 1) {
-               ngrp = 1;
-       } else {
+       if (ngrp >= 1) {
                error = copyin(gidset,
                    (caddr_t)newgroups, ngrp * sizeof(gid_t));
                if (error) {
                        return error;
                }
        }
+       return setgroups_internal(p, ngrp, newgroups, gmuid);
+}
+
+int
+setgroups_internal(proc_t p, u_int ngrp, gid_t *newgroups, uid_t gmuid)
+{
+       struct uthread *uthread = get_bsdthread_info(current_thread());
+       kauth_cred_t my_cred, my_new_cred;
+       int     error;
 
        my_cred = kauth_cred_proc_ref(p);
        if ((error = suser(my_cred, &p->p_acflag))) {
@@ -1671,6 +1688,11 @@ setgroups1(proc_t p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __unused
                return error;
        }
 
+       if (ngrp < 1) {
+               ngrp = 1;
+               newgroups[0] = 0;
+       }
+
        if ((uthread->uu_flag & UT_SETUID) != 0) {
 #if DEBUG_CRED
                int my_cred_flags = uthread->uu_ucred->cr_flags;
@@ -1942,6 +1964,18 @@ getlogin(proc_t p, struct getlogin_args *uap, __unused int32_t *retval)
        return copyout((caddr_t)buffer, uap->namebuf, uap->namelen);
 }
 
+void
+setlogin_internal(proc_t p, const char login[static MAXLOGNAME])
+{
+       struct session *sessp = proc_session(p);
+
+       if (sessp != SESSION_NULL) {
+               session_lock(sessp);
+               bcopy(login, sessp->s_login, MAXLOGNAME);
+               session_unlock(sessp);
+               session_rele(sessp);
+       }
+}
 
 /*
  * setlogin
@@ -1965,7 +1999,6 @@ setlogin(proc_t p, struct setlogin_args *uap, __unused int32_t *retval)
        int error;
        size_t dummy = 0;
        char buffer[MAXLOGNAME + 1];
-       struct session * sessp;
 
        if ((error = proc_suser(p))) {
                return error;
@@ -1978,15 +2011,7 @@ setlogin(proc_t p, struct setlogin_args *uap, __unused int32_t *retval)
            (caddr_t) &buffer[0],
            MAXLOGNAME - 1, (size_t *)&dummy);
 
-       sessp = proc_session(p);
-
-       if (sessp != SESSION_NULL) {
-               session_lock(sessp);
-               bcopy(buffer, sessp->s_login, MAXLOGNAME);
-               session_unlock(sessp);
-               session_rele(sessp);
-       }
-
+       setlogin_internal(p, buffer);
 
        if (!error) {
                AUDIT_ARG(text, buffer);
@@ -2008,6 +2033,30 @@ set_security_token(proc_t p)
        return set_security_token_task_internal(p, p->task);
 }
 
+static void
+proc_calc_audit_token(proc_t p, kauth_cred_t my_cred, audit_token_t *audit_token)
+{
+       posix_cred_t my_pcred = posix_cred_get(my_cred);
+
+       /*
+        * 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] = my_cred->cr_audit.as_aia_p->ai_auid;
+       audit_token->val[1] = my_pcred->cr_uid;
+       audit_token->val[2] = my_pcred->cr_gid;
+       audit_token->val[3] = my_pcred->cr_ruid;
+       audit_token->val[4] = my_pcred->cr_rgid;
+       audit_token->val[5] = p->p_pid;
+       audit_token->val[6] = my_cred->cr_audit.as_aia_p->ai_asid;
+       audit_token->val[7] = p->p_idversion;
+}
+
 /*
  * Set the secrity token of the task with current euid and eguid
  * The function takes a proc and a task, where proc->task might point to a
@@ -2017,10 +2066,9 @@ set_security_token(proc_t p)
 int
 set_security_token_task_internal(proc_t p, void *t)
 {
+       kauth_cred_t my_cred;
        security_token_t sec_token;
        audit_token_t    audit_token;
-       kauth_cred_t my_cred;
-       posix_cred_t my_pcred;
        host_priv_t host_priv;
        task_t task = t;
 
@@ -2039,7 +2087,8 @@ set_security_token_task_internal(proc_t p, void *t)
        }
 
        my_cred = kauth_cred_proc_ref(p);
-       my_pcred = posix_cred_get(my_cred);
+
+       proc_calc_audit_token(p, my_cred, &audit_token);
 
        /* XXX mach_init doesn't have a p_ucred when it calls this function */
        if (IS_VALID_CRED(my_cred)) {
@@ -2050,24 +2099,6 @@ set_security_token_task_internal(proc_t p, void *t)
                sec_token.val[1] = 0;
        }
 
-       /*
-        * 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] = my_cred->cr_audit.as_aia_p->ai_auid;
-       audit_token.val[1] = my_pcred->cr_uid;
-       audit_token.val[2] = my_pcred->cr_gid;
-       audit_token.val[3] = my_pcred->cr_ruid;
-       audit_token.val[4] = my_pcred->cr_rgid;
-       audit_token.val[5] = p->p_pid;
-       audit_token.val[6] = my_cred->cr_audit.as_aia_p->ai_asid;
-       audit_token.val[7] = p->p_idversion;
-
        host_priv = (sec_token.val[0]) ? HOST_PRIV_NULL : host_priv_self();
 #if CONFIG_MACF
        if (host_priv != HOST_PRIV_NULL && mac_system_check_host_priv(my_cred)) {
@@ -2090,6 +2121,22 @@ set_security_token_task_internal(proc_t p, void *t)
                   host_priv) != KERN_SUCCESS;
 }
 
+void
+proc_parent_audit_token(proc_t p, audit_token_t *token_out)
+{
+       proc_t parent;
+       kauth_cred_t my_cred;
+
+       proc_list_lock();
+
+       parent = p->p_pptr;
+       my_cred = kauth_cred_proc_ref(parent);
+       proc_calc_audit_token(parent, my_cred, token_out);
+       kauth_cred_unref(&my_cred);
+
+       proc_list_unlock();
+}
+
 
 int get_audit_token_pid(audit_token_t *audit_token);