X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3903760236c30e3b5ace7a4eefac3a269d68957c..0a7de7458d150b5d4dffc935ba399be265ef0a1a:/osfmk/ipc/ipc_voucher.c?ds=sidebyside diff --git a/osfmk/ipc/ipc_voucher.c b/osfmk/ipc/ipc_voucher.c index ab0858c99..ff6da5605 100644 --- a/osfmk/ipc/ipc_voucher.c +++ b/osfmk/ipc/ipc_voucher.c @@ -67,11 +67,11 @@ static uint32_t ivht_count = 0; lck_spin_init(&ivht_lock_data, &ipc_lck_grp, &ipc_lck_attr) #define ivht_lock_destroy() \ lck_spin_destroy(&ivht_lock_data, &ipc_lck_grp) -#define ivht_lock() \ - lck_spin_lock(&ivht_lock_data) -#define ivht_lock_try() \ - lck_spin_try_lock(&ivht_lock_data) -#define ivht_unlock() \ +#define ivht_lock() \ + lck_spin_lock_grp(&ivht_lock_data, &ipc_lck_grp) +#define ivht_lock_try() \ + lck_spin_try_lock_grp(&ivht_lock_data, &ipc_lck_grp) +#define ivht_unlock() \ lck_spin_unlock(&ivht_lock_data) /* @@ -83,41 +83,37 @@ static uint32_t ivht_count = 0; */ static iv_index_t ivgt_keys_in_use = MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN; static ipc_voucher_global_table_element iv_global_table[MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN]; -static lck_spin_t ivgt_lock_data; +static lck_spin_t ivgt_lock_data; #define ivgt_lock_init() \ lck_spin_init(&ivgt_lock_data, &ipc_lck_grp, &ipc_lck_attr) #define ivgt_lock_destroy() \ lck_spin_destroy(&ivgt_lock_data, &ipc_lck_grp) -#define ivgt_lock() \ - lck_spin_lock(&ivgt_lock_data) -#define ivgt_lock_try() \ - lck_spin_try_lock(&ivgt_lock_data) -#define ivgt_unlock() \ +#define ivgt_lock() \ + lck_spin_lock_grp(&ivgt_lock_data, &ipc_lck_grp) +#define ivgt_lock_try() \ + lck_spin_try_lock_grp(&ivgt_lock_data, &ipc_lck_grp) +#define ivgt_unlock() \ lck_spin_unlock(&ivgt_lock_data) ipc_voucher_t iv_alloc(iv_index_t entries); void iv_dealloc(ipc_voucher_t iv, boolean_t unhash); -extern int thread_qos_from_pthread_priority(unsigned long, unsigned long *); -static inline iv_refs_t +os_refgrp_decl(static, iv_refgrp, "voucher", NULL); +os_refgrp_decl(static, ivac_refgrp, "voucher attribute control", NULL); + +static inline void iv_reference(ipc_voucher_t iv) { - iv_refs_t refs; - - refs = hw_atomic_add(&iv->iv_refs, 1); - return refs; + os_ref_retain(&iv->iv_refs); } static inline void iv_release(ipc_voucher_t iv) { - iv_refs_t refs; - - assert(0 < iv->iv_refs); - refs = hw_atomic_sub(&iv->iv_refs, 1); - if (0 == refs) + if (os_ref_release(&iv->iv_refs) == 0) { iv_dealloc(iv, TRUE); + } } /* @@ -159,32 +155,33 @@ static inline iv_index_t iv_key_to_index(mach_voucher_attr_key_t key) { if (MACH_VOUCHER_ATTR_KEY_ALL == key || - MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN < key) + MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN < key) { return IV_UNUSED_KEYINDEX; + } return (iv_index_t)key - 1; } static inline mach_voucher_attr_key_t iv_index_to_key(iv_index_t key_index) { - if (MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN > key_index) + if (MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN > key_index) { return iv_global_table[key_index].ivgte_key; + } return MACH_VOUCHER_ATTR_KEY_NONE; - } static void ivace_release(iv_index_t key_index, iv_index_t value_index); -static void ivace_lookup_values(iv_index_t key_index, iv_index_t value_index, - mach_voucher_attr_value_handle_array_t values, - mach_voucher_attr_value_handle_array_size_t *count); +static void ivace_lookup_values(iv_index_t key_index, iv_index_t value_index, + mach_voucher_attr_value_handle_array_t values, + mach_voucher_attr_value_handle_array_size_t *count); static iv_index_t iv_lookup(ipc_voucher_t, iv_index_t); - + static void ivgt_lookup(iv_index_t, - boolean_t, - ipc_voucher_attr_manager_t *, - ipc_voucher_attr_control_t *); + boolean_t, + ipc_voucher_attr_manager_t *, + ipc_voucher_attr_control_t *); static kern_return_t ipc_voucher_prepare_processing_recipe( @@ -197,7 +194,7 @@ ipc_voucher_prepare_processing_recipe( #if defined(MACH_VOUCHER_ATTR_KEY_USER_DATA) || defined(MACH_VOUCHER_ATTR_KEY_TEST) void user_data_attr_manager_init(void); -#endif +#endif void ipc_voucher_init(void) @@ -207,21 +204,22 @@ ipc_voucher_init(void) iv_index_t i; ipc_voucher_zone = zinit(sizeof(struct ipc_voucher), - ipc_voucher_max * sizeof(struct ipc_voucher), - sizeof(struct ipc_voucher), - "ipc vouchers"); + ipc_voucher_max * sizeof(struct ipc_voucher), + sizeof(struct ipc_voucher), + "ipc vouchers"); zone_change(ipc_voucher_zone, Z_NOENCRYPT, TRUE); ipc_voucher_attr_control_zone = zinit(sizeof(struct ipc_voucher_attr_control), - attr_manager_max * sizeof(struct ipc_voucher_attr_control), - sizeof(struct ipc_voucher_attr_control), - "ipc voucher attr controls"); + attr_manager_max * sizeof(struct ipc_voucher_attr_control), + sizeof(struct ipc_voucher_attr_control), + "ipc voucher attr controls"); zone_change(ipc_voucher_attr_control_zone, Z_NOENCRYPT, TRUE); /* initialize voucher hash */ ivht_lock_init(); - for (i = 0; i < IV_HASH_BUCKETS; i++) + for (i = 0; i < IV_HASH_BUCKETS; i++) { queue_init(&ivht_bucket[i]); + } /* initialize global table locking */ ivgt_lock_init(); @@ -239,10 +237,11 @@ iv_alloc(iv_index_t entries) iv = (ipc_voucher_t)zalloc(ipc_voucher_zone); - if (IV_NULL == iv) + if (IV_NULL == iv) { return IV_NULL; - - iv->iv_refs = 1; + } + + os_ref_init(&iv->iv_refs, &iv_refgrp); iv->iv_sum = 0; iv->iv_hash = 0; iv->iv_port = IP_NULL; @@ -264,10 +263,11 @@ iv_alloc(iv_index_t entries) } /* initialize the table entries */ - for (i=0; i < iv->iv_table_size; i++) + for (i = 0; i < iv->iv_table_size; i++) { iv->iv_table[i] = IV_UNUSED_VALINDEX; - - return (iv); + } + + return iv; } /* @@ -279,9 +279,9 @@ iv_alloc(iv_index_t entries) * they are immutable once references are distributed. */ static void -iv_set(ipc_voucher_t iv, - iv_index_t key_index, - iv_index_t value_index) +iv_set(ipc_voucher_t iv, + iv_index_t key_index, + iv_index_t value_index) { assert(key_index < iv->iv_table_size); iv->iv_table[key_index] = value_index; @@ -298,17 +298,18 @@ iv_dealloc(ipc_voucher_t iv, boolean_t unhash) */ if (unhash) { ivht_lock(); - assert(0 == iv->iv_refs); + assert(os_ref_get_count(&iv->iv_refs) == 0); assert(IV_HASH_BUCKETS > iv->iv_hash); queue_remove(&ivht_bucket[iv->iv_hash], iv, ipc_voucher_t, iv_hash_link); ivht_count--; ivht_unlock(); - KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_VOUCHER_DESTROY) | DBG_FUNC_NONE, - VM_KERNEL_ADDRPERM((uintptr_t)iv), 0, ivht_count, 0, 0); - - } else - assert(0 == --iv->iv_refs); + KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_VOUCHER_DESTROY) | DBG_FUNC_NONE, + VM_KERNEL_ADDRPERM((uintptr_t)iv), 0, ivht_count, 0, 0); + } else { + os_ref_count_t cnt __assert_only = os_ref_release(&iv->iv_refs); + assert(cnt == 0); + } /* * if a port was allocated for this voucher, @@ -330,10 +331,11 @@ iv_dealloc(ipc_voucher_t iv, boolean_t unhash) iv_set(iv, i, ~0); #endif } - - if (iv->iv_table != iv->iv_inline_table) - kfree(iv->iv_table, - iv->iv_table_size * sizeof(*iv->iv_table)); + + if (iv->iv_table != iv->iv_inline_table) { + kfree(iv->iv_table, + iv->iv_table_size * sizeof(*iv->iv_table)); + } zfree(ipc_voucher_zone, iv); } @@ -349,8 +351,9 @@ iv_dealloc(ipc_voucher_t iv, boolean_t unhash) static inline iv_index_t iv_lookup(ipc_voucher_t iv, iv_index_t key_index) { - if (key_index < iv->iv_table_size) + if (key_index < iv->iv_table_size) { return iv->iv_table[key_index]; + } return IV_UNUSED_VALINDEX; } @@ -369,7 +372,7 @@ iv_lookup(ipc_voucher_t iv, iv_index_t key_index) */ uintptr_t unsafe_convert_port_to_voucher( - ipc_port_t port) + ipc_port_t port) { if (IP_VALID(port)) { uintptr_t voucher = (uintptr_t) port->ip_kobject; @@ -379,8 +382,9 @@ unsafe_convert_port_to_voucher( * port, and if it is a true voucher port, that reference * keeps the voucher bound to the port (and active). */ - if (ip_kotype(port) == IKOT_VOUCHER) - return (voucher); + if (ip_kotype(port) == IKOT_VOUCHER) { + return voucher; + } } return (uintptr_t)IV_NULL; } @@ -397,7 +401,7 @@ unsafe_convert_port_to_voucher( */ ipc_voucher_t convert_port_to_voucher( - ipc_port_t port) + ipc_port_t port) { if (IP_VALID(port)) { ipc_voucher_t voucher = (ipc_voucher_t) port->ip_kobject; @@ -407,13 +411,14 @@ convert_port_to_voucher( * port, and if it is a true voucher port, that reference * keeps the voucher bound to the port (and active). */ - if (ip_kotype(port) != IKOT_VOUCHER) + if (ip_kotype(port) != IKOT_VOUCHER) { return IV_NULL; + } assert(ip_active(port)); ipc_voucher_reference(voucher); - return (voucher); + return voucher; } return IV_NULL; } @@ -429,7 +434,7 @@ convert_port_to_voucher( ipc_voucher_t convert_port_name_to_voucher( - mach_port_name_t voucher_name) + mach_port_name_t voucher_name) { ipc_voucher_t iv; kern_return_t kr; @@ -437,8 +442,9 @@ convert_port_name_to_voucher( if (MACH_PORT_VALID(voucher_name)) { kr = ipc_port_translate_send(current_space(), voucher_name, &port); - if (KERN_SUCCESS != kr) + if (KERN_SUCCESS != kr) { return IV_NULL; + } iv = convert_port_to_voucher(port); ip_unlock(port); @@ -451,20 +457,19 @@ convert_port_name_to_voucher( void ipc_voucher_reference(ipc_voucher_t voucher) { - iv_refs_t refs; - - if (IPC_VOUCHER_NULL == voucher) + if (IPC_VOUCHER_NULL == voucher) { return; + } - refs = iv_reference(voucher); - assert(1 < refs); + iv_reference(voucher); } void ipc_voucher_release(ipc_voucher_t voucher) { - if (IPC_VOUCHER_NULL != voucher) + if (IPC_VOUCHER_NULL != voucher) { iv_release(voucher); + } } /* @@ -473,7 +478,7 @@ ipc_voucher_release(ipc_voucher_t voucher) * Called whenever the Mach port system detects no-senders * on the voucher port. * - * Each time the send-right count goes positive, a no-senders + * Each time the send-right count goes positive, a no-senders * notification is armed (and a voucher reference is donated). * So, each notification that comes in must release a voucher * reference. If more send rights have been added since it @@ -500,12 +505,13 @@ ipc_voucher_notify(mach_msg_header_t *msg) ipc_port_t convert_voucher_to_port(ipc_voucher_t voucher) { - ipc_port_t port, send; + ipc_port_t port, send; - if (IV_NULL == voucher) - return (IP_NULL); + if (IV_NULL == voucher) { + return IP_NULL; + } - assert(0 < voucher->iv_refs); + assert(os_ref_get_count(&voucher->iv_refs) > 0); /* create a port if needed */ port = voucher->iv_port; @@ -522,7 +528,7 @@ convert_voucher_to_port(ipc_voucher_t voucher) assert(port->ip_kobject == (ipc_kobject_t)voucher); } } - + ip_lock(port); assert(ip_active(port)); send = ipc_port_make_send_locked(port); @@ -540,7 +546,7 @@ convert_voucher_to_port(ipc_voucher_t voucher) ip_unlock(port); ipc_voucher_release(voucher); } - return (send); + return send; } #define ivace_reset_data(ivace_elem, next_index) { \ @@ -576,32 +582,33 @@ ivac_alloc(iv_index_t key_index) ivac = (ipc_voucher_attr_control_t)zalloc(ipc_voucher_attr_control_zone); - if (IVAC_NULL == ivac) + if (IVAC_NULL == ivac) { return IVAC_NULL; - - ivac->ivac_refs = 1; + } + + os_ref_init(&ivac->ivac_refs, &ivac_refgrp); ivac->ivac_is_growing = FALSE; ivac->ivac_port = IP_NULL; /* start with just the inline table */ - table = (ivac_entry_t) kalloc(IVAC_ENTRIES_MIN * sizeof(ivac_entry)); + table = (ivac_entry_t) kalloc(IVAC_ENTRIES_MIN * sizeof(ivac_entry)); ivac->ivac_table = table; ivac->ivac_table_size = IVAC_ENTRIES_MIN; ivac->ivac_init_table_size = IVAC_ENTRIES_MIN; for (i = 0; i < ivac->ivac_table_size; i++) { - ivace_reset_data(&table[i], i+1); + ivace_reset_data(&table[i], i + 1); } /* the default table entry is never on freelist */ table[0].ivace_next = IV_HASH_END; table[0].ivace_free = FALSE; - table[i-1].ivace_next = IV_FREELIST_END; + table[i - 1].ivace_next = IV_FREELIST_END; ivac->ivac_freelist = 1; ivac_lock_init(ivac); ivac->ivac_key_index = key_index; - return (ivac); + return ivac; } - + void ivac_dealloc(ipc_voucher_attr_control_t ivac) @@ -617,7 +624,7 @@ ivac_dealloc(ipc_voucher_attr_control_t ivac) * that the reference count is still zero. */ ivgt_lock(); - if (ivac->ivac_refs > 0) { + if (os_ref_get_count(&ivac->ivac_refs) > 0) { ivgt_unlock(); return; } @@ -632,8 +639,9 @@ ivac_dealloc(ipc_voucher_attr_control_t ivac) ivgt_unlock(); /* release the reference held on the resource manager */ - if (IVAM_NULL != ivam) + if (IVAM_NULL != ivam) { (ivam->ivam_release)(ivam); + } /* * if a port was allocated for this voucher, @@ -654,9 +662,11 @@ ivac_dealloc(ipc_voucher_attr_control_t ivac) * table. */ #ifdef MACH_DEBUG - for (i = 0; i < ivac->ivac_table_size; i++) - if (ivac->ivac_table[i].ivace_refs != 0) + for (i = 0; i < ivac->ivac_table_size; i++) { + if (ivac->ivac_table[i].ivace_refs != 0) { panic("deallocing a resource manager with live refs to its attr values\n"); + } + } #endif kfree(ivac->ivac_table, ivac->ivac_table_size * sizeof(*ivac->ivac_table)); ivac_lock_destroy(ivac); @@ -686,7 +696,7 @@ ipc_voucher_attr_control_release(ipc_voucher_attr_control_t control) */ ipc_voucher_attr_control_t convert_port_to_voucher_attr_control( - ipc_port_t port) + ipc_port_t port) { if (IP_VALID(port)) { ipc_voucher_attr_control_t ivac = (ipc_voucher_attr_control_t) port->ip_kobject; @@ -697,13 +707,14 @@ convert_port_to_voucher_attr_control( * that reference keeps the voucher bound to the port * (and active). */ - if (ip_kotype(port) != IKOT_VOUCHER_ATTR_CONTROL) + if (ip_kotype(port) != IKOT_VOUCHER_ATTR_CONTROL) { return IVAC_NULL; + } assert(ip_active(port)); ivac_reference(ivac); - return (ivac); + return ivac; } return IVAC_NULL; } @@ -736,10 +747,11 @@ ipc_voucher_attr_control_notify(mach_msg_header_t *msg) ipc_port_t convert_voucher_attr_control_to_port(ipc_voucher_attr_control_t control) { - ipc_port_t port, send; + ipc_port_t port, send; - if (IVAC_NULL == control) - return (IP_NULL); + if (IVAC_NULL == control) { + return IP_NULL; + } /* create a port if needed */ port = control->ivac_port; @@ -756,8 +768,9 @@ convert_voucher_attr_control_to_port(ipc_voucher_attr_control_t control) assert(ip_kotype(port) == IKOT_VOUCHER_ATTR_CONTROL); assert(port->ip_kobject == (ipc_kobject_t)control); } - } else + } else { ip_lock(port); + } assert(ip_active(port)); send = ipc_port_make_send_locked(port); @@ -775,7 +788,7 @@ convert_voucher_attr_control_to_port(ipc_voucher_attr_control_t control) ip_unlock(port); ivac_release(control); } - return (send); + return send; } /* @@ -783,10 +796,10 @@ convert_voucher_attr_control_to_port(ipc_voucher_attr_control_t control) */ static void ivace_lookup_values( - iv_index_t key_index, - iv_index_t value_index, - mach_voucher_attr_value_handle_array_t values, - mach_voucher_attr_value_handle_array_size_t *count) + iv_index_t key_index, + iv_index_t value_index, + mach_voucher_attr_value_handle_array_t values, + mach_voucher_attr_value_handle_array_size_t *count) { ipc_voucher_attr_control_t ivac; ivac_entry_t ivace; @@ -850,19 +863,19 @@ ivac_grow_table(ipc_voucher_attr_control_t ivac) assert(new_size < IVAC_ENTRIES_MAX); new_table = kalloc(sizeof(ivac_entry) * new_size); - if (!new_table){ + if (!new_table) { panic("Failed to grow ivac table to size %d\n", new_size); return; } /* setup the free list for new entries */ for (i = old_size; i < new_size; i++) { - ivace_reset_data(&new_table[i], i+1); + ivace_reset_data(&new_table[i], i + 1); } ivac_lock(ivac); - - for (i = 0; i < ivac->ivac_table_size; i++){ + + for (i = 0; i < ivac->ivac_table_size; i++) { ivace_copy_data(&ivac->ivac_table[i], &new_table[i]); } @@ -870,14 +883,14 @@ ivac_grow_table(ipc_voucher_attr_control_t ivac) ivac->ivac_table = new_table; ivac->ivac_table_size = new_size; - + /* adding new free entries at head of freelist */ ivac->ivac_table[new_size - 1].ivace_next = ivac->ivac_freelist; ivac->ivac_freelist = old_size; ivac->ivac_is_growing = 0; ivac_wakeup(ivac); - if (old_table){ + if (old_table) { ivac_unlock(ivac); kfree(old_table, old_size * sizeof(ivac_entry)); ivac_lock(ivac); @@ -893,14 +906,15 @@ ivac_grow_table(ipc_voucher_attr_control_t ivac) */ static void ivace_reference_by_index( - iv_index_t key_index, - iv_index_t val_index) + iv_index_t key_index, + iv_index_t val_index) { ipc_voucher_attr_control_t ivac; ivac_entry_t ivace; - if (IV_UNUSED_VALINDEX == val_index) + if (IV_UNUSED_VALINDEX == val_index) { return; + } ivgt_lookup(key_index, FALSE, NULL, &ivac); assert(IVAC_NULL != ivac); @@ -931,8 +945,8 @@ ivace_reference_by_index( */ static iv_index_t ivace_reference_by_value( - ipc_voucher_attr_control_t ivac, - mach_voucher_attr_value_handle_t value, + ipc_voucher_attr_control_t ivac, + mach_voucher_attr_value_handle_t value, mach_voucher_attr_value_flags_t flag) { ivac_entry_t ivace = IVACE_NULL; @@ -943,7 +957,7 @@ ivace_reference_by_value( return IV_UNUSED_VALINDEX; } - ivac_lock(ivac); + ivac_lock(ivac); restart: hash_index = IV_HASH_VAL(ivac->ivac_init_table_size, value); index = ivac->ivac_table[hash_index].ivace_index; @@ -952,15 +966,16 @@ restart: ivace = &ivac->ivac_table[index]; assert(!ivace->ivace_free); - if (ivace->ivace_value == value) + if (ivace->ivace_value == value) { break; + } assert(ivace->ivace_next != index); index = ivace->ivace_next; } /* found it? */ - if (index != IV_HASH_END) { + if (index != IV_HASH_END) { /* only add reference on non-persistent value */ if (!ivace->ivace_persist) { ivace->ivace_refs++; @@ -1005,11 +1020,12 @@ restart: * Release a reference on the given pair. * * Conditions: called with nothing locked, as it may cause - * callouts and/or messaging to the resource + * callouts and/or messaging to the resource * manager. */ -static void ivace_release( - iv_index_t key_index, +static void +ivace_release( + iv_index_t key_index, iv_index_t value_index) { ipc_voucher_attr_control_t ivac; @@ -1022,8 +1038,9 @@ static void ivace_release( kern_return_t kr; /* cant release the default value */ - if (IV_UNUSED_VALINDEX == value_index) + if (IV_UNUSED_VALINDEX == value_index) { return; + } ivgt_lookup(key_index, FALSE, &ivam, &ivac); assert(IVAC_NULL != ivac); @@ -1063,7 +1080,7 @@ static void ivace_release( ivace->ivace_releasing = TRUE; value = ivace->ivace_value; - redrive: +redrive: assert(value == ivace->ivace_value); assert(!ivace->ivace_free); made = ivace->ivace_made; @@ -1085,18 +1102,20 @@ static void ivace_release( * re-drive the release. */ if (ivace->ivace_made != made) { - if (KERN_SUCCESS == kr) + if (KERN_SUCCESS == kr) { ivace->ivace_made -= made; + } - if (0 == ivace->ivace_refs) + if (0 == ivace->ivace_refs) { goto redrive; + } ivace->ivace_releasing = FALSE; ivac_unlock(ivac); return; } else { /* - * If the manager returned FAILURE, someone took a + * If the manager returned FAILURE, someone took a * reference on the value but have not updated the ivace, * release the lock and return since thread who got * the new reference will update the ivace and will have @@ -1160,16 +1179,17 @@ static void ivace_release( */ static void ivgt_lookup(iv_index_t key_index, - boolean_t take_reference, - ipc_voucher_attr_manager_t *manager, - ipc_voucher_attr_control_t *control) + boolean_t take_reference, + ipc_voucher_attr_manager_t *manager, + ipc_voucher_attr_control_t *control) { ipc_voucher_attr_control_t ivac; if (key_index < MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN) { ivgt_lock(); - if (NULL != manager) + if (NULL != manager) { *manager = iv_global_table[key_index].ivgte_manager; + } ivac = iv_global_table[key_index].ivgte_control; if (IVAC_NULL != ivac) { assert(key_index == ivac->ivac_key_index); @@ -1179,18 +1199,21 @@ ivgt_lookup(iv_index_t key_index, } } ivgt_unlock(); - if (NULL != control) + if (NULL != control) { *control = ivac; + } } else { - if (NULL != manager) + if (NULL != manager) { *manager = IVAM_NULL; - if (NULL != control) + } + if (NULL != control) { *control = IVAC_NULL; + } } } /* - * Routine: ipc_replace_voucher_value + * Routine: ipc_replace_voucher_value * Purpose: * Replace the value with the results of * running the supplied command through the resource @@ -1201,11 +1224,11 @@ ivgt_lookup(iv_index_t key_index, */ static kern_return_t ipc_replace_voucher_value( - ipc_voucher_t voucher, - mach_voucher_attr_key_t key, - mach_voucher_attr_recipe_command_t command, - ipc_voucher_t prev_voucher, - mach_voucher_attr_content_t content, + ipc_voucher_t voucher, + mach_voucher_attr_key_t key, + mach_voucher_attr_recipe_command_t command, + ipc_voucher_t prev_voucher, + mach_voucher_attr_content_t content, mach_voucher_attr_content_size_t content_size) { mach_voucher_attr_value_handle_t previous_vals[MACH_VOUCHER_ATTR_VALUE_MAX_NESTED]; @@ -1220,15 +1243,16 @@ ipc_replace_voucher_value( iv_index_t val_index; iv_index_t key_index; kern_return_t kr; - + /* * Get the manager for this key_index. * Returns a reference on the control. */ key_index = iv_key_to_index(key); ivgt_lookup(key_index, TRUE, &ivam, &ivac); - if (IVAM_NULL == ivam) + if (IVAM_NULL == ivam) { return KERN_INVALID_ARGUMENT; + } /* save the current value stored in the forming voucher */ save_val_index = iv_lookup(voucher, key_index); @@ -1240,26 +1264,27 @@ ipc_replace_voucher_value( * in the forming voucher. */ prev_val_index = (IV_NULL != prev_voucher) ? - iv_lookup(prev_voucher, key_index) : - save_val_index; + iv_lookup(prev_voucher, key_index) : + save_val_index; ivace_lookup_values(key_index, prev_val_index, - previous_vals, &previous_vals_count); + previous_vals, &previous_vals_count); /* Call out to resource manager to get new value */ new_value_voucher = IV_NULL; kr = (ivam->ivam_get_value)( - ivam, key, command, - previous_vals, previous_vals_count, - content, content_size, - &new_value, &new_flag, &new_value_voucher); + ivam, key, command, + previous_vals, previous_vals_count, + content, content_size, + &new_value, &new_flag, &new_value_voucher); if (KERN_SUCCESS != kr) { ivac_release(ivac); return kr; } /* TODO: value insertion from returned voucher */ - if (IV_NULL != new_value_voucher) + if (IV_NULL != new_value_voucher) { iv_release(new_value_voucher); + } /* * Find or create a slot in the table associated @@ -1277,12 +1302,12 @@ ipc_replace_voucher_value( * as was there before. */ ivace_release(key_index, save_val_index); - + return KERN_SUCCESS; } /* - * Routine: ipc_directly_replace_voucher_value + * Routine: ipc_directly_replace_voucher_value * Purpose: * Replace the value with the value-handle * supplied directly by the attribute manager. @@ -1293,24 +1318,25 @@ ipc_replace_voucher_value( */ static kern_return_t ipc_directly_replace_voucher_value( - ipc_voucher_t voucher, - mach_voucher_attr_key_t key, - mach_voucher_attr_value_handle_t new_value) + ipc_voucher_t voucher, + mach_voucher_attr_key_t key, + mach_voucher_attr_value_handle_t new_value) { ipc_voucher_attr_manager_t ivam; ipc_voucher_attr_control_t ivac; iv_index_t save_val_index; iv_index_t val_index; iv_index_t key_index; - + /* * Get the manager for this key_index. * Returns a reference on the control. */ key_index = iv_key_to_index(key); ivgt_lookup(key_index, TRUE, &ivam, &ivac); - if (IVAM_NULL == ivam) + if (IVAM_NULL == ivam) { return KERN_INVALID_ARGUMENT; + } /* save the current value stored in the forming voucher */ save_val_index = iv_lookup(voucher, key_index); @@ -1322,7 +1348,7 @@ ipc_directly_replace_voucher_value( * we find a matching existing value. */ val_index = ivace_reference_by_value(ivac, new_value, - MACH_VOUCHER_ATTR_VALUE_FLAGS_NONE); + MACH_VOUCHER_ATTR_VALUE_FLAGS_NONE); iv_set(voucher, key_index, val_index); /* @@ -1332,26 +1358,25 @@ ipc_directly_replace_voucher_value( * as was there before. */ ivace_release(key_index, save_val_index); - + return KERN_SUCCESS; } static kern_return_t ipc_execute_voucher_recipe_command( - ipc_voucher_t voucher, - mach_voucher_attr_key_t key, - mach_voucher_attr_recipe_command_t command, - ipc_voucher_t prev_iv, - mach_voucher_attr_content_t content, - mach_voucher_attr_content_size_t content_size, - boolean_t key_priv) + ipc_voucher_t voucher, + mach_voucher_attr_key_t key, + mach_voucher_attr_recipe_command_t command, + ipc_voucher_t prev_iv, + mach_voucher_attr_content_t content, + mach_voucher_attr_content_size_t content_size, + boolean_t key_priv) { iv_index_t prev_val_index; iv_index_t val_index; kern_return_t kr; switch (command) { - /* * MACH_VOUCHER_ATTR_COPY * Copy the attribute(s) from the previous voucher to the new @@ -1360,22 +1385,24 @@ ipc_execute_voucher_recipe_command( * voucher. */ case MACH_VOUCHER_ATTR_COPY: - + /* no recipe data on a copy */ - if (0 < content_size) + if (0 < content_size) { return KERN_INVALID_ARGUMENT; + } /* nothing to copy from? - done */ - if (IV_NULL == prev_iv) + if (IV_NULL == prev_iv) { return KERN_SUCCESS; + } if (MACH_VOUCHER_ATTR_KEY_ALL == key) { iv_index_t limit, j; /* reconcile possible difference in voucher sizes */ limit = (prev_iv->iv_table_size < voucher->iv_table_size) ? - prev_iv->iv_table_size : - voucher->iv_table_size; + prev_iv->iv_table_size : + voucher->iv_table_size; /* wildcard matching */ for (j = 0; j < limit; j++) { @@ -1393,8 +1420,9 @@ ipc_execute_voucher_recipe_command( /* copy just one key */ key_index = iv_key_to_index(key); - if (ivgt_keys_in_use < key_index) + if (ivgt_keys_in_use < key_index) { return KERN_INVALID_ARGUMENT; + } /* release old value being replaced */ val_index = iv_lookup(voucher, key_index); @@ -1417,16 +1445,17 @@ ipc_execute_voucher_recipe_command( */ case MACH_VOUCHER_ATTR_REMOVE: /* no recipe data on a remove */ - if (0 < content_size) + if (0 < content_size) { return KERN_INVALID_ARGUMENT; + } if (MACH_VOUCHER_ATTR_KEY_ALL == key) { iv_index_t limit, j; /* reconcile possible difference in voucher sizes */ limit = (IV_NULL == prev_iv) ? voucher->iv_table_size : - ((prev_iv->iv_table_size < voucher->iv_table_size) ? - prev_iv->iv_table_size : voucher->iv_table_size); + ((prev_iv->iv_table_size < voucher->iv_table_size) ? + prev_iv->iv_table_size : voucher->iv_table_size); /* wildcard matching */ for (j = 0; j < limit; j++) { @@ -1435,8 +1464,9 @@ ipc_execute_voucher_recipe_command( /* If not matched in previous, skip */ if (IV_NULL != prev_iv) { prev_val_index = iv_lookup(prev_iv, j); - if (val_index != prev_val_index) + if (val_index != prev_val_index) { continue; + } } /* release and clear */ ivace_release(j, val_index); @@ -1447,16 +1477,18 @@ ipc_execute_voucher_recipe_command( /* copy just one key */ key_index = iv_key_to_index(key); - if (ivgt_keys_in_use < key_index) + if (ivgt_keys_in_use < key_index) { return KERN_INVALID_ARGUMENT; + } val_index = iv_lookup(voucher, key_index); /* If not matched in previous, skip */ if (IV_NULL != prev_iv) { prev_val_index = iv_lookup(prev_iv, key_index); - if (val_index != prev_val_index) + if (val_index != prev_val_index) { break; + } } /* release and clear */ @@ -1475,17 +1507,20 @@ ipc_execute_voucher_recipe_command( if (key_priv) { mach_voucher_attr_value_handle_t new_value; - if (sizeof(mach_voucher_attr_value_handle_t) != content_size) + if (sizeof(mach_voucher_attr_value_handle_t) != content_size) { return KERN_INVALID_ARGUMENT; - + } + new_value = *(mach_voucher_attr_value_handle_t *)(void *)content; kr = ipc_directly_replace_voucher_value(voucher, - key, - new_value); - if (KERN_SUCCESS != kr) + key, + new_value); + if (KERN_SUCCESS != kr) { return kr; - } else + } + } else { return KERN_INVALID_CAPABILITY; + } break; /* @@ -1493,19 +1528,20 @@ ipc_execute_voucher_recipe_command( * Redeem the attribute(s) from the previous voucher for a possibly * new value in the new voucher. A wildcard key is an acceptable value, * indicating a desire to redeem all the values. - */ + */ case MACH_VOUCHER_ATTR_REDEEM: if (MACH_VOUCHER_ATTR_KEY_ALL == key) { iv_index_t limit, j; /* reconcile possible difference in voucher sizes */ - if (IV_NULL != prev_iv) + if (IV_NULL != prev_iv) { limit = (prev_iv->iv_table_size < voucher->iv_table_size) ? - prev_iv->iv_table_size : - voucher->iv_table_size; - else + prev_iv->iv_table_size : + voucher->iv_table_size; + } else { limit = voucher->iv_table_size; + } /* wildcard matching */ for (j = 0; j < limit; j++) { @@ -1514,22 +1550,24 @@ ipc_execute_voucher_recipe_command( j_key = iv_index_to_key(j); /* skip non-existent managers */ - if (MACH_VOUCHER_ATTR_KEY_NONE == j_key) + if (MACH_VOUCHER_ATTR_KEY_NONE == j_key) { continue; + } /* get the new value from redeem (skip empty previous) */ kr = ipc_replace_voucher_value(voucher, - j_key, - command, - prev_iv, - content, - content_size); - if (KERN_SUCCESS != kr) + j_key, + command, + prev_iv, + content, + content_size); + if (KERN_SUCCESS != kr) { return kr; + } } break; } - /* fall thru for single key redemption */ + /* fall thru for single key redemption */ /* * DEFAULT: @@ -1539,13 +1577,14 @@ ipc_execute_voucher_recipe_command( */ default: kr = ipc_replace_voucher_value(voucher, - key, - command, - prev_iv, - content, - content_size); - if (KERN_SUCCESS != kr) + key, + command, + prev_iv, + content, + content_size); + if (KERN_SUCCESS != kr) { return kr; + } break; } @@ -1553,7 +1592,7 @@ ipc_execute_voucher_recipe_command( } /* - * Routine: iv_checksum + * Routine: iv_checksum * Purpose: * Compute the voucher sum. This is more position- * relevant than many other checksums - important for @@ -1567,13 +1606,13 @@ iv_checksum(ipc_voucher_t voucher, boolean_t *emptyp) boolean_t empty = TRUE; if (0 < voucher->iv_table_size) { iv_index_t i = voucher->iv_table_size - 1; - + do { iv_index_t v = voucher->iv_table[i]; - c = c << 3 | c >> (32 - 3); /* rotate */ - c = ~c; /* invert */ + c = c << 3 | c >> (32 - 3); /* rotate */ + c = ~c; /* invert */ if (0 < v) { - c += v; /* add in */ + c += v; /* add in */ empty = FALSE; } } while (0 < i--); @@ -1583,7 +1622,7 @@ iv_checksum(ipc_voucher_t voucher, boolean_t *emptyp) } /* - * Routine: iv_dedup + * Routine: iv_dedup * Purpose: * See if the set of values represented by this new voucher * already exist in another voucher. If so return a reference @@ -1598,7 +1637,7 @@ static ipc_voucher_t iv_dedup(ipc_voucher_t new_iv) { boolean_t empty; - iv_index_t sum; + iv_index_t sum; iv_index_t hash; ipc_voucher_t iv; @@ -1617,40 +1656,41 @@ iv_dedup(ipc_voucher_t new_iv) assert(iv->iv_hash == hash); /* if not already deallocating and sums match... */ - if (0 < iv->iv_refs && iv->iv_sum == sum) { - iv_refs_t refs; + if ((os_ref_get_count(&iv->iv_refs) > 0) && (iv->iv_sum == sum)) { iv_index_t i; assert(iv->iv_table_size <= new_iv->iv_table_size); - + /* and common entries match... */ - for (i = 0; i < iv->iv_table_size; i++) - if (iv->iv_table[i] != new_iv->iv_table[i]) + for (i = 0; i < iv->iv_table_size; i++) { + if (iv->iv_table[i] != new_iv->iv_table[i]) { break; - if (i < iv->iv_table_size) + } + } + if (i < iv->iv_table_size) { continue; + } /* and all extra entries in new one are unused... */ - while (i < new_iv->iv_table_size) - if (new_iv->iv_table[i++] != IV_UNUSED_VALINDEX) + while (i < new_iv->iv_table_size) { + if (new_iv->iv_table[i++] != IV_UNUSED_VALINDEX) { break; - if (i < new_iv->iv_table_size) + } + } + if (i < new_iv->iv_table_size) { continue; + } /* ... we found a match... */ /* can we get a ref before it hits 0 * - * This is thread safe. The reference is just an atomic - * add. If the reference count is zero when we adjust it, - * no other thread can have a reference to the voucher. + * This is thread safe. If the reference count is zero before we + * adjust it, no other thread can have a reference to the voucher. * The dealloc code requires holding the ivht_lock, so * the voucher cannot be yanked out from under us. */ - refs = iv_reference(iv); - if (1 == refs) { - /* drats! going away. Put back to zero */ - iv->iv_refs = 0; + if (!os_ref_retain_try(&iv->iv_refs)) { continue; } @@ -1720,28 +1760,25 @@ iv_dedup(ipc_voucher_t new_iv) size_t remainder = payload_size % PAYLOAD_PER_TRACEPOINT; if (remainder) { bzero((uint8_t*)payload + payload_size, - PAYLOAD_PER_TRACEPOINT - remainder); + PAYLOAD_PER_TRACEPOINT - remainder); } } - KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_VOUCHER_CREATE) | DBG_FUNC_NONE, - voucher_addr, - new_iv->iv_table_size, ivht_count, payload_size, 0); + KDBG(MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_VOUCHER_CREATE), + voucher_addr, new_iv->iv_table_size, ivht_count, + payload_size); uintptr_t index = 0; while (attr_tracepoints_needed--) { - KERNEL_DEBUG_CONSTANT1(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_VOUCHER_CREATE_ATTR_DATA) | DBG_FUNC_NONE, - payload[index], - payload[index+1], - payload[index+2], - payload[index+3], - voucher_addr); + KDBG(MACHDBG_CODE(DBG_MACH_IPC, + MACH_IPC_VOUCHER_CREATE_ATTR_DATA), payload[index], + payload[index + 1], payload[index + 2], + payload[index + 3]); index += 4; } } else { - KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_VOUCHER_CREATE) | DBG_FUNC_NONE, - voucher_addr, - new_iv->iv_table_size, ivht_count, 0, 0); + KDBG(MACHDBG_CODE(DBG_MACH_IPC, MACH_IPC_VOUCHER_CREATE), + voucher_addr, new_iv->iv_table_size, ivht_count); } } #endif /* KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD */ @@ -1750,7 +1787,7 @@ iv_dedup(ipc_voucher_t new_iv) } /* - * Routine: ipc_create_mach_voucher + * Routine: ipc_create_mach_voucher * Purpose: * Create a new mach voucher and initialize it with the * value(s) created by having the appropriate resource @@ -1763,9 +1800,9 @@ iv_dedup(ipc_voucher_t new_iv) */ kern_return_t ipc_create_mach_voucher( - ipc_voucher_attr_raw_recipe_array_t recipes, - ipc_voucher_attr_raw_recipe_array_size_t recipe_size, - ipc_voucher_t *new_voucher) + ipc_voucher_attr_raw_recipe_array_t recipes, + ipc_voucher_attr_raw_recipe_array_size_t recipe_size, + ipc_voucher_t *new_voucher) { ipc_voucher_attr_recipe_t sub_recipe; ipc_voucher_attr_recipe_size_t recipe_used = 0; @@ -1780,12 +1817,12 @@ ipc_create_mach_voucher( /* allocate a voucher */ voucher = iv_alloc(ivgt_keys_in_use); - if (IV_NULL == voucher) + if (IV_NULL == voucher) { return KERN_RESOURCE_SHORTAGE; + } /* iterate over the recipe items */ while (0 < recipe_size - recipe_used) { - if (recipe_size - recipe_used < sizeof(*sub_recipe)) { kr = KERN_INVALID_ARGUMENT; break; @@ -1800,14 +1837,15 @@ ipc_create_mach_voucher( recipe_used += sizeof(*sub_recipe) + sub_recipe->content_size; kr = ipc_execute_voucher_recipe_command(voucher, - sub_recipe->key, - sub_recipe->command, - sub_recipe->previous_voucher, - sub_recipe->content, - sub_recipe->content_size, - FALSE); - if (KERN_SUCCESS != kr) + sub_recipe->key, + sub_recipe->command, + sub_recipe->previous_voucher, + sub_recipe->content, + sub_recipe->content_size, + FALSE); + if (KERN_SUCCESS != kr) { break; + } } if (KERN_SUCCESS == kr) { @@ -1820,7 +1858,7 @@ ipc_create_mach_voucher( } /* - * Routine: ipc_voucher_attr_control_create_mach_voucher + * Routine: ipc_voucher_attr_control_create_mach_voucher * Purpose: * Create a new mach voucher and initialize it with the * value(s) created by having the appropriate resource @@ -1841,10 +1879,10 @@ ipc_create_mach_voucher( */ kern_return_t ipc_voucher_attr_control_create_mach_voucher( - ipc_voucher_attr_control_t control, - ipc_voucher_attr_raw_recipe_array_t recipes, - ipc_voucher_attr_raw_recipe_array_size_t recipe_size, - ipc_voucher_t *new_voucher) + ipc_voucher_attr_control_t control, + ipc_voucher_attr_raw_recipe_array_t recipes, + ipc_voucher_attr_raw_recipe_array_size_t recipe_size, + ipc_voucher_t *new_voucher) { mach_voucher_attr_key_t control_key; ipc_voucher_attr_recipe_t sub_recipe; @@ -1852,8 +1890,9 @@ ipc_voucher_attr_control_create_mach_voucher( ipc_voucher_t voucher = IV_NULL; kern_return_t kr = KERN_SUCCESS; - if (IPC_VOUCHER_ATTR_CONTROL_NULL == control) + if (IPC_VOUCHER_ATTR_CONTROL_NULL == control) { return KERN_INVALID_CAPABILITY; + } /* if nothing to do ... */ if (0 == recipe_size) { @@ -1863,14 +1902,14 @@ ipc_voucher_attr_control_create_mach_voucher( /* allocate new voucher */ voucher = iv_alloc(ivgt_keys_in_use); - if (IV_NULL == voucher) + if (IV_NULL == voucher) { return KERN_RESOURCE_SHORTAGE; + } control_key = iv_index_to_key(control->ivac_key_index); /* iterate over the recipe items */ while (0 < recipe_size - recipe_used) { - if (recipe_size - recipe_used < sizeof(*sub_recipe)) { kr = KERN_INVALID_ARGUMENT; break; @@ -1885,14 +1924,15 @@ ipc_voucher_attr_control_create_mach_voucher( recipe_used += sizeof(*sub_recipe) + sub_recipe->content_size; kr = ipc_execute_voucher_recipe_command(voucher, - sub_recipe->key, - sub_recipe->command, - sub_recipe->previous_voucher, - sub_recipe->content, - sub_recipe->content_size, - (sub_recipe->key == control_key)); - if (KERN_SUCCESS != kr) + sub_recipe->key, + sub_recipe->command, + sub_recipe->previous_voucher, + sub_recipe->content, + sub_recipe->content_size, + (sub_recipe->key == control_key)); + if (KERN_SUCCESS != kr) { break; + } } if (KERN_SUCCESS == kr) { @@ -1905,7 +1945,7 @@ ipc_voucher_attr_control_create_mach_voucher( } /* - * ipc_register_well_known_mach_voucher_attr_manager + * ipc_register_well_known_mach_voucher_attr_manager * * Register the resource manager responsible for a given key value. */ @@ -1913,23 +1953,26 @@ kern_return_t ipc_register_well_known_mach_voucher_attr_manager( ipc_voucher_attr_manager_t manager, mach_voucher_attr_value_handle_t default_value, - mach_voucher_attr_key_t key, + mach_voucher_attr_key_t key, ipc_voucher_attr_control_t *control) { ipc_voucher_attr_control_t new_control; iv_index_t key_index; iv_index_t hash_index; - if (IVAM_NULL == manager) + if (IVAM_NULL == manager) { return KERN_INVALID_ARGUMENT; + } key_index = iv_key_to_index(key); - if (IV_UNUSED_KEYINDEX == key_index) + if (IV_UNUSED_KEYINDEX == key_index) { return KERN_INVALID_ARGUMENT; + } new_control = ivac_alloc(key_index); - if (IVAC_NULL == new_control) + if (IVAC_NULL == new_control) { return KERN_RESOURCE_SHORTAGE; + } /* insert the default value into slot 0 */ new_control->ivac_table[IV_UNUSED_VALINDEX].ivace_value = default_value; @@ -1956,7 +1999,7 @@ ipc_register_well_known_mach_voucher_attr_manager( new_control->ivac_table[hash_index].ivace_index = IV_UNUSED_VALINDEX; ivgt_unlock(); - + /* return the reference on the new cache control to the caller */ *control = new_control; @@ -1964,7 +2007,7 @@ ipc_register_well_known_mach_voucher_attr_manager( } /* - * Routine: mach_voucher_extract_attr_content + * Routine: mach_voucher_extract_attr_content * Purpose: * Extract the content for a given pair. * @@ -1979,10 +2022,10 @@ ipc_register_well_known_mach_voucher_attr_manager( */ kern_return_t mach_voucher_extract_attr_content( - ipc_voucher_t voucher, - mach_voucher_attr_key_t key, - mach_voucher_attr_content_t content, - mach_voucher_attr_content_size_t *in_out_size) + ipc_voucher_t voucher, + mach_voucher_attr_key_t key, + mach_voucher_attr_content_t content, + mach_voucher_attr_content_size_t *in_out_size) { mach_voucher_attr_value_handle_t vals[MACH_VOUCHER_ATTR_VALUE_MAX_NESTED]; mach_voucher_attr_value_handle_array_size_t vals_count; @@ -1993,8 +2036,9 @@ mach_voucher_extract_attr_content( kern_return_t kr; - if (IV_NULL == voucher) + if (IV_NULL == voucher) { return KERN_INVALID_ARGUMENT; + } key_index = iv_key_to_index(key); @@ -2020,20 +2064,20 @@ mach_voucher_extract_attr_content( * for this value_index. */ ivace_lookup_values(key_index, value_index, - vals, &vals_count); + vals, &vals_count); assert(0 < vals_count); /* callout to manager */ - - kr = (manager->ivam_extract_content)(manager, key, - vals, vals_count, - &command, - content, in_out_size); + + kr = (manager->ivam_extract_content)(manager, key, + vals, vals_count, + &command, + content, in_out_size); return kr; } /* - * Routine: mach_voucher_extract_attr_recipe + * Routine: mach_voucher_extract_attr_recipe * Purpose: * Extract a recipe for a given pair. * @@ -2048,10 +2092,10 @@ mach_voucher_extract_attr_content( */ kern_return_t mach_voucher_extract_attr_recipe( - ipc_voucher_t voucher, - mach_voucher_attr_key_t key, - mach_voucher_attr_raw_recipe_t raw_recipe, - mach_voucher_attr_raw_recipe_size_t *in_out_size) + ipc_voucher_t voucher, + mach_voucher_attr_key_t key, + mach_voucher_attr_raw_recipe_t raw_recipe, + mach_voucher_attr_raw_recipe_size_t *in_out_size) { mach_voucher_attr_value_handle_t vals[MACH_VOUCHER_ATTR_VALUE_MAX_NESTED]; mach_voucher_attr_value_handle_array_size_t vals_count; @@ -2062,8 +2106,9 @@ mach_voucher_extract_attr_recipe( kern_return_t kr; - if (IV_NULL == voucher) + if (IV_NULL == voucher) { return KERN_INVALID_ARGUMENT; + } key_index = iv_key_to_index(key); @@ -2073,8 +2118,9 @@ mach_voucher_extract_attr_recipe( return KERN_SUCCESS; } - if (*in_out_size < sizeof(*recipe)) + if (*in_out_size < sizeof(*recipe)) { return KERN_NO_SPACE; + } recipe = (mach_voucher_attr_recipe_t)(void *)raw_recipe; recipe->key = key; @@ -2098,17 +2144,17 @@ mach_voucher_extract_attr_recipe( * for this value_index. */ ivace_lookup_values(key_index, value_index, - vals, &vals_count); + vals, &vals_count); assert(0 < vals_count); /* callout to manager */ - kr = (manager->ivam_extract_content)(manager, key, - vals, vals_count, - &recipe->command, - recipe->content, &recipe->content_size); + kr = (manager->ivam_extract_content)(manager, key, + vals, vals_count, + &recipe->command, + recipe->content, &recipe->content_size); if (KERN_SUCCESS == kr) { - assert(*in_out_size - sizeof(*recipe) >= recipe->content_size); - *in_out_size = sizeof(*recipe) + recipe->content_size; + assert(*in_out_size - sizeof(*recipe) >= recipe->content_size); + *in_out_size = sizeof(*recipe) + recipe->content_size; } return kr; @@ -2117,27 +2163,28 @@ mach_voucher_extract_attr_recipe( /* - * Routine: mach_voucher_extract_all_attr_recipes + * Routine: mach_voucher_extract_all_attr_recipes * Purpose: * Extract all the (non-default) contents for a given voucher, - * building up a recipe that could be provided to a future + * building up a recipe that could be provided to a future * voucher creation call. - * Conditions: + * Conditions: * Nothing locked (may invoke user-space). * Caller holds a reference on the supplied voucher. */ kern_return_t mach_voucher_extract_all_attr_recipes( - ipc_voucher_t voucher, - mach_voucher_attr_raw_recipe_array_t recipes, - mach_voucher_attr_raw_recipe_array_size_t *in_out_size) + ipc_voucher_t voucher, + mach_voucher_attr_raw_recipe_array_t recipes, + mach_voucher_attr_raw_recipe_array_size_t *in_out_size) { mach_voucher_attr_recipe_size_t recipe_size = *in_out_size; mach_voucher_attr_recipe_size_t recipe_used = 0; iv_index_t key_index; - if (IV_NULL == voucher) + if (IV_NULL == voucher) { return KERN_INVALID_ARGUMENT; + } for (key_index = 0; key_index < voucher->iv_table_size; key_index++) { mach_voucher_attr_value_handle_t vals[MACH_VOUCHER_ATTR_VALUE_MAX_NESTED]; @@ -2151,11 +2198,13 @@ mach_voucher_extract_all_attr_recipes( /* don't output anything for a default value */ value_index = iv_lookup(voucher, key_index); - if (IV_UNUSED_VALINDEX == value_index) + if (IV_UNUSED_VALINDEX == value_index) { continue; + } - if (recipe_size - recipe_used < sizeof(*recipe)) + if (recipe_size - recipe_used < sizeof(*recipe)) { return KERN_NO_SPACE; + } /* * Get the manager for this key_index. The @@ -2177,7 +2226,7 @@ mach_voucher_extract_all_attr_recipes( * for this value_index. */ ivace_lookup_values(key_index, value_index, - vals, &vals_count); + vals, &vals_count); assert(0 < vals_count); key = iv_index_to_key(key_index); @@ -2187,12 +2236,13 @@ mach_voucher_extract_all_attr_recipes( recipe->content_size = content_size; /* callout to manager */ - kr = (manager->ivam_extract_content)(manager, key, - vals, vals_count, - &recipe->command, - recipe->content, &recipe->content_size); - if (KERN_SUCCESS != kr) + kr = (manager->ivam_extract_content)(manager, key, + vals, vals_count, + &recipe->command, + recipe->content, &recipe->content_size); + if (KERN_SUCCESS != kr) { return kr; + } assert(recipe->content_size <= content_size); recipe_used += sizeof(*recipe) + recipe->content_size; @@ -2203,10 +2253,10 @@ mach_voucher_extract_all_attr_recipes( } /* - * Routine: mach_voucher_debug_info + * Routine: mach_voucher_debug_info * Purpose: * Extract all the (non-default) contents for a given mach port name, - * building up a recipe that could be provided to a future + * building up a recipe that could be provided to a future * voucher creation call. * Conditions: * Nothing locked (may invoke user-space). @@ -2215,20 +2265,20 @@ mach_voucher_extract_all_attr_recipes( #if !(DEVELOPMENT || DEBUG) kern_return_t mach_voucher_debug_info( - ipc_space_t __unused space, - mach_port_name_t __unused voucher_name, - mach_voucher_attr_raw_recipe_array_t __unused recipes, - mach_voucher_attr_raw_recipe_array_size_t __unused *in_out_size) + ipc_space_t __unused space, + mach_port_name_t __unused voucher_name, + mach_voucher_attr_raw_recipe_array_t __unused recipes, + mach_voucher_attr_raw_recipe_array_size_t __unused *in_out_size) { return KERN_NOT_SUPPORTED; } #else kern_return_t mach_voucher_debug_info( - ipc_space_t space, - mach_port_name_t voucher_name, - mach_voucher_attr_raw_recipe_array_t recipes, - mach_voucher_attr_raw_recipe_array_size_t *in_out_size) + ipc_space_t space, + mach_port_name_t voucher_name, + mach_voucher_attr_raw_recipe_array_t recipes, + mach_voucher_attr_raw_recipe_array_size_t *in_out_size) { ipc_voucher_t voucher = IPC_VOUCHER_NULL; kern_return_t kr; @@ -2239,8 +2289,9 @@ mach_voucher_debug_info( } kr = ipc_port_translate_send(space, voucher_name, &port); - if (KERN_SUCCESS != kr) + if (KERN_SUCCESS != kr) { return KERN_INVALID_ARGUMENT; + } voucher = convert_port_to_voucher(port); ip_unlock(port); @@ -2256,7 +2307,7 @@ mach_voucher_debug_info( #endif /* - * Routine: mach_voucher_attr_command + * Routine: mach_voucher_attr_command * Purpose: * Invoke an attribute-specific command through this voucher. * @@ -2269,13 +2320,13 @@ mach_voucher_debug_info( */ kern_return_t mach_voucher_attr_command( - ipc_voucher_t voucher, - mach_voucher_attr_key_t key, - mach_voucher_attr_command_t command, - mach_voucher_attr_content_t in_content, - mach_voucher_attr_content_size_t in_content_size, - mach_voucher_attr_content_t out_content, - mach_voucher_attr_content_size_t *out_content_size) + ipc_voucher_t voucher, + mach_voucher_attr_key_t key, + mach_voucher_attr_command_t command, + mach_voucher_attr_content_t in_content, + mach_voucher_attr_content_size_t in_content_size, + mach_voucher_attr_content_t out_content, + mach_voucher_attr_content_size_t *out_content_size) { mach_voucher_attr_value_handle_t vals[MACH_VOUCHER_ATTR_VALUE_MAX_NESTED]; mach_voucher_attr_value_handle_array_size_t vals_count; @@ -2286,8 +2337,9 @@ mach_voucher_attr_command( kern_return_t kr; - if (IV_NULL == voucher) + if (IV_NULL == voucher) { return KERN_INVALID_ARGUMENT; + } key_index = iv_key_to_index(key); @@ -2312,14 +2364,14 @@ mach_voucher_attr_command( */ value_index = iv_lookup(voucher, key_index); ivace_lookup_values(key_index, value_index, - vals, &vals_count); + vals, &vals_count); /* callout to manager */ - kr = (manager->ivam_command)(manager, key, - vals, vals_count, - command, - in_content, in_content_size, - out_content, out_content_size); + kr = (manager->ivam_command)(manager, key, + vals, vals_count, + command, + in_content, in_content_size, + out_content, out_content_size); /* release reference on control */ ivac_release(control); @@ -2328,7 +2380,7 @@ mach_voucher_attr_command( } /* - * Routine: mach_voucher_attr_control_get_values + * Routine: mach_voucher_attr_control_get_values * Purpose: * For a given voucher, get the value handle associated with the * specified attribute manager. @@ -2342,26 +2394,29 @@ mach_voucher_attr_control_get_values( { iv_index_t key_index, value_index; - if (IPC_VOUCHER_ATTR_CONTROL_NULL == control) + if (IPC_VOUCHER_ATTR_CONTROL_NULL == control) { return KERN_INVALID_CAPABILITY; + } - if (IV_NULL == voucher) + if (IV_NULL == voucher) { return KERN_INVALID_ARGUMENT; + } - if (0 == *in_out_size) + if (0 == *in_out_size) { return KERN_SUCCESS; + } key_index = control->ivac_key_index; - assert(0 < voucher->iv_refs); + assert(os_ref_get_count(&voucher->iv_refs) > 0); value_index = iv_lookup(voucher, key_index); ivace_lookup_values(key_index, value_index, - out_values, in_out_size); + out_values, in_out_size); return KERN_SUCCESS; } /* - * Routine: mach_voucher_attr_control_create_mach_voucher + * Routine: mach_voucher_attr_control_create_mach_voucher * Purpose: * Create a new mach voucher and initialize it by processing the * supplied recipe(s). @@ -2389,8 +2444,9 @@ mach_voucher_attr_control_create_mach_voucher( ipc_voucher_t voucher = IV_NULL; kern_return_t kr = KERN_SUCCESS; - if (IPC_VOUCHER_ATTR_CONTROL_NULL == control) + if (IPC_VOUCHER_ATTR_CONTROL_NULL == control) { return KERN_INVALID_CAPABILITY; + } /* if nothing to do ... */ if (0 == recipe_size) { @@ -2400,8 +2456,9 @@ mach_voucher_attr_control_create_mach_voucher( /* allocate new voucher */ voucher = iv_alloc(ivgt_keys_in_use); - if (IV_NULL == voucher) + if (IV_NULL == voucher) { return KERN_RESOURCE_SHORTAGE; + } control_key = iv_index_to_key(control->ivac_key_index); @@ -2430,16 +2487,17 @@ mach_voucher_attr_control_create_mach_voucher( } kr = ipc_execute_voucher_recipe_command(voucher, - sub_recipe->key, - sub_recipe->command, - prev_iv, - sub_recipe->content, - sub_recipe->content_size, - (sub_recipe->key == control_key)); + sub_recipe->key, + sub_recipe->command, + prev_iv, + sub_recipe->content, + sub_recipe->content_size, + (sub_recipe->key == control_key)); ipc_voucher_release(prev_iv); - if (KERN_SUCCESS != kr) + if (KERN_SUCCESS != kr) { break; + } } if (KERN_SUCCESS == kr) { @@ -2452,7 +2510,7 @@ mach_voucher_attr_control_create_mach_voucher( } /* - * Routine: host_create_mach_voucher + * Routine: host_create_mach_voucher * Purpose: * Create a new mach voucher and initialize it by processing the * supplied recipe(s). @@ -2476,8 +2534,9 @@ host_create_mach_voucher( ipc_voucher_t voucher = IV_NULL; kern_return_t kr = KERN_SUCCESS; - if (host == HOST_NULL) + if (host == HOST_NULL) { return KERN_INVALID_ARGUMENT; + } /* if nothing to do ... */ if (0 == recipe_size) { @@ -2487,8 +2546,9 @@ host_create_mach_voucher( /* allocate new voucher */ voucher = iv_alloc(ivgt_keys_in_use); - if (IV_NULL == voucher) + if (IV_NULL == voucher) { return KERN_RESOURCE_SHORTAGE; + } /* iterate over the recipe items */ while (0 < recipe_size - recipe_used) { @@ -2515,16 +2575,17 @@ host_create_mach_voucher( } kr = ipc_execute_voucher_recipe_command(voucher, - sub_recipe->key, - sub_recipe->command, - prev_iv, - sub_recipe->content, - sub_recipe->content_size, - FALSE); + sub_recipe->key, + sub_recipe->command, + prev_iv, + sub_recipe->content, + sub_recipe->content_size, + FALSE); ipc_voucher_release(prev_iv); - if (KERN_SUCCESS != kr) + if (KERN_SUCCESS != kr) { break; + } } if (KERN_SUCCESS == kr) { @@ -2537,10 +2598,10 @@ host_create_mach_voucher( } /* - * Routine: host_register_well_known_mach_voucher_attr_manager + * Routine: host_register_well_known_mach_voucher_attr_manager * Purpose: * Register the user-level resource manager responsible for a given - * key value. + * key value. * Conditions: * The manager port passed in has to be converted/wrapped * in an ipc_voucher_attr_manager_t structure and then call the @@ -2550,14 +2611,15 @@ host_create_mach_voucher( */ kern_return_t host_register_well_known_mach_voucher_attr_manager( - host_t host, + host_t host, mach_voucher_attr_manager_t __unused manager, mach_voucher_attr_value_handle_t __unused default_value, - mach_voucher_attr_key_t __unused key, + mach_voucher_attr_key_t __unused key, ipc_voucher_attr_control_t __unused *control) { - if (HOST_NULL == host) + if (HOST_NULL == host) { return KERN_INVALID_HOST; + } #if 1 return KERN_NOT_SUPPORTED; @@ -2576,18 +2638,19 @@ host_register_well_known_mach_voucher_attr_manager( proxy = mvam_alloc(manager); kr = ipc_register_well_known_mach_voucher_attr_manager(&proxy->mvam_manager, - default_value, - key, - control); - if (KERN_SUCCESS != kr) + default_value, + key, + control); + if (KERN_SUCCESS != kr) { mvam_release(proxy); + } return kr; #endif } /* - * Routine: host_register_mach_voucher_attr_manager + * Routine: host_register_mach_voucher_attr_manager * Purpose: * Register the user-space resource manager and return a * dynamically allocated key. @@ -2598,14 +2661,15 @@ host_register_well_known_mach_voucher_attr_manager( */ kern_return_t host_register_mach_voucher_attr_manager( - host_t host, + host_t host, mach_voucher_attr_manager_t __unused manager, mach_voucher_attr_value_handle_t __unused default_value, - mach_voucher_attr_key_t __unused *key, + mach_voucher_attr_key_t __unused *key, ipc_voucher_attr_control_t __unused *control) { - if (HOST_NULL == host) + if (HOST_NULL == host) { return KERN_INVALID_HOST; + } return KERN_NOT_SUPPORTED; } @@ -2622,7 +2686,7 @@ ipc_get_pthpriority_from_kmsg_voucher( { ipc_voucher_t pthread_priority_voucher; mach_voucher_attr_raw_recipe_size_t content_size = - sizeof(mach_voucher_attr_recipe_data_t) + sizeof(ipc_pthread_priority_value_t); + sizeof(mach_voucher_attr_recipe_data_t) + sizeof(ipc_pthread_priority_value_t); uint8_t content_data[content_size]; mach_voucher_attr_recipe_t cur_content; kern_return_t kr = KERN_SUCCESS; @@ -2633,9 +2697,9 @@ ipc_get_pthpriority_from_kmsg_voucher( pthread_priority_voucher = (ipc_voucher_t)kmsg->ikm_voucher->ip_kobject; kr = mach_voucher_extract_attr_recipe(pthread_priority_voucher, - MACH_VOUCHER_ATTR_KEY_PTHPRIORITY, - content_data, - &content_size); + MACH_VOUCHER_ATTR_KEY_PTHPRIORITY, + content_data, + &content_size); if (kr != KERN_SUCCESS) { return kr; } @@ -2664,8 +2728,8 @@ void ipc_voucher_send_preprocessing(ipc_kmsg_t kmsg) { uint8_t recipes[(MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN + 1) * sizeof(ipc_voucher_attr_recipe_data_t)]; - ipc_voucher_attr_raw_recipe_array_size_t recipe_size = (MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN + 1) * - sizeof(ipc_voucher_attr_recipe_data_t); + ipc_voucher_attr_raw_recipe_array_size_t recipe_size = (MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN + 1) * + sizeof(ipc_voucher_attr_recipe_data_t); ipc_voucher_t pre_processed_voucher; ipc_voucher_t voucher_to_send; kern_return_t kr; @@ -2679,9 +2743,9 @@ ipc_voucher_send_preprocessing(ipc_kmsg_t kmsg) pre_processed_voucher = (ipc_voucher_t)kmsg->ikm_voucher->ip_kobject; kr = ipc_voucher_prepare_processing_recipe(pre_processed_voucher, - (mach_voucher_attr_raw_recipe_array_t)recipes, - &recipe_size, MACH_VOUCHER_ATTR_SEND_PREPROCESS, - IVAM_FLAGS_SUPPORT_SEND_PREPROCESS, &need_preprocessing); + (mach_voucher_attr_raw_recipe_array_t)recipes, + &recipe_size, MACH_VOUCHER_ATTR_SEND_PREPROCESS, + IVAM_FLAGS_SUPPORT_SEND_PREPROCESS, &need_preprocessing); assert(KERN_SUCCESS == kr); /* @@ -2689,8 +2753,8 @@ ipc_voucher_send_preprocessing(ipc_kmsg_t kmsg) */ if (need_preprocessing) { kr = ipc_create_mach_voucher(recipes, - recipe_size, - &voucher_to_send); + recipe_size, + &voucher_to_send); assert(KERN_SUCCESS == kr); ipc_port_release_send(kmsg->ikm_voucher); kmsg->ikm_voucher = convert_voucher_to_port(voucher_to_send); @@ -2708,19 +2772,19 @@ ipc_voucher_send_preprocessing(ipc_kmsg_t kmsg) */ void ipc_voucher_receive_postprocessing( - ipc_kmsg_t kmsg, - mach_msg_option_t option) + ipc_kmsg_t kmsg, + mach_msg_option_t option) { uint8_t recipes[(MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN + 1) * sizeof(ipc_voucher_attr_recipe_data_t)]; - ipc_voucher_attr_raw_recipe_array_size_t recipe_size = (MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN + 1) * - sizeof(ipc_voucher_attr_recipe_data_t); + ipc_voucher_attr_raw_recipe_array_size_t recipe_size = (MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN + 1) * + sizeof(ipc_voucher_attr_recipe_data_t); ipc_voucher_t recv_voucher; ipc_voucher_t sent_voucher; kern_return_t kr; int need_postprocessing = FALSE; if ((option & MACH_RCV_VOUCHER) == 0 || (!IP_VALID(kmsg->ikm_voucher)) || - current_task() == kernel_task) { + current_task() == kernel_task) { return; } @@ -2728,9 +2792,9 @@ ipc_voucher_receive_postprocessing( sent_voucher = (ipc_voucher_t)kmsg->ikm_voucher->ip_kobject; kr = ipc_voucher_prepare_processing_recipe(sent_voucher, - (mach_voucher_attr_raw_recipe_array_t)recipes, - &recipe_size, MACH_VOUCHER_ATTR_AUTO_REDEEM, - IVAM_FLAGS_SUPPORT_RECEIVE_POSTPROCESS, &need_postprocessing); + (mach_voucher_attr_raw_recipe_array_t)recipes, + &recipe_size, MACH_VOUCHER_ATTR_AUTO_REDEEM, + IVAM_FLAGS_SUPPORT_RECEIVE_POSTPROCESS, &need_postprocessing); assert(KERN_SUCCESS == kr); @@ -2739,8 +2803,8 @@ ipc_voucher_receive_postprocessing( */ if (need_postprocessing) { kr = ipc_create_mach_voucher(recipes, - recipe_size, - &recv_voucher); + recipe_size, + &recv_voucher); assert(KERN_SUCCESS == kr); /* swap the voucher port (and set voucher bits in case it didn't already exist) */ kmsg->ikm_header->msgh_bits |= (MACH_MSG_TYPE_MOVE_SEND << 16); @@ -2769,13 +2833,15 @@ ipc_voucher_prepare_processing_recipe( ipc_voucher_attr_raw_recipe_array_size_t recipe_used = 0; iv_index_t key_index; ipc_voucher_attr_recipe_t recipe; - - if (IV_NULL == voucher) + + if (IV_NULL == voucher) { return KERN_INVALID_ARGUMENT; - + } + /* Setup a recipe to copy all attributes. */ - if (recipe_size < sizeof(*recipe)) - return KERN_NO_SPACE; + if (recipe_size < sizeof(*recipe)) { + return KERN_NO_SPACE; + } *need_processing = FALSE; recipe = (ipc_voucher_attr_recipe_t)(void *)&recipes[recipe_used]; @@ -2792,14 +2858,16 @@ ipc_voucher_prepare_processing_recipe( /* don't output anything for a default value */ value_index = iv_lookup(voucher, key_index); - if (IV_UNUSED_VALINDEX == value_index) + if (IV_UNUSED_VALINDEX == value_index) { continue; + } - if (recipe_size - recipe_used < sizeof(*recipe)) + if (recipe_size - recipe_used < sizeof(*recipe)) { return KERN_NO_SPACE; + } recipe = (ipc_voucher_attr_recipe_t)(void *)&recipes[recipe_used]; - + /* * Get the manager for this key_index. The * existence of a non-default value for this @@ -2813,9 +2881,10 @@ ipc_voucher_prepare_processing_recipe( } /* Check if the supported flag is set in the manager */ - if ((manager->ivam_flags & flags) == 0) + if ((manager->ivam_flags & flags) == 0) { continue; - + } + key = iv_index_to_key(key_index); recipe->key = key; @@ -2867,9 +2936,9 @@ mach_generate_activity_id( } activity_id = generate_activity_id(args->count); - kr = copyout(&activity_id, args->activity_id, sizeof (activity_id)); + kr = copyout(&activity_id, args->activity_id, sizeof(activity_id)); - return (kr); + return kr; } #if defined(MACH_VOUCHER_ATTR_KEY_USER_DATA) || defined(MACH_VOUCHER_ATTR_KEY_TEST) @@ -2877,15 +2946,15 @@ mach_generate_activity_id( /* * Build-in a simple User Data Resource Manager */ -#define USER_DATA_MAX_DATA (16*1024) +#define USER_DATA_MAX_DATA (16*1024) struct user_data_value_element { - mach_voucher_attr_value_reference_t e_made; - mach_voucher_attr_content_size_t e_size; - iv_index_t e_sum; - iv_index_t e_hash; - queue_chain_t e_hash_link; - uint8_t e_data[]; + mach_voucher_attr_value_reference_t e_made; + mach_voucher_attr_content_size_t e_size; + iv_index_t e_sum; + iv_index_t e_hash; + queue_chain_t e_hash_link; + uint8_t e_data[]; }; typedef struct user_data_value_element *user_data_element_t; @@ -2903,74 +2972,74 @@ static lck_spin_t user_data_lock_data; lck_spin_init(&user_data_lock_data, &ipc_lck_grp, &ipc_lck_attr) #define user_data_lock_destroy() \ lck_spin_destroy(&user_data_lock_data, &ipc_lck_grp) -#define user_data_lock() \ - lck_spin_lock(&user_data_lock_data) -#define user_data_lock_try() \ - lck_spin_try_lock(&user_data_lock_data) -#define user_data_unlock() \ +#define user_data_lock() \ + lck_spin_lock_grp(&user_data_lock_data, &ipc_lck_grp) +#define user_data_lock_try() \ + lck_spin_try_lock_grp(&user_data_lock_data, &ipc_lck_grp) +#define user_data_unlock() \ lck_spin_unlock(&user_data_lock_data) static kern_return_t user_data_release_value( - ipc_voucher_attr_manager_t manager, - mach_voucher_attr_key_t key, - mach_voucher_attr_value_handle_t value, - mach_voucher_attr_value_reference_t sync); + ipc_voucher_attr_manager_t manager, + mach_voucher_attr_key_t key, + mach_voucher_attr_value_handle_t value, + mach_voucher_attr_value_reference_t sync); static kern_return_t user_data_get_value( - ipc_voucher_attr_manager_t manager, - mach_voucher_attr_key_t key, - mach_voucher_attr_recipe_command_t command, - mach_voucher_attr_value_handle_array_t prev_values, - mach_voucher_attr_value_handle_array_size_t prev_value_count, - mach_voucher_attr_content_t content, - mach_voucher_attr_content_size_t content_size, - mach_voucher_attr_value_handle_t *out_value, - mach_voucher_attr_value_flags_t *out_flags, - ipc_voucher_t *out_value_voucher); + ipc_voucher_attr_manager_t manager, + mach_voucher_attr_key_t key, + mach_voucher_attr_recipe_command_t command, + mach_voucher_attr_value_handle_array_t prev_values, + mach_voucher_attr_value_handle_array_size_t prev_value_count, + mach_voucher_attr_content_t content, + mach_voucher_attr_content_size_t content_size, + mach_voucher_attr_value_handle_t *out_value, + mach_voucher_attr_value_flags_t *out_flags, + ipc_voucher_t *out_value_voucher); static kern_return_t user_data_extract_content( - ipc_voucher_attr_manager_t manager, - mach_voucher_attr_key_t key, - mach_voucher_attr_value_handle_array_t values, - mach_voucher_attr_value_handle_array_size_t value_count, - mach_voucher_attr_recipe_command_t *out_command, - mach_voucher_attr_content_t out_content, - mach_voucher_attr_content_size_t *in_out_content_size); + ipc_voucher_attr_manager_t manager, + mach_voucher_attr_key_t key, + mach_voucher_attr_value_handle_array_t values, + mach_voucher_attr_value_handle_array_size_t value_count, + mach_voucher_attr_recipe_command_t *out_command, + mach_voucher_attr_content_t out_content, + mach_voucher_attr_content_size_t *in_out_content_size); static kern_return_t user_data_command( - ipc_voucher_attr_manager_t manager, - mach_voucher_attr_key_t key, - mach_voucher_attr_value_handle_array_t values, - mach_msg_type_number_t value_count, - mach_voucher_attr_command_t command, - mach_voucher_attr_content_t in_content, - mach_voucher_attr_content_size_t in_content_size, - mach_voucher_attr_content_t out_content, - mach_voucher_attr_content_size_t *out_content_size); + ipc_voucher_attr_manager_t manager, + mach_voucher_attr_key_t key, + mach_voucher_attr_value_handle_array_t values, + mach_msg_type_number_t value_count, + mach_voucher_attr_command_t command, + mach_voucher_attr_content_t in_content, + mach_voucher_attr_content_size_t in_content_size, + mach_voucher_attr_content_t out_content, + mach_voucher_attr_content_size_t *out_content_size); static void user_data_release( - ipc_voucher_attr_manager_t manager); + ipc_voucher_attr_manager_t manager); struct ipc_voucher_attr_manager user_data_manager = { - .ivam_release_value = user_data_release_value, - .ivam_get_value = user_data_get_value, - .ivam_extract_content = user_data_extract_content, - .ivam_command = user_data_command, - .ivam_release = user_data_release, - .ivam_flags = IVAM_FLAGS_NONE, + .ivam_release_value = user_data_release_value, + .ivam_get_value = user_data_get_value, + .ivam_extract_content = user_data_extract_content, + .ivam_command = user_data_command, + .ivam_release = user_data_release, + .ivam_flags = IVAM_FLAGS_NONE, }; ipc_voucher_attr_control_t user_data_control; ipc_voucher_attr_control_t test_control; #if defined(MACH_VOUCHER_ATTR_KEY_USER_DATA) && defined(MACH_VOUCHER_ATTR_KEY_TEST) -#define USER_DATA_ASSERT_KEY(key) \ - assert(MACH_VOUCHER_ATTR_KEY_USER_DATA == (key) || \ +#define USER_DATA_ASSERT_KEY(key) \ + assert(MACH_VOUCHER_ATTR_KEY_USER_DATA == (key) || \ MACH_VOUCHER_ATTR_KEY_TEST == (key)); #elif defined(MACH_VOUCHER_ATTR_KEY_USER_DATA) #define USER_DATA_ASSERT_KEY(key) assert(MACH_VOUCHER_ATTR_KEY_USER_DATA == (key)) @@ -2979,7 +3048,7 @@ ipc_voucher_attr_control_t test_control; #endif /* - * Routine: user_data_release_value + * Routine: user_data_release_value * Purpose: * Release a made reference on a specific value managed by * this voucher attribute manager. @@ -2989,15 +3058,15 @@ ipc_voucher_attr_control_t test_control; */ static kern_return_t user_data_release_value( - ipc_voucher_attr_manager_t __assert_only manager, - mach_voucher_attr_key_t __assert_only key, - mach_voucher_attr_value_handle_t value, - mach_voucher_attr_value_reference_t sync) + ipc_voucher_attr_manager_t __assert_only manager, + mach_voucher_attr_key_t __assert_only key, + mach_voucher_attr_value_handle_t value, + mach_voucher_attr_value_reference_t sync) { user_data_element_t elem; iv_index_t hash; - assert (&user_data_manager == manager); + assert(&user_data_manager == manager); USER_DATA_ASSERT_KEY(key); elem = (user_data_element_t)value; @@ -3017,28 +3086,28 @@ user_data_release_value( } /* - * Routine: user_data_checksum + * Routine: user_data_checksum * Purpose: * Provide a rudimentary checksum for the data presented * to these voucher attribute managers. */ static iv_index_t user_data_checksum( - mach_voucher_attr_content_t content, - mach_voucher_attr_content_size_t content_size) + mach_voucher_attr_content_t content, + mach_voucher_attr_content_size_t content_size) { mach_voucher_attr_content_size_t i; iv_index_t cksum = 0; - for(i = 0; i < content_size; i++, content++) { + for (i = 0; i < content_size; i++, content++) { cksum = (cksum << 8) ^ (cksum + *(unsigned char *)content); } - return (~cksum); + return ~cksum; } /* - * Routine: user_data_dedup + * Routine: user_data_dedup * Purpose: * See if the content represented by this request already exists * in another user data element. If so return a made reference @@ -3051,10 +3120,10 @@ user_data_checksum( */ static user_data_element_t user_data_dedup( - mach_voucher_attr_content_t content, - mach_voucher_attr_content_size_t content_size) + mach_voucher_attr_content_t content, + mach_voucher_attr_content_size_t content_size) { - iv_index_t sum; + iv_index_t sum; iv_index_t hash; user_data_element_t elem; user_data_element_t alloc = NULL; @@ -3062,7 +3131,7 @@ user_data_dedup( sum = user_data_checksum(content, content_size); hash = USER_DATA_HASH_BUCKET(sum); - retry: +retry: user_data_lock(); queue_iterate(&user_data_bucket[hash], elem, user_data_element_t, e_hash_link) { assert(elem->e_hash == hash); @@ -3072,19 +3141,23 @@ user_data_dedup( iv_index_t i; /* and all data matches */ - for (i = 0; i < content_size; i++) - if (elem->e_data[i] != content[i]) + for (i = 0; i < content_size; i++) { + if (elem->e_data[i] != content[i]) { break; - if (i < content_size) + } + } + if (i < content_size) { continue; + } /* ... we found a match... */ elem->e_made++; user_data_unlock(); - if (NULL != alloc) + if (NULL != alloc) { kfree(alloc, sizeof(*alloc) + content_size); + } return elem; } @@ -3110,20 +3183,20 @@ user_data_dedup( static kern_return_t user_data_get_value( - ipc_voucher_attr_manager_t __assert_only manager, - mach_voucher_attr_key_t __assert_only key, - mach_voucher_attr_recipe_command_t command, - mach_voucher_attr_value_handle_array_t prev_values, - mach_voucher_attr_value_handle_array_size_t prev_value_count, - mach_voucher_attr_content_t content, - mach_voucher_attr_content_size_t content_size, - mach_voucher_attr_value_handle_t *out_value, - mach_voucher_attr_value_flags_t *out_flags, - ipc_voucher_t *out_value_voucher) + ipc_voucher_attr_manager_t __assert_only manager, + mach_voucher_attr_key_t __assert_only key, + mach_voucher_attr_recipe_command_t command, + mach_voucher_attr_value_handle_array_t prev_values, + mach_voucher_attr_value_handle_array_size_t prev_value_count, + mach_voucher_attr_content_t content, + mach_voucher_attr_content_size_t content_size, + mach_voucher_attr_value_handle_t *out_value, + mach_voucher_attr_value_flags_t *out_flags, + ipc_voucher_t *out_value_voucher) { user_data_element_t elem; - assert (&user_data_manager == manager); + assert(&user_data_manager == manager); USER_DATA_ASSERT_KEY(key); /* never an out voucher */ @@ -3131,7 +3204,6 @@ user_data_get_value( *out_flags = MACH_VOUCHER_ATTR_VALUE_FLAGS_NONE; switch (command) { - case MACH_VOUCHER_ATTR_REDEEM: /* redeem of previous values is the value */ @@ -3148,8 +3220,9 @@ user_data_get_value( return KERN_SUCCESS; case MACH_VOUCHER_ATTR_USER_DATA_STORE: - if (USER_DATA_MAX_DATA < content_size) + if (USER_DATA_MAX_DATA < content_size) { return KERN_RESOURCE_SHORTAGE; + } /* empty is the default */ if (0 == content_size) { @@ -3169,28 +3242,29 @@ user_data_get_value( static kern_return_t user_data_extract_content( - ipc_voucher_attr_manager_t __assert_only manager, - mach_voucher_attr_key_t __assert_only key, - mach_voucher_attr_value_handle_array_t values, - mach_voucher_attr_value_handle_array_size_t value_count, - mach_voucher_attr_recipe_command_t *out_command, - mach_voucher_attr_content_t out_content, - mach_voucher_attr_content_size_t *in_out_content_size) + ipc_voucher_attr_manager_t __assert_only manager, + mach_voucher_attr_key_t __assert_only key, + mach_voucher_attr_value_handle_array_t values, + mach_voucher_attr_value_handle_array_size_t value_count, + mach_voucher_attr_recipe_command_t *out_command, + mach_voucher_attr_content_t out_content, + mach_voucher_attr_content_size_t *in_out_content_size) { mach_voucher_attr_content_size_t size = 0; user_data_element_t elem; unsigned int i; - assert (&user_data_manager == manager); + assert(&user_data_manager == manager); USER_DATA_ASSERT_KEY(key); /* concatenate the stored data items */ - for (i = 0; i < value_count ; i++) { + for (i = 0; i < value_count && *in_out_content_size > 0; i++) { elem = (user_data_element_t)values[i]; assert(USER_DATA_MAX_DATA >= elem->e_size); - if (size + elem->e_size > *in_out_content_size) + if (size + elem->e_size > *in_out_content_size) { return KERN_NO_SPACE; + } memcpy(&out_content[size], elem->e_data, elem->e_size); size += elem->e_size; @@ -3202,27 +3276,28 @@ user_data_extract_content( static kern_return_t user_data_command( - ipc_voucher_attr_manager_t __assert_only manager, - mach_voucher_attr_key_t __assert_only key, - mach_voucher_attr_value_handle_array_t __unused values, - mach_msg_type_number_t __unused value_count, - mach_voucher_attr_command_t __unused command, - mach_voucher_attr_content_t __unused in_content, - mach_voucher_attr_content_size_t __unused in_content_size, - mach_voucher_attr_content_t __unused out_content, - mach_voucher_attr_content_size_t __unused *out_content_size) + ipc_voucher_attr_manager_t __assert_only manager, + mach_voucher_attr_key_t __assert_only key, + mach_voucher_attr_value_handle_array_t __unused values, + mach_msg_type_number_t __unused value_count, + mach_voucher_attr_command_t __unused command, + mach_voucher_attr_content_t __unused in_content, + mach_voucher_attr_content_size_t __unused in_content_size, + mach_voucher_attr_content_t __unused out_content, + mach_voucher_attr_content_size_t __unused *out_content_size) { - assert (&user_data_manager == manager); + assert(&user_data_manager == manager); USER_DATA_ASSERT_KEY(key); return KERN_FAILURE; } static void user_data_release( - ipc_voucher_attr_manager_t manager) + ipc_voucher_attr_manager_t manager) { - if (manager != &user_data_manager) + if (manager != &user_data_manager) { return; + } panic("Voucher user-data manager released"); } @@ -3234,35 +3309,38 @@ user_data_attr_manager_init() { kern_return_t kr; -#if defined(MACH_VOUCHER_ATTR_KEY_USER_DATA) +#if defined(MACH_VOUCHER_ATTR_KEY_USER_DATA) if ((user_data_manager_inited & 0x1) != 0x1) { kr = ipc_register_well_known_mach_voucher_attr_manager(&user_data_manager, - (mach_voucher_attr_value_handle_t)0, - MACH_VOUCHER_ATTR_KEY_USER_DATA, - &user_data_control); - if (KERN_SUCCESS != kr) + (mach_voucher_attr_value_handle_t)0, + MACH_VOUCHER_ATTR_KEY_USER_DATA, + &user_data_control); + if (KERN_SUCCESS != kr) { printf("Voucher user-data manager register(USER-DATA) returned %d", kr); - else + } else { user_data_manager_inited |= 0x1; + } } #endif #if defined(MACH_VOUCHER_ATTR_KEY_TEST) if ((user_data_manager_inited & 0x2) != 0x2) { kr = ipc_register_well_known_mach_voucher_attr_manager(&user_data_manager, - (mach_voucher_attr_value_handle_t)0, - MACH_VOUCHER_ATTR_KEY_TEST, - &test_control); - if (KERN_SUCCESS != kr) + (mach_voucher_attr_value_handle_t)0, + MACH_VOUCHER_ATTR_KEY_TEST, + &test_control); + if (KERN_SUCCESS != kr) { printf("Voucher user-data manager register(TEST) returned %d", kr); - else + } else { user_data_manager_inited |= 0x2; + } } #endif #if defined(MACH_VOUCHER_ATTR_KEY_USER_DATA) || defined(MACH_VOUCHER_ATTR_KEY_TEST) int i; - for (i=0; i < USER_DATA_HASH_BUCKETS; i++) + for (i = 0; i < USER_DATA_HASH_BUCKETS; i++) { queue_init(&user_data_bucket[i]); + } user_data_lock_init(); #endif