X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/b0d623f7f2ae71ed96e60569f61f9a9a27016e80..fe8ab488e9161c46dd9885d58fc52996dc0249ff:/osfmk/ipc/ipc_object.c?ds=sidebyside diff --git a/osfmk/ipc/ipc_object.c b/osfmk/ipc/ipc_object.c index 4b1dc1c85..49b7e4690 100644 --- a/osfmk/ipc/ipc_object.c +++ b/osfmk/ipc/ipc_object.c @@ -83,6 +83,7 @@ #include #include +#include #include #include #include @@ -90,8 +91,8 @@ #include #include #include +#include #include -#include #include @@ -107,10 +108,7 @@ void ipc_object_reference( ipc_object_t object) { - io_lock(object); - assert(object->io_references > 0); io_reference(object); - io_unlock(object); } /* @@ -123,10 +121,7 @@ void ipc_object_release( ipc_object_t object) { - io_lock(object); - assert(object->io_references > 0); io_release(object); - io_check_unlock(object); } /* @@ -262,7 +257,7 @@ ipc_object_alloc_dead( assert(entry->ie_object == IO_NULL); entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; - + ipc_entry_modified(space, *namep, entry); is_write_unlock(space); return KERN_SUCCESS; } @@ -300,7 +295,7 @@ ipc_object_alloc_dead_name( assert(entry->ie_object == IO_NULL); entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; - + ipc_entry_modified(space, name, entry); is_write_unlock(space); return KERN_SUCCESS; } @@ -311,6 +306,7 @@ ipc_object_alloc_dead_name( * Allocate an object. * Conditions: * Nothing locked. If successful, the object is returned locked. + * The space is write locked on successful return. * The caller doesn't get a reference for the object. * Returns: * KERN_SUCCESS The object is allocated. @@ -345,9 +341,6 @@ ipc_object_alloc( ipc_port_t port = (ipc_port_t)object; bzero((char *)port, sizeof(*port)); -#if CONFIG_MACF_MACH - mac_port_label_init(&port->ip_label); -#endif } else if (otype == IOT_PORT_SET) { ipc_pset_t pset = (ipc_pset_t)object; @@ -365,9 +358,9 @@ ipc_object_alloc( entry->ie_bits |= type | urefs; entry->ie_object = object; + ipc_entry_modified(space, *namep, entry); io_lock(object); - is_write_unlock(space); object->io_references = 1; /* for entry, not caller */ object->io_bits = io_makebits(TRUE, otype, 0); @@ -416,9 +409,6 @@ ipc_object_alloc_name( ipc_port_t port = (ipc_port_t)object; bzero((char *)port, sizeof(*port)); -#if CONFIG_MACF_MACH - mac_port_label_init(&port->ip_label); -#endif } else if (otype == IOT_PORT_SET) { ipc_pset_t pset = (ipc_pset_t)object; @@ -440,6 +430,7 @@ ipc_object_alloc_name( entry->ie_bits |= type | urefs; entry->ie_object = object; + ipc_entry_modified(space, name, entry); io_lock(object); is_write_unlock(space); @@ -464,7 +455,6 @@ ipc_object_copyin_type( switch (msgt_name) { case MACH_MSG_TYPE_MOVE_RECEIVE: - case MACH_MSG_TYPE_COPY_RECEIVE: return MACH_MSG_TYPE_PORT_RECEIVE; case MACH_MSG_TYPE_MOVE_SEND_ONCE: @@ -476,6 +466,10 @@ ipc_object_copyin_type( case MACH_MSG_TYPE_COPY_SEND: return MACH_MSG_TYPE_PORT_SEND; + case MACH_MSG_TYPE_DISPOSE_RECEIVE: + case MACH_MSG_TYPE_DISPOSE_SEND: + case MACH_MSG_TYPE_DISPOSE_SEND_ONCE: + /* fall thru */ default: return MACH_MSG_TYPE_PORT_NONE; } @@ -505,7 +499,17 @@ ipc_object_copyin( { ipc_entry_t entry; ipc_port_t soright; + ipc_port_t release_port; kern_return_t kr; + queue_head_t links_data; + queue_t links = &links_data; + wait_queue_link_t wql; + +#if IMPORTANCE_INHERITANCE + int assertcnt = 0; +#endif + + queue_init(links); /* * Could first try a read lock when doing @@ -518,13 +522,33 @@ ipc_object_copyin( return kr; /* space is write-locked and active */ + release_port = IP_NULL; kr = ipc_right_copyin(space, name, entry, msgt_name, TRUE, - objectp, &soright); + objectp, &soright, + &release_port, +#if IMPORTANCE_INHERITANCE + &assertcnt, +#endif /* IMPORTANCE_INHERITANCE */ + links); if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) ipc_entry_dealloc(space, name, entry); is_write_unlock(space); + while(!queue_empty(links)) { + wql = (wait_queue_link_t) dequeue(links); + wait_queue_link_free(wql); + } + +#if IMPORTANCE_INHERITANCE + if (0 < assertcnt && ipc_importance_task_is_any_receiver_type(current_task()->task_imp_base)) { + ipc_importance_task_drop_internal_assertion(current_task()->task_imp_base, assertcnt); + } +#endif /* IMPORTANCE_INHERITANCE */ + + if (release_port != IP_NULL) + ip_release(release_port); + if ((kr == KERN_SUCCESS) && (soright != IP_NULL)) ipc_notify_port_deleted(soright, name); @@ -602,13 +626,14 @@ ipc_object_copyin_from_kernel( ipc_port_t port = (ipc_port_t) object; ip_lock(port); - assert(ip_active(port)); - assert(port->ip_receiver_name != MACH_PORT_NULL); - assert(port->ip_receiver == ipc_space_kernel); + if (ip_active(port)) { + assert(port->ip_receiver_name != MACH_PORT_NULL); + assert(port->ip_receiver == ipc_space_kernel); + port->ip_mscount++; + } - ip_reference(port); - port->ip_mscount++; port->ip_srights++; + ip_reference(port); ip_unlock(port); break; } @@ -623,11 +648,11 @@ ipc_object_copyin_from_kernel( ipc_port_t port = (ipc_port_t) object; ip_lock(port); - assert(ip_active(port)); - assert(port->ip_receiver_name != MACH_PORT_NULL); - - ip_reference(port); + if (ip_active(port)) { + assert(port->ip_receiver_name != MACH_PORT_NULL); + } port->ip_sorights++; + ip_reference(port); ip_unlock(port); break; } @@ -680,6 +705,42 @@ ipc_object_destroy( } } +/* + * Routine: ipc_object_destroy_dest + * Purpose: + * Destroys a naked capability for the destination of + * of a message. Consumes a ref for the object. + * + * Conditions: + * Nothing locked. + */ + +void +ipc_object_destroy_dest( + ipc_object_t object, + mach_msg_type_name_t msgt_name) +{ + assert(IO_VALID(object)); + assert(io_otype(object) == IOT_PORT); + + switch (msgt_name) { + case MACH_MSG_TYPE_PORT_SEND: + ipc_port_release_send((ipc_port_t) object); + break; + + case MACH_MSG_TYPE_PORT_SEND_ONCE: + if (io_active(object) && + !ip_full_kernel((ipc_port_t) object)) + ipc_notify_send_once((ipc_port_t) object); + else + ipc_port_release_sonce((ipc_port_t) object); + break; + + default: + panic("ipc_object_destroy_dest: strange rights"); + } +} + /* * Routine: ipc_object_copyout * Purpose: @@ -715,7 +776,7 @@ ipc_object_copyout( is_write_lock(space); for (;;) { - if (!space->is_active) { + if (!is_active(space)) { is_write_unlock(space); return KERN_INVALID_TASK; } @@ -759,6 +820,7 @@ ipc_object_copyout( kr = ipc_right_copyout(space, name, entry, msgt_name, overflow, object); + /* object is unlocked */ is_write_unlock(space); @@ -799,6 +861,11 @@ ipc_object_copyout_name( ipc_entry_t entry; kern_return_t kr; +#if IMPORTANCE_INHERITANCE + int assertcnt = 0; + ipc_importance_task_t task_imp = IIT_NULL; +#endif /* IMPORTANCE_INHERITANCE */ + assert(IO_VALID(object)); assert(io_otype(object) == IOT_PORT); @@ -843,10 +910,47 @@ ipc_object_copyout_name( /* space is write-locked and active, object is locked and active */ +#if IMPORTANCE_INHERITANCE + /* + * We are slamming a receive right into the space, without + * first having been enqueued on a port destined there. So, + * we have to arrange to boost the task appropriately if this + * port has assertions (and the task wants them). + */ + if (msgt_name == MACH_MSG_TYPE_PORT_RECEIVE) { + ipc_port_t port = (ipc_port_t)object; + + if (space->is_task != TASK_NULL) { + task_imp = space->is_task->task_imp_base; + if (ipc_importance_task_is_any_receiver_type(task_imp)) { + assertcnt = port->ip_impcount; + ipc_importance_task_reference(task_imp); + } + } + + /* take port out of limbo */ + assert(port->ip_tempowner != 0); + port->ip_tempowner = 0; + } + +#endif /* IMPORTANCE_INHERITANCE */ + kr = ipc_right_copyout(space, name, entry, msgt_name, overflow, object); + /* object is unlocked */ is_write_unlock(space); + +#if IMPORTANCE_INHERITANCE + /* + * Add the assertions to the task that we captured before + */ + if (task_imp != IIT_NULL) { + ipc_importance_task_hold_internal_assertion(task_imp, assertcnt); + ipc_importance_task_release(task_imp); + } +#endif /* IMPORTANCE_INHERITANCE */ + return kr; } @@ -995,31 +1099,6 @@ ipc_object_rename( return kr; } -/* - * Get a label out of a port, to be used by a kernel call - * that takes a security label as a parameter. In this case, we want - * to use the label stored in the label handle and not the label on its - * port. - * - * The port should be locked for this call. The lock protecting - * label handle contents should not be necessary, as they can only - * be modified when a label handle with one reference is a task label. - * User allocated label handles can never be modified. - */ -#if CONFIG_MACF_MACH -struct label *io_getlabel (ipc_object_t objp) -{ - ipc_port_t port = (ipc_port_t)objp; - - assert(io_otype(objp) == IOT_PORT); - - if (ip_kotype(port) == IKOT_LABELH) - return &((ipc_labelh_t) port->ip_kobject)->lh_label; - else - return &port->ip_label; -} -#endif - /* * Check whether the object is a port if so, free it. But * keep track of that fact. @@ -1033,93 +1112,8 @@ io_free( if (otype == IOT_PORT) { port = (ipc_port_t) object; -#if MACH_ASSERT - ipc_port_track_dealloc(port); -#endif /* MACH_ASSERT */ - -#if CONFIG_MACF_MACH - /* Port label should have been initialized after creation. */ - mac_port_label_destroy(&port->ip_label); -#endif + ipc_port_finalize(port); } io_lock_destroy(object); zfree(ipc_object_zones[otype], object); } - -#include -#if MACH_KDB - -#include - -#define printf kdbprintf - -/* - * Routine: ipc_object_print - * Purpose: - * Pretty-print an object for kdb. - */ - -const char *ikot_print_array[IKOT_MAX_TYPE] = { - "(NONE) ", - "(THREAD) ", - "(TASK) ", - "(HOST) ", - "(HOST_PRIV) ", - "(PROCESSOR) ", - "(PSET) ", - "(PSET_NAME) ", - "(TIMER) ", - "(PAGER_REQUEST) ", - "(DEVICE) ", /* 10 */ - "(XMM_OBJECT) ", - "(XMM_PAGER) ", - "(XMM_KERNEL) ", - "(XMM_REPLY) ", - "(NOTDEF 15) ", - "(NOTDEF 16) ", - "(HOST_SECURITY) ", - "(LEDGER) ", - "(MASTER_DEVICE) ", - "(ACTIVATION) ", /* 20 */ - "(SUBSYSTEM) ", - "(IO_DONE_QUEUE) ", - "(SEMAPHORE) ", - "(LOCK_SET) ", - "(CLOCK) ", - "(CLOCK_CTRL) ", /* 26 */ - "(IOKIT_SPARE) ", /* 27 */ - "(NAMED_MEM_ENTRY) ", /* 28 */ - "(IOKIT_CONNECT) ", - "(IOKIT_OBJECT) ", /* 30 */ - "(UPL) ", - "(MEM_OBJ_CONTROL) ", - "(AU_SESSIONPORT) ", /* 33 */ -#if CONFIG_MACF_MACH - "(LABELH) ", -#endif -/* - * Add new entries here. - * Please keep in sync with kern/ipc_kobject.h - */ - "(UNKNOWN) " /* magic catchall */ -}; - -void -ipc_object_print( - ipc_object_t object) -{ - int kotype; - - iprintf("%s", io_active(object) ? "active" : "dead"); - printf(", refs=%d", object->io_references); - printf(", otype=%d", io_otype(object)); - kotype = io_kotype(object); - if (kotype >= 0 && kotype < IKOT_MAX_TYPE) - printf(", kotype=%d %s\n", io_kotype(object), - ikot_print_array[kotype]); - else - printf(", kotype=0x%x %s\n", io_kotype(object), - ikot_print_array[IKOT_UNKNOWN]); -} - -#endif /* MACH_KDB */