]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_credential.c
xnu-3248.50.21.tar.gz
[apple/xnu.git] / bsd / kern / kern_credential.c
index b3c0d357afa8c42c01071e9257352ec9f76fb44d..0558ce4499be9acb0d3172f431e008ba1eec3786 100644 (file)
@@ -264,9 +264,7 @@ static void kauth_groups_trimcache(int newsize);
 
 #endif /* CONFIG_EXT_RESOLVER */
 
 
 #endif /* CONFIG_EXT_RESOLVER */
 
-static const int kauth_cred_primes[KAUTH_CRED_PRIMES_COUNT] = KAUTH_CRED_PRIMES;
-static int     kauth_cred_primes_index = 0;
-static int     kauth_cred_table_size = 0;
+#define KAUTH_CRED_TABLE_SIZE 97
 
 TAILQ_HEAD(kauth_cred_entry_head, ucred);
 static struct kauth_cred_entry_head * kauth_cred_table_anchor = NULL;
 
 TAILQ_HEAD(kauth_cred_entry_head, ucred);
 static struct kauth_cred_entry_head * kauth_cred_table_anchor = NULL;
@@ -2075,14 +2073,66 @@ static int      kauth_cred_cache_lookup(int from, int to, void *src, void *dst);
 
 #if CONFIG_EXT_RESOLVER == 0
 /*
 
 #if CONFIG_EXT_RESOLVER == 0
 /*
- * If there's no resolver, short-circuit the kauth_cred_x2y() lookups.
+ * If there's no resolver, only support a subset of the kauth_cred_x2y() lookups.
  */
 static __inline int
  */
 static __inline int
-kauth_cred_cache_lookup(__unused int from, __unused int to,
-       __unused void *src, __unused void *dst)
+kauth_cred_cache_lookup(int from, int to, void *src, void *dst)
 {
 {
-       return (EWOULDBLOCK);
-
+       /* NB: These must match the definitions used by Libinfo's mbr_identifier_translate(). */
+       static const uuid_t _user_compat_prefix = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00};
+       static const uuid_t _group_compat_prefix = {0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00};
+#define COMPAT_PREFIX_LEN      (sizeof(uuid_t) - sizeof(id_t))
+
+       assert(from != to);
+
+       switch (from) {
+       case KI_VALID_UID: {
+               id_t uid = htonl(*(id_t *)src);
+
+               if (to == KI_VALID_GUID) {
+                       uint8_t *uu = dst;
+                       memcpy(uu, _user_compat_prefix, sizeof(_user_compat_prefix));
+                       memcpy(&uu[COMPAT_PREFIX_LEN], &uid, sizeof(uid));
+                       return (0);
+               }
+               break;
+       }
+       case KI_VALID_GID: {
+               id_t gid = htonl(*(id_t *)src);
+
+               if (to == KI_VALID_GUID) {
+                       uint8_t *uu = dst;
+                       memcpy(uu, _group_compat_prefix, sizeof(_group_compat_prefix));
+                       memcpy(&uu[COMPAT_PREFIX_LEN], &gid, sizeof(gid));
+                       return (0);
+               }
+               break;
+       }
+       case KI_VALID_GUID: {
+               const uint8_t *uu = src;
+
+               if (to == KI_VALID_UID) {
+                       if (memcmp(uu, _user_compat_prefix, COMPAT_PREFIX_LEN) == 0) {
+                               id_t uid;
+                               memcpy(&uid, &uu[COMPAT_PREFIX_LEN], sizeof(uid));
+                               *(id_t *)dst = ntohl(uid);
+                               return (0);
+                       }
+               } else if (to == KI_VALID_GID) {
+                       if (memcmp(uu, _group_compat_prefix, COMPAT_PREFIX_LEN) == 0) {
+                               id_t gid;
+                               memcpy(&gid, &uu[COMPAT_PREFIX_LEN], sizeof(gid));
+                               *(id_t *)dst = ntohl(gid);
+                               return (0);
+                       }
+               }
+               break;
+       }
+       default:
+               /* NOT IMPLEMENTED */
+               break;
+       }
+       return (ENOENT);
 }
 #endif
 
 }
 #endif
 
