]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_prot.c
xnu-792.22.5.tar.gz
[apple/xnu.git] / bsd / kern / kern_prot.c
index 2e2a52dff620cd577f134d22e83affe47dd0b4b9..8ed96a39095e89e8c38f1d025710168ad417572a 100644 (file)
@@ -251,21 +251,21 @@ getgroups(__unused struct proc *p, struct getgroups_args *uap, register_t *retva
 
        if ((ngrp = uap->gidsetsize) == 0) {
                *retval = cred->cr_ngroups;
-               kauth_cred_rele(cred);
+               kauth_cred_unref(&cred);
                return (0);
        }
        if (ngrp < cred->cr_ngroups) {
-               kauth_cred_rele(cred);
+               kauth_cred_unref(&cred);
                return (EINVAL);
        }
        ngrp = cred->cr_ngroups;
        if ((error = copyout((caddr_t)cred->cr_groups,
                                        uap->gidset, 
                                        ngrp * sizeof(gid_t)))) {
-               kauth_cred_rele(cred);
+               kauth_cred_unref(&cred);
                return (error);
        }
-       kauth_cred_rele(cred);
+       kauth_cred_unref(&cred);
        *retval = ngrp;
        return (0);
 }
@@ -394,8 +394,11 @@ setuid(struct proc *p, struct setuid_args *uap, __unused register_t *retval)
                my_cred = kauth_cred_proc_ref(p);
                
                /* 
-                * set the credential with new info.  If there is no change we get back 
-                * the same credential we passed in.
+                * Set the credential with new info.  If there is no change,
+                * we get back the same credential we passed in; if there is
+                * a change, we drop the reference on the credential we
+                * passed in.  The subsequent compare is safe, because it is
+                * a pointer compare rather than a contents compare.
                 */
                my_new_cred = kauth_cred_setuid(my_cred, uid);
                if (my_cred != my_new_cred) {
@@ -406,8 +409,7 @@ setuid(struct proc *p, struct setuid_args *uap, __unused register_t *retval)
                         */
                        if (p->p_ucred != my_cred) {
                                proc_unlock(p);
-                               kauth_cred_rele(my_cred);
-                               kauth_cred_rele(my_new_cred);
+                               kauth_cred_unref(&my_new_cred);
                                /* try again */
                                continue;
                        }
@@ -415,8 +417,8 @@ setuid(struct proc *p, struct setuid_args *uap, __unused register_t *retval)
                        p->p_flag |= P_SUGID;
                        proc_unlock(p);
                }
-               /* drop our extra reference */
-               kauth_cred_rele(my_cred);
+               /* drop old proc reference or our extra reference */
+               kauth_cred_unref(&my_cred);
                break;
        }
        
@@ -446,21 +448,25 @@ seteuid(struct proc *p, struct seteuid_args *uap, __unused register_t *retval)
                my_cred = kauth_cred_proc_ref(p);
        
                /* 
-                * set the credential with new info.  If there is no change we get back 
-                * the same credential we passed in.
+                * Set the credential with new info.  If there is no change,
+                * we get back the same credential we passed in; if there is
+                * a change, we drop the reference on the credential we
+                * passed in.  The subsequent compare is safe, because it is
+                * a pointer compare rather than a contents compare.
                 */
-               my_new_cred = kauth_cred_seteuid(p->p_ucred, euid);
+               my_new_cred = kauth_cred_seteuid(my_cred, euid);
        
                if (my_cred != my_new_cred) {
                        proc_lock(p);
-                       /* need to protect for a race where another thread also changed
-                        * the credential after we took our reference.  If p_ucred has 
-                        * changed then we should restart this again with the new cred.
+                       /*
+                        * We need to protect for a race where another thread
+                        * also changed the credential after we took our
+                        * reference.  If p_ucred has changed then we should
+                        * restart this again with the new cred.
                         */
                        if (p->p_ucred != my_cred) {
                                proc_unlock(p);
-                               kauth_cred_rele(my_cred);
-                               kauth_cred_rele(my_new_cred);
+                               kauth_cred_unref(&my_new_cred);
                                /* try again */
                                continue;
                        }
@@ -468,8 +474,8 @@ seteuid(struct proc *p, struct seteuid_args *uap, __unused register_t *retval)
                        p->p_flag |= P_SUGID;
                        proc_unlock(p);
                }
