/*
- * Copyright (c) 2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2013-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
*/
uint32_t ipc_voucher_trace_contents = 0;
-static zone_t ipc_voucher_zone;
-static zone_t ipc_voucher_attr_control_zone;
+static SECURITY_READ_ONLY_LATE(zone_t) ipc_voucher_zone;
+static ZONE_DECLARE(ipc_voucher_attr_control_zone, "ipc voucher attr controls",
+ sizeof(struct ipc_voucher_attr_control), ZC_NOENCRYPT | ZC_ZFREE_CLEARMEM);
+
+ZONE_INIT(&ipc_voucher_zone, "ipc vouchers", sizeof(struct ipc_voucher),
+ ZC_NOENCRYPT | ZC_ZFREE_CLEARMEM | ZC_NOSEQUESTER,
+ ZONE_ID_IPC_VOUCHERS, NULL);
+
+#define voucher_require(v) \
+ zone_id_require(ZONE_ID_IPC_VOUCHERS, sizeof(struct ipc_voucher), v)
/*
* Voucher hash table
#define IV_HASH_BUCKET(x) ((x) % IV_HASH_BUCKETS)
static queue_head_t ivht_bucket[IV_HASH_BUCKETS];
-static lck_spin_t ivht_lock_data;
+static LCK_SPIN_DECLARE_ATTR(ivht_lock_data, &ipc_lck_grp, &ipc_lck_attr);
static uint32_t ivht_count = 0;
-#define ivht_lock_init() \
- 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() \
*/
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_DECLARE_ATTR(ivgt_lock_data, &ipc_lck_grp, &ipc_lck_attr);
-#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() \
ipc_voucher_attr_manager_flags flags,
int *need_processing);
-#if defined(MACH_VOUCHER_ATTR_KEY_USER_DATA) || defined(MACH_VOUCHER_ATTR_KEY_TEST)
-void user_data_attr_manager_init(void);
-#endif
-
-void
+__startup_func
+static void
ipc_voucher_init(void)
{
- natural_t ipc_voucher_max = (task_max + thread_max) * 2;
- natural_t attr_manager_max = MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN;
- 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");
- zone_change(ipc_voucher_zone, Z_NOENCRYPT, TRUE);
- zone_change(ipc_voucher_zone, Z_CLEARMEMORY, 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");
- zone_change(ipc_voucher_attr_control_zone, Z_NOENCRYPT, TRUE);
- zone_change(ipc_voucher_attr_control_zone, Z_CLEARMEMORY, TRUE);
-
/* initialize voucher hash */
- ivht_lock_init();
- for (i = 0; i < IV_HASH_BUCKETS; i++) {
+ for (iv_index_t i = 0; i < IV_HASH_BUCKETS; i++) {
queue_init(&ivht_bucket[i]);
}
-
- /* initialize global table locking */
- ivgt_lock_init();
-
-#if defined(MACH_VOUCHER_ATTR_KEY_USER_DATA) || defined(MACH_VOUCHER_ATTR_KEY_TEST)
- user_data_attr_manager_init();
-#endif
}
+STARTUP(MACH_IPC, STARTUP_RANK_FIRST, ipc_voucher_init);
ipc_voucher_t
iv_alloc(iv_index_t entries)
ipc_port_t port)
{
if (IP_VALID(port)) {
- uintptr_t voucher = (uintptr_t) port->ip_kobject;
+ /* vouchers never labeled (they get transformed before use) */
+ if (ip_is_kolabeled(port)) {
+ return (uintptr_t)IV_NULL;
+ }
/*
* No need to lock because we have a reference on the
* keeps the voucher bound to the port (and active).
*/
if (ip_kotype(port) == IKOT_VOUCHER) {
- return voucher;
+ return (uintptr_t)port->ip_kobject;
}
}
return (uintptr_t)IV_NULL;
}
+static ipc_voucher_t
+ip_get_voucher(ipc_port_t port)
+{
+ ipc_voucher_t voucher = (ipc_voucher_t)ip_get_kobject(port);
+ require_ip_active(port);
+ voucher_require(voucher);
+ return voucher;
+}
+
/*
* Routine: convert_port_to_voucher
* Purpose:
convert_port_to_voucher(
ipc_port_t port)
{
- if (IP_VALID(port)) {
- zone_require(port, ipc_object_zones[IOT_PORT]);
- ipc_voucher_t voucher = (ipc_voucher_t) port->ip_kobject;
-
+ if (IP_VALID(port) && ip_kotype(port) == IKOT_VOUCHER) {
/*
* No need to lock because we have a reference on the
* 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 IV_NULL;
- }
-
- require_ip_active(port);
-
- zone_require(voucher, ipc_voucher_zone);
+ ipc_voucher_t voucher = ip_get_voucher(port);
ipc_voucher_reference(voucher);
return voucher;
}
{
mach_no_senders_notification_t *notification = (void *)msg;
ipc_port_t port = notification->not_header.msgh_remote_port;
+ ipc_voucher_t voucher = ip_get_voucher(port);
- require_ip_active(port);
assert(IKOT_VOUCHER == ip_kotype(port));
/* consume the reference donated by convert_voucher_to_port */
- zone_require((ipc_voucher_t)port->ip_kobject, ipc_voucher_zone);
- ipc_voucher_release((ipc_voucher_t)port->ip_kobject);
+ ipc_voucher_release(voucher);
}
/*
return IP_NULL;
}
- zone_require(voucher, ipc_voucher_zone);
+ voucher_require(voucher);
assert(os_ref_get_count(&voucher->iv_refs) > 0);
/*
* if this is the first send right
*/
if (!ipc_kobject_make_send_lazy_alloc_port(&voucher->iv_port,
- (ipc_kobject_t)voucher, IKOT_VOUCHER)) {
+ (ipc_kobject_t)voucher, IKOT_VOUCHER, false, 0)) {
ipc_voucher_release(voucher);
}
return voucher->iv_port;
ipc_port_t port)
{
if (IP_VALID(port)) {
- zone_require(port, ipc_object_zones[IOT_PORT]);
- ipc_voucher_attr_control_t ivac = (ipc_voucher_attr_control_t) port->ip_kobject;
+ ipc_voucher_attr_control_t ivac = (ipc_voucher_attr_control_t) ip_get_kobject(port);
/*
* No need to lock because we have a reference on the
}
require_ip_active(port);
- zone_require(ivac, ipc_voucher_attr_control_zone);
+ zone_require(ipc_voucher_attr_control_zone, ivac);
ivac_reference(ivac);
return ivac;
}
{
mach_no_senders_notification_t *notification = (void *)msg;
ipc_port_t port = notification->not_header.msgh_remote_port;
+ ipc_voucher_attr_control_t ivac;
require_ip_active(port);
assert(IKOT_VOUCHER_ATTR_CONTROL == ip_kotype(port));
/* release the reference donated by convert_voucher_attr_control_to_port */
- ivac_release((ipc_voucher_attr_control_t)port->ip_kobject);
+ ivac = (ipc_voucher_attr_control_t)ip_get_kobject(port);
+ ivac_release(ivac);
}
/*
return IP_NULL;
}
- zone_require(control, ipc_voucher_attr_control_zone);
+ zone_require(ipc_voucher_attr_control_zone, control);
/*
* make a send right and donate our reference for
* ipc_voucher_attr_control_notify if this is the first send right
*/
if (!ipc_kobject_make_send_lazy_alloc_port(&control->ivac_port,
- (ipc_kobject_t)control, IKOT_VOUCHER_ATTR_CONTROL)) {
+ (ipc_kobject_t)control, IKOT_VOUCHER_ATTR_CONTROL, false, 0)) {
ivac_release(control);
}
return control->ivac_port;
}
break;
}
- /* fall thru for single key redemption */
+ OS_FALLTHROUGH; /* fall thru for single key redemption */
/*
* DEFAULT:
return KERN_FAILURE;
}
- pthread_priority_voucher = (ipc_voucher_t)kmsg->ikm_voucher->ip_kobject;
+ pthread_priority_voucher = ip_get_voucher(kmsg->ikm_voucher);
kr = mach_voucher_extract_attr_recipe(pthread_priority_voucher,
MACH_VOUCHER_ATTR_KEY_PTHPRIORITY,
content_data,
}
/* setup recipe for preprocessing of all the attributes. */
- pre_processed_voucher = (ipc_voucher_t)kmsg->ikm_voucher->ip_kobject;
+ pre_processed_voucher = ip_get_voucher(kmsg->ikm_voucher);
kr = ipc_voucher_prepare_processing_recipe(pre_processed_voucher,
(mach_voucher_attr_raw_recipe_array_t)recipes,
}
/* setup recipe for auto redeem of all the attributes. */
- sent_voucher = (ipc_voucher_t)kmsg->ikm_voucher->ip_kobject;
+ sent_voucher = ip_get_voucher(kmsg->ikm_voucher);
kr = ipc_voucher_prepare_processing_recipe(sent_voucher,
(mach_voucher_attr_raw_recipe_array_t)recipes,
#define USER_DATA_HASH_BUCKET(x) ((x) % USER_DATA_HASH_BUCKETS)
static queue_head_t user_data_bucket[USER_DATA_HASH_BUCKETS];
-static lck_spin_t user_data_lock_data;
+static LCK_SPIN_DECLARE_ATTR(user_data_lock_data, &ipc_lck_grp, &ipc_lck_attr);
-#define user_data_lock_init() \
- 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() \
panic("Voucher user-data manager released");
}
-static int user_data_manager_inited = 0;
-
-void
-user_data_attr_manager_init()
+__startup_func
+static void
+user_data_attr_manager_init(void)
{
kern_return_t kr;
#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) {
- printf("Voucher user-data manager register(USER-DATA) returned %d", kr);
- } else {
- user_data_manager_inited |= 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) {
+ printf("Voucher user-data manager register(USER-DATA) returned %d", kr);
}
#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) {
- printf("Voucher user-data manager register(TEST) returned %d", kr);
- } else {
- user_data_manager_inited |= 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) {
+ printf("Voucher user-data manager register(TEST) returned %d", kr);
}
#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 (int i = 0; i < USER_DATA_HASH_BUCKETS; i++) {
queue_init(&user_data_bucket[i]);
}
-
- user_data_lock_init();
#endif
}
+STARTUP(MACH_IPC, STARTUP_RANK_FIRST, user_data_attr_manager_init);
-#endif /* MACH_DEBUG */
+#endif /* MACH_VOUCHER_ATTR_KEY_USER_DATA || MACH_VOUCHER_ATTR_KEY_TEST */