@@ -3161,11 +3211,11 @@ kauth_cred_ismember_guid(__unused kauth_cred_t cred, guid_t *guidp, int *resultp
                *resultp = 1;
                break;
        default:
                *resultp = 1;
                break;
        default:
-#if CONFIG_EXT_RESOLVER
        {
        {
-               struct kauth_identity ki;
                gid_t gid;
                gid_t gid;
-#if 6603280
+#if CONFIG_EXT_RESOLVER
+               struct kauth_identity ki;
+
                /*
                 * Grovel the identity cache looking for this GUID.
                 * If we find it, and it is for a user record, return
                /*
                 * Grovel the identity cache looking for this GUID.
                 * If we find it, and it is for a user record, return
@@ -3192,7 +3242,7 @@ kauth_cred_ismember_guid(__unused kauth_cred_t cred, guid_t *guidp, int *resultp
                                return (0);
                        }
                }
                                return (0);
                        }
                }
-#endif /* 6603280 */
+#endif /* CONFIG_EXT_RESOLVER */
                /*
                 * Attempt to translate the GUID to a GID.  Even if
                 * this fails, we will have primed the cache if it is
                /*
                 * Attempt to translate the GUID to a GID.  Even if
                 * this fails, we will have primed the cache if it is
@@ -3209,13 +3259,12 @@ kauth_cred_ismember_guid(__unused kauth_cred_t cred, guid_t *guidp, int *resultp
                                error = 0;
                        }
                } else {
                                error = 0;
                        }
                } else {
+#if CONFIG_EXT_RESOLVER
  do_check:
  do_check:
+#endif /* CONFIG_EXT_RESOLVER */
                        error = kauth_cred_ismember_gid(cred, gid, resultp);
                }
        }
                        error = kauth_cred_ismember_gid(cred, gid, resultp);
                }
        }
-#else  /* CONFIG_EXT_RESOLVER */
-               error = ENOENT;
-#endif /* CONFIG_EXT_RESOLVER */
                break;
        }
        return(error);
                break;
        }
        return(error);
@@ -3364,15 +3413,14 @@ kauth_cred_init(void)
        int             i;
        
        kauth_cred_hash_mtx = lck_mtx_alloc_init(kauth_lck_grp, 0/*LCK_ATTR_NULL*/);
        int             i;
        
        kauth_cred_hash_mtx = lck_mtx_alloc_init(kauth_lck_grp, 0/*LCK_ATTR_NULL*/);
-       kauth_cred_table_size = kauth_cred_primes[kauth_cred_primes_index];
 
        /*allocate credential hash table */
        MALLOC(kauth_cred_table_anchor, struct kauth_cred_entry_head *, 
 
        /*allocate credential hash table */
        MALLOC(kauth_cred_table_anchor, struct kauth_cred_entry_head *, 
-                       (sizeof(struct kauth_cred_entry_head) * kauth_cred_table_size), 
+                       (sizeof(struct kauth_cred_entry_head) * KAUTH_CRED_TABLE_SIZE),
                        M_KAUTH, M_WAITOK | M_ZERO);
        if (kauth_cred_table_anchor == NULL)
                panic("startup: kauth_cred_init");
                        M_KAUTH, M_WAITOK | M_ZERO);
        if (kauth_cred_table_anchor == NULL)
                panic("startup: kauth_cred_init");
-       for (i = 0; i < kauth_cred_table_size; i++) {
+       for (i = 0; i < KAUTH_CRED_TABLE_SIZE; i++) {
                TAILQ_INIT(&kauth_cred_table_anchor[i]);
        }
 }
                TAILQ_INIT(&kauth_cred_table_anchor[i]);
        }
 }
@@ -3601,7 +3649,7 @@ kauth_cred_get_with_ref(void)
  * Returns:    (kauth_cred_t)                  Pointer to the process's
  *                                             newly referenced credential
  *
  * Returns:    (kauth_cred_t)                  Pointer to the process's
  *                                             newly referenced credential
  *
- * Locks:      PROC_LOCK is held before taking the reference and released
+ * Locks:      PROC_UCRED_LOCK is held before taking the reference and released
  *             after the refeence is taken to protect the p_ucred field of
  *             the process referred to by procp.
  *
  *             after the refeence is taken to protect the p_ucred field of
  *             the process referred to by procp.
  *