-               /* drop our extra reference */
-               kauth_cred_rele(my_cred);
+               /* drop old proc reference or our extra reference */
+               kauth_cred_unref(&my_cred);
                break;
        }
 
@@ -495,20 +501,24 @@ setgid(struct proc *p, struct setgid_args *uap, __unused register_t *retval)
                my_cred = kauth_cred_proc_ref(p);
                
                /* 
-                * set the credential with new info.  If there is no change we get back 
-                * the same credential we passed in.
+                * Set the credential with new info.  If there is no change,
+                * we get back the same credential we passed in; if there is
+                * a change, we drop the reference on the credential we
+                * passed in.  The subsequent compare is safe, because it is
+                * a pointer compare rather than a contents compare.
                 */
-               my_new_cred = kauth_cred_setgid(p->p_ucred, gid);
+               my_new_cred = kauth_cred_setgid(my_cred, gid);
                if (my_cred != my_new_cred) {
                        proc_lock(p);
-                       /* need to protect for a race where another thread also changed
-                        * the credential after we took our reference.  If p_ucred has 
-                        * changed then we should restart this again with the new cred.
+                       /*
+                        * We need to protect for a race where another thread
+                        * also changed the credential after we took our
+                        * reference.  If p_ucred has changed then we should
+                        * restart this again with the new cred.
                         */
                        if (p->p_ucred != my_cred) {
                                proc_unlock(p);
-                               kauth_cred_rele(my_cred);
-                               kauth_cred_rele(my_new_cred);
+                               kauth_cred_unref(&my_new_cred);
                                /* try again */
                                continue;
                        }
@@ -516,8 +526,8 @@ setgid(struct proc *p, struct setgid_args *uap, __unused register_t *retval)
                        p->p_flag |= P_SUGID;
                        proc_unlock(p);
                }
-               /* drop our extra reference */
-               kauth_cred_rele(my_cred);
+               /* drop old proc reference or our extra reference */
+               kauth_cred_unref(&my_cred);
                break;
        }
        
@@ -544,10 +554,13 @@ setegid(struct proc *p, struct setegid_args *uap, __unused register_t *retval)
                my_cred = kauth_cred_proc_ref(p);
                
                /* 
-                * set the credential with new info.  If there is no change we get back 
-                * the same credential we passed in.
+                * Set the credential with new info.  If there is no change,
+                * we get back the same credential we passed in; if there is
+                * a change, we drop the reference on the credential we
+                * passed in.  The subsequent compare is safe, because it is
+                * a pointer compare rather than a contents compare.
                 */
-               my_new_cred = kauth_cred_setegid(p->p_ucred, egid);
+               my_new_cred = kauth_cred_setegid(my_cred, egid);
                if (my_cred != my_new_cred) {
                        proc_lock(p);
                        /* need to protect for a race where another thread also changed
@@ -556,8 +569,7 @@ setegid(struct proc *p, struct setegid_args *uap, __unused register_t *retval)
                         */
                        if (p->p_ucred != my_cred) {
                                proc_unlock(p);
-                               kauth_cred_rele(my_cred);
-                               kauth_cred_rele(my_new_cred);
+                               kauth_cred_unref(&my_new_cred);
                                /* try again */
                                continue;
                        }
@@ -565,8 +577,8 @@ setegid(struct proc *p, struct setegid_args *uap, __unused register_t *retval)
                        p->p_flag |= P_SUGID;
                        proc_unlock(p);
                }
-               /* drop our extra reference */
-               kauth_cred_rele(my_cred);
+               /* drop old proc reference or our extra reference */
+               kauth_cred_unref(&my_cred);
                break;
        }
 