@@ -3623,10 +3671,10 @@ kauth_cred_proc_ref(proc_t procp)
 {
        kauth_cred_t    cred;
        
 {
        kauth_cred_t    cred;
        
-       proc_lock(procp);
+       proc_ucred_lock(procp);
        cred = proc_ucred(procp);
        kauth_cred_ref(cred);
        cred = proc_ucred(procp);
        kauth_cred_ref(cred);
-       proc_unlock(procp);
+       proc_ucred_unlock(procp);
        return(cred);
 }
 
        return(cred);
 }
 
@@ -4459,7 +4507,7 @@ int kauth_proc_label_update(struct proc *p, struct label *label)
 
                        DEBUG_CRED_CHANGE("kauth_proc_setlabel_unlocked CH(%d): %p/0x%08x -> %p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
 
 
                        DEBUG_CRED_CHANGE("kauth_proc_setlabel_unlocked CH(%d): %p/0x%08x -> %p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
 
-                       proc_lock(p);
+                       proc_ucred_lock(p);
                        /*
                         * We need to protect for a race where another thread
                         * also changed the credential after we took our
                        /*
                         * We need to protect for a race where another thread
                         * also changed the credential after we took our
@@ -4467,7 +4515,7 @@ int kauth_proc_label_update(struct proc *p, struct label *label)
                         * restart this again with the new cred.
                         */
                        if (p->p_ucred != my_cred) {
                         * restart this again with the new cred.
                         */
                        if (p->p_ucred != my_cred) {
-                               proc_unlock(p);
+                               proc_ucred_unlock(p);
                                kauth_cred_unref(&my_new_cred);
                                my_cred = kauth_cred_proc_ref(p);
                                /* try again */
                                kauth_cred_unref(&my_new_cred);
                                my_cred = kauth_cred_proc_ref(p);
                                /* try again */
@@ -4478,7 +4526,7 @@ int kauth_proc_label_update(struct proc *p, struct label *label)
                        PROC_UPDATE_CREDS_ONPROC(p);
 
                        mac_proc_set_enforce(p, MAC_ALL_ENFORCE);
                        PROC_UPDATE_CREDS_ONPROC(p);
 
                        mac_proc_set_enforce(p, MAC_ALL_ENFORCE);
-                       proc_unlock(p);
+                       proc_ucred_unlock(p);
                }
                break;
        }
                }
                break;
        }
@@ -4539,7 +4587,7 @@ kauth_proc_label_update_execve(struct proc *p, vfs_context_t ctx,
 
                        DEBUG_CRED_CHANGE("kauth_proc_label_update_execve_unlocked CH(%d): %p/0x%08x -> %p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
 
 
                        DEBUG_CRED_CHANGE("kauth_proc_label_update_execve_unlocked CH(%d): %p/0x%08x -> %p/0x%08x\n", p->p_pid, my_cred, my_cred->cr_flags, my_new_cred, my_new_cred->cr_flags);
 
-                       proc_lock(p);
+                       proc_ucred_lock(p);
                        /*
                         * We need to protect for a race where another thread
                         * also changed the credential after we took our
                        /*
                         * We need to protect for a race where another thread
                         * also changed the credential after we took our
@@ -4547,7 +4595,7 @@ kauth_proc_label_update_execve(struct proc *p, vfs_context_t ctx,
                         * restart this again with the new cred.
                         */
                        if (p->p_ucred != my_cred) {
                         * restart this again with the new cred.
                         */
                        if (p->p_ucred != my_cred) {
-                               proc_unlock(p);
+                               proc_ucred_unlock(p);
                                kauth_cred_unref(&my_new_cred);
                                my_cred = kauth_cred_proc_ref(p);
                                /* try again */
                                kauth_cred_unref(&my_new_cred);
                                my_cred = kauth_cred_proc_ref(p);
                                /* try again */
@@ -4557,7 +4605,7 @@ kauth_proc_label_update_execve(struct proc *p, vfs_context_t ctx,
                        /* update cred on proc */
                        PROC_UPDATE_CREDS_ONPROC(p);
                        mac_proc_set_enforce(p, MAC_ALL_ENFORCE);
                        /* update cred on proc */
                        PROC_UPDATE_CREDS_ONPROC(p);
                        mac_proc_set_enforce(p, MAC_ALL_ENFORCE);
-                       proc_unlock(p);
+                       proc_ucred_unlock(p);
                }
                break;
        }
                }
                break;
        }
@@ -5095,7 +5143,7 @@ kauth_cred_add(kauth_cred_t new_cred)
        KAUTH_CRED_HASH_LOCK_ASSERT();
 
        hash_key = kauth_cred_get_hashkey(new_cred);
        KAUTH_CRED_HASH_LOCK_ASSERT();
 
        hash_key = kauth_cred_get_hashkey(new_cred);
-       hash_key %= kauth_cred_table_size;
+       hash_key %= KAUTH_CRED_TABLE_SIZE;
 
        /* race fix - there is a window where another matching credential 
         * could have been inserted between the time this one was created and we
 
        /* race fix - there is a window where another matching credential 
         * could have been inserted between the time this one was created and we
@@ -5140,7 +5188,7 @@ kauth_cred_remove(kauth_cred_t cred)
        kauth_cred_t    found_cred;
 
        hash_key = kauth_cred_get_hashkey(cred);
        kauth_cred_t    found_cred;
 
        hash_key = kauth_cred_get_hashkey(cred);
-       hash_key %= kauth_cred_table_size;
+       hash_key %= KAUTH_CRED_TABLE_SIZE;
 
        /* Avoid race */
        if (cred->cr_ref < 1)
 
        /* Avoid race */
        if (cred->cr_ref < 1)
@@ -5200,7 +5248,7 @@ kauth_cred_find(kauth_cred_t cred)
 #endif
 
        hash_key = kauth_cred_get_hashkey(cred);
 #endif
 
        hash_key = kauth_cred_get_hashkey(cred);
-       hash_key %= kauth_cred_table_size;
+       hash_key %= KAUTH_CRED_TABLE_SIZE;
 
        /* Find cred in the credential hash table */
        TAILQ_FOREACH(found_cred, &kauth_cred_table_anchor[hash_key], cr_link) {
 
        /* Find cred in the credential hash table */
        TAILQ_FOREACH(found_cred, &kauth_cred_table_anchor[hash_key], cr_link) {
@@ -5325,7 +5373,7 @@ kauth_cred_hash_print(void)
                
        printf("\n\t kauth credential hash table statistics - current cred count %d \n", kauth_cred_count);
        /* count slot hits, misses, collisions, and max depth */
                
        printf("\n\t kauth credential hash table statistics - current cred count %d \n", kauth_cred_count);
        /* count slot hits, misses, collisions, and max depth */
-       for (i = 0; i < kauth_cred_table_size; i++) {
+       for (i = 0; i < KAUTH_CRED_TABLE_SIZE; i++) {
                printf("[%02d] ", i);
                j = 0;
                TAILQ_FOREACH(found_cred, &kauth_cred_table_anchor[i], cr_link) {
                printf("[%02d] ", i);
                j = 0;
                TAILQ_FOREACH(found_cred, &kauth_cred_table_anchor[i], cr_link) {
@@ -5510,7 +5558,7 @@ sysctl_dump_creds( __unused struct sysctl_oid *oidp, __unused void *arg1, __unus
                return (EPERM);
 
        /* calculate space needed */
                return (EPERM);
 
        /* calculate space needed */
-       for (i = 0; i < kauth_cred_table_size; i++) {
+       for (i = 0; i < KAUTH_CRED_TABLE_SIZE; i++) {
                TAILQ_FOREACH(found_cred, &kauth_cred_table_anchor[i], cr_link) {
                        counter++;
                }
                TAILQ_FOREACH(found_cred, &kauth_cred_table_anchor[i], cr_link) {
                        counter++;
                }
@@ -5531,7 +5579,7 @@ sysctl_dump_creds( __unused struct sysctl_oid *oidp, __unused void *arg1, __unus
        /* fill in creds to send back */
        nextp = cred_listp;
        space = 0;
        /* fill in creds to send back */
        nextp = cred_listp;
        space = 0;
-       for (i = 0; i < kauth_cred_table_size; i++) {
+       for (i = 0; i < KAUTH_CRED_TABLE_SIZE; i++) {
                TAILQ_FOREACH(found_cred, &kauth_cred_table_anchor[i], cr_link) {
                        nextp->credp = found_cred;
                        nextp->cr_ref = found_cred->cr_ref;
                TAILQ_FOREACH(found_cred, &kauth_cred_table_anchor[i], cr_link) {
                        nextp->credp = found_cred;
                        nextp->cr_ref = found_cred->cr_ref;