@@ -606,7 +618,7 @@ settid(struct proc *p, struct settid_args *uap, __unused register_t *retval)
 
                /* revert to delayed binding of process credential */
                uc = kauth_cred_proc_ref(p);
-               kauth_cred_rele(uthread->uu_ucred);
+               kauth_cred_unref(&uthread->uu_ucred);
                uthread->uu_ucred = uc;
                uthread->uu_flag &= ~UT_SETUID;
        } else {
@@ -630,7 +642,7 @@ settid(struct proc *p, struct settid_args *uap, __unused register_t *retval)
                uthread->uu_flag |= UT_SETUID;
 
                /* drop our extra reference */
-               kauth_cred_rele(my_cred);
+               kauth_cred_unref(&my_cred);
        }
        /*
         * XXX should potentially set per thread security token (there is
@@ -699,8 +711,8 @@ settid_with_pid(struct proc *p, struct settid_with_pid_args *uap, __unused regis
                uthread->uu_flag |= UT_SETUID;
                
                /* drop our extra references */
-               kauth_cred_rele(my_cred);
-               kauth_cred_rele(my_target_cred);
+               kauth_cred_unref(&my_cred);
+               kauth_cred_unref(&my_target_cred);
 
                return (0);
        }
@@ -713,7 +725,7 @@ settid_with_pid(struct proc *p, struct settid_with_pid_args *uap, __unused regis
 
        /* revert to delayed binding of process credential */
        my_new_cred = kauth_cred_proc_ref(p);
-       kauth_cred_rele(uthread->uu_ucred);
+       kauth_cred_unref(&uthread->uu_ucred);
        uthread->uu_ucred = my_new_cred;
        uthread->uu_flag &= ~UT_SETUID;
        
@@ -773,8 +785,12 @@ setgroups1(struct proc *p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __
                        my_cred = kauth_cred_proc_ref(p);
 
                        /* 
-                        * set the credential with new info.  If there is no
-                        * change we get back the same credential we passed in.
+                        * Set the credential with new info.  If there is no
+                        * change, we get back the same credential we passed
+                        * in; if there is a change, we drop the reference on
+                        * the credential we passed in.  The subsequent
+                        * compare is safe, because it is a pointer compare
+                        * rather than a contents compare.
                         */
                        my_new_cred = kauth_cred_setgroups(my_cred, &newgroups[0], ngrp, gmuid);
                        if (my_cred != my_new_cred) {
@@ -788,8 +804,7 @@ setgroups1(struct proc *p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __
                                 */
                                if (p->p_ucred != my_cred) {
                                        proc_unlock(p);
-                                       kauth_cred_rele(my_cred);
-                                       kauth_cred_rele(my_new_cred);
+                                       kauth_cred_unref(&my_new_cred);
                                        /* try again */
                                        continue;
                                }
@@ -797,8 +812,8 @@ setgroups1(struct proc *p, u_int gidsetsize, user_addr_t gidset, uid_t gmuid, __
                                p->p_flag |= P_SUGID;
                                proc_unlock(p);
                        }
-                       /* drop our extra reference */
-                       kauth_cred_rele(my_cred);
+                       /* drop old proc reference or our extra reference */
+                       kauth_cred_unref(&my_cred);
                        break;
                }
 
@@ -868,7 +883,7 @@ int
 suser(kauth_cred_t cred, u_short *acflag)
 {
 #if DIAGNOSTIC
-       if (cred == NOCRED || cred == FSCRED)
+       if (!IS_VALID_CRED(cred))
                panic("suser");
 #endif
        if (kauth_cred_getuid(cred) == 0) {
@@ -965,7 +980,7 @@ set_security_token(struct proc * p)
        }
                
        /* XXX mach_init doesn't have a p_ucred when it calls this function */
-       if (p->p_ucred != NOCRED && p->p_ucred != FSCRED) {
+       if (IS_VALID_CRED(p->p_ucred)) {
                sec_token.val[0] = kauth_cred_getuid(p->p_ucred);
                sec_token.val[1] = p->p_ucred->cr_gid;
        } else {