void ipc_kobject_destroy( ipc_port_t port) { switch (ip_kotype(port)) { case IKOT_PAGER: vm_object_destroy(port); break; case IKOT_PAGER_TERMINATING: vm_object_pager_wakeup(port); break; case IKOT_DEVICE: case IKOT_SEMAPHORE: case IKOT_LOCK_SET: break; default: #if MACH_ASSERT printf("ipc_kobject_destroy: port 0x%x, kobj 0x%x, type %d\n", port, port->ip_kobject, ip_kotype(port)); #endif /* MACH_ASSERT */ break; } }
void host_notify_port_destroy( ipc_port_t port) { host_notify_t entry; mutex_lock(&host_notify_lock); ip_lock(port); if (ip_kotype(port) == IKOT_HOST_NOTIFY) { entry = (host_notify_t)port->ip_kobject; assert(entry != NULL); ipc_kobject_set_atomically(port, IKO_NULL, IKOT_NONE); ip_unlock(port); assert(entry->port == port); remqueue(NULL, (queue_entry_t)entry); mutex_unlock(&host_notify_lock); zfree(host_notify_zone, (vm_offset_t)entry); ipc_port_release_sonce(port); return; } ip_unlock(port); mutex_unlock(&host_notify_lock); }
boolean_t ipc_kobject_notify( mach_msg_header_t *request_header, mach_msg_header_t *reply_header) { ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port; ((mig_reply_error_t *) reply_header)->RetCode = MIG_NO_REPLY; switch (request_header->msgh_id) { case MACH_NOTIFY_PORT_DELETED: case MACH_NOTIFY_PORT_DESTROYED: case MACH_NOTIFY_NO_SENDERS: case MACH_NOTIFY_SEND_ONCE: case MACH_NOTIFY_DEAD_NAME: break; default: return FALSE; } switch (ip_kotype(port)) { case IKOT_DEVICE: return ds_notify(request_header); case IKOT_MASTER_DEVICE: return ds_master_notify(request_header); default: return FALSE; } }
/* * Routine: convert_port_to_mig_object [interface] * Purpose: * Base implementation of MIG intrans routine to convert from * an incoming port reference to a new reference on the * underlying object. A new reference must be created, because * the port's reference could go away asynchronously. * Returns: * NULL - Not an active MIG object port or iid not supported * Otherwise, a reference to the underlying MIG interface * Conditions: * Nothing locked. */ mig_object_t convert_port_to_mig_object( ipc_port_t port, const MIGIID *iid) { mig_object_t mig_object; void *ppv; if (!IP_VALID(port)) return NULL; ip_lock(port); if (!ip_active(port) || (ip_kotype(port) != IKOT_MIG)) { ip_unlock(port); return NULL; } /* * Our port points to some MIG object interface. Now * query it to get a reference to the desired interface. */ ppv = NULL; mig_object = (mig_object_t)port->ip_kobject; mig_object->pVtbl->QueryInterface((IMIGObject *)mig_object, iid, &ppv); ip_unlock(port); return (mig_object_t)ppv; }
void mk_timer_port_destroy( ipc_port_t port) { mk_timer_t timer = NULL; ip_lock(port); if (ip_kotype(port) == IKOT_TIMER) { timer = (mk_timer_t)port->ip_kobject; assert(timer != NULL); ipc_kobject_set_atomically(port, IKO_NULL, IKOT_NONE); simple_lock(&timer->lock); assert(timer->port == port); } ip_unlock(port); if (timer != NULL) { if (thread_call_cancel(&timer->call_entry)) timer->active--; timer->is_armed = FALSE; timer->is_dead = TRUE; if (timer->active == 0) { simple_unlock(&timer->lock); zfree(mk_timer_zone, timer); ipc_port_release_send(port); return; } simple_unlock(&timer->lock); } }
/* * Routine: convert_port_to_locked_task * Purpose: * Internal helper routine to convert from a port to a locked * task. Used by several routines that try to convert from a * task port to a reference on some task related object. * Conditions: * Nothing locked, blocking OK. */ task_t convert_port_to_locked_task(ipc_port_t port) { int try_failed_count = 0; while (IP_VALID(port)) { task_t task; ip_lock(port); if (!ip_active(port) || (ip_kotype(port) != IKOT_TASK)) { ip_unlock(port); return TASK_NULL; } task = (task_t) port->ip_kobject; assert(task != TASK_NULL); /* * Normal lock ordering puts task_lock() before ip_lock(). * Attempt out-of-order locking here. */ if (task_lock_try(task)) { ip_unlock(port); return(task); } try_failed_count++; ip_unlock(port); mutex_pause(try_failed_count); } return TASK_NULL; }
EXTERN io_object_t iokit_lookup_connect_ref(io_object_t connectRef, ipc_space_t space) { io_object_t obj = NULL; if (connectRef && MACH_PORT_VALID(CAST_MACH_PORT_TO_NAME(connectRef))) { ipc_port_t port; kern_return_t kr; kr = ipc_object_translate(space, CAST_MACH_PORT_TO_NAME(connectRef), MACH_PORT_RIGHT_SEND, (ipc_object_t *)&port); if (kr == KERN_SUCCESS) { assert(IP_VALID(port)); ip_reference(port); ip_unlock(port); iokit_lock_port(port); if (ip_active(port) && (ip_kotype(port) == IKOT_IOKIT_CONNECT)) { obj = (io_object_t) port->ip_kobject; iokit_add_connect_reference(obj); } iokit_unlock_port(port); ip_release(port); } } return obj; }
/* * fileport_notify * * Description: Handle a no-senders notification for a fileport. Unless * the message is spoofed, destroys the port and releases * its reference on the fileglob. * * Parameters: msg A Mach no-senders notification message. */ void fileport_notify(mach_msg_header_t *msg) { mach_no_senders_notification_t *notification = (void *)msg; ipc_port_t port = notification->not_header.msgh_remote_port; struct fileglob *fg = NULL; if (!IP_VALID(port)) panic("Invalid port passed to fileport_notify()\n"); ip_lock(port); fg = (struct fileglob *)port->ip_kobject; if (!ip_active(port)) panic("Inactive port passed to fileport_notify()\n"); if (ip_kotype(port) != IKOT_FILEPORT) panic("Port of type other than IKOT_FILEPORT passed to fileport_notify()\n"); if (fg == NULL) panic("fileport without an assocated fileglob\n"); if (port->ip_srights == 0) { ip_unlock(port); fileport_releasefg(fg); ipc_port_dealloc_kernel(port); } else { ip_unlock(port); } return; }
void ipc_kobject_destroy( ipc_port_t port) { switch (ip_kotype(port)) { case IKOT_TIMER: mk_timer_port_destroy(port); break; case IKOT_NAMED_ENTRY: mach_destroy_memory_entry(port); break; case IKOT_HOST_NOTIFY: host_notify_port_destroy(port); break; #if CONFIG_MACF_MACH case IKOT_LABELH: labelh_destroy(port); break; #endif default: break; } }
/* * Routine: convert_port_to_clock * Purpose: * Convert from a port to a clock. * Doesn't consume the port ref; produces a clock ref, * which may be null. * Conditions: * Nothing locked. */ clock_t convert_port_to_clock( ipc_port_t port) { clock_t clock = CLOCK_NULL; if (IP_VALID(port)) { ip_lock(port); if (ip_active(port) && ((ip_kotype(port) == IKOT_CLOCK) || (ip_kotype(port) == IKOT_CLOCK_CTRL))) { clock = (clock_t) port->ip_kobject; } ip_unlock(port); } return (clock); }
boolean_t ref_pset_port_locked(ipc_port_t port, boolean_t matchn, processor_set_t *ppset) { processor_set_t pset; pset = PROCESSOR_SET_NULL; if (ip_active(port) && ((ip_kotype(port) == IKOT_PSET) || (matchn && (ip_kotype(port) == IKOT_PSET_NAME)))) { pset = (processor_set_t) port->ip_kobject; } *ppset = pset; ip_unlock(port); return (TRUE); }
host_t convert_port_to_host( ipc_port_t port) { host_t host = HOST_NULL; if (IP_VALID(port)) { ip_lock(port); if (ip_active(port) && ((ip_kotype(port) == IKOT_HOST) || (ip_kotype(port) == IKOT_HOST_PRIV))) host = (host_t) port->ip_kobject; ip_unlock(port); } return host; }
processor_set_t convert_port_to_pset_name( ipc_port_t port) { processor_set_t pset = PROCESSOR_SET_NULL; if (IP_VALID(port)) { ip_lock(port); if (ip_active(port) && ((ip_kotype(port) == IKOT_PSET) || (ip_kotype(port) == IKOT_PSET_NAME))) { pset = (processor_set_t) port->ip_kobject; pset_reference(pset); } ip_unlock(port); } return pset; }
kern_return_t xmm_object_reference( ipc_port_t memory_object) { ipc_port_t xmm_object; #if DIPC node_name node; #endif /* DIPC */ ip_lock(memory_object); /* We shouldn't ever be doing remote xmm_object refs */ assert(!IP_WAS_REMOTE(memory_object)); if (IP_WAS_REMOTE(memory_object)) { #if DIPC node = DIPC_ORIGIN_NODE(memory_object); ip_unlock(memory_object); return r_xmm_remote_object_reference(dipc_host_priv_port(node), memory_object); #else /* DIPC */ panic("xmm_object_reference: no transport"); #endif /* DIPC */ } /* * return error if XMM object is terminating or terminated. */ if (((int)memory_object->ip_norma_xmm_object | 1) == ((int)memory_object | 1) || (xmm_object = memory_object->ip_norma_xmm_object) == IP_NULL) { ip_unlock(memory_object); assert(!IP_IS_REMOTE(xmm_object)); return KERN_ABORTED; } assert(!IP_IS_REMOTE(xmm_object)); assert(ip_kotype(xmm_object) == IKOT_XMM_OBJECT); assert((memory_object->ip_norma_xmm_object_refs > 0) || (ip_kotype(memory_object) == IKOT_NONE)); memory_object->ip_norma_xmm_object_refs++; ip_unlock(memory_object); return KERN_SUCCESS; }
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; }
/* * Routine: semaphore_notify * Purpose: * Called whenever the Mach port system detects no-senders * on the semaphore port. * * When a send-right is first created, a no-senders * notification is armed (and a semaphore reference is donated). * * A no-senders notification will be posted when no one else holds a * send-right (reference) to the semaphore's port. This notification function * will consume the semaphore reference donated to the extant collection of * send-rights. */ void semaphore_notify(mach_msg_header_t *msg) { mach_no_senders_notification_t *notification = (void *)msg; ipc_port_t port = notification->not_header.msgh_remote_port; semaphore_t semaphore; assert(ip_active(port)); assert(IKOT_SEMAPHORE == ip_kotype(port)); semaphore = (semaphore_t)port->ip_kobject; semaphore_dereference(semaphore); }
boolean_t ref_pset_port_locked(ipc_port_t port, boolean_t matchn, processor_set_t *ppset) { processor_set_t pset; pset = PROCESSOR_SET_NULL; if (ip_active(port) && ((ip_kotype(port) == IKOT_PSET) || (matchn && (ip_kotype(port) == IKOT_PSET_NAME)))) { pset = (processor_set_t) port->ip_kobject; if (!pset_lock_try(pset)) { ip_unlock(port); mutex_pause(); return (FALSE); } pset->ref_count++; pset_unlock(pset); } *ppset = pset; ip_unlock(port); return (TRUE); }
/* * Routine: convert_port_to_task_name * Purpose: * Convert from a port to a task name. * Doesn't consume the port ref; produces a task name ref, * which may be null. * Conditions: * Nothing locked. */ task_name_t convert_port_to_task_name( ipc_port_t port) { task_name_t task = TASK_NULL; if (IP_VALID(port)) { ip_lock(port); if ( ip_active(port) && (ip_kotype(port) == IKOT_TASK || ip_kotype(port) == IKOT_TASK_NAME)) { task = (task_name_t)port->ip_kobject; assert(task != TASK_NAME_NULL); task_reference_internal(task); } ip_unlock(port); } return (task); }
static void host_notify_all( host_flavor_t notify_type, mach_msg_header_t *msg, mach_msg_size_t msg_size) { queue_t notify_queue = &host_notify_queue[notify_type]; mutex_lock(&host_notify_lock); if (!queue_empty(notify_queue)) { queue_head_t send_queue; host_notify_t entry; send_queue = *notify_queue; queue_init(notify_queue); send_queue.next->prev = &send_queue; send_queue.prev->next = &send_queue; msg->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0); msg->msgh_local_port = MACH_PORT_NULL; msg->msgh_id = host_notify_replyid[notify_type]; msg->msgh_reserved = 0; while ((entry = (host_notify_t)dequeue(&send_queue)) != NULL) { ipc_port_t port; port = entry->port; assert(port != IP_NULL); ip_lock(port); assert(ip_kotype(port) == IKOT_HOST_NOTIFY); assert(port->ip_kobject == (ipc_kobject_t)entry); ipc_kobject_set_atomically(port, IKO_NULL, IKOT_NONE); ip_unlock(port); mutex_unlock(&host_notify_lock); zfree(host_notify_zone, (vm_offset_t)entry); msg->msgh_remote_port = port; (void) mach_msg_send_from_kernel(msg, msg_size); mutex_lock(&host_notify_lock); } } mutex_unlock(&host_notify_lock); }
kern_return_t mach_port_kobject( ipc_space_t space, mach_port_name_t name, natural_t *typep, mach_vm_address_t *addrp) { ipc_entry_t entry; ipc_port_t port; kern_return_t kr; mach_vm_address_t kaddr; if (space == IS_NULL) return KERN_INVALID_TASK; kr = ipc_right_lookup_read(space, name, &entry); if (kr != KERN_SUCCESS) return kr; /* space is read-locked and active */ if ((entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE) == 0) { is_read_unlock(space); return KERN_INVALID_RIGHT; } __IGNORE_WCASTALIGN(port = (ipc_port_t) entry->ie_object); assert(port != IP_NULL); ip_lock(port); is_read_unlock(space); if (!ip_active(port)) { ip_unlock(port); return KERN_INVALID_RIGHT; } *typep = (unsigned int) ip_kotype(port); kaddr = (mach_vm_address_t)port->ip_kobject; ip_unlock(port); #if (DEVELOPMENT || DEBUG) if (0 != kaddr && is_ipc_kobject(*typep)) *addrp = VM_KERNEL_UNSLIDE_OR_PERM(kaddr); else #endif *addrp = 0; return KERN_SUCCESS; }
/* * fileport_get_fileglob * * Description: Obtain the fileglob associated with a given port. * * Parameters: port A Mach port of type IKOT_FILEPORT. * * Returns: NULL The given Mach port did not reference a * fileglob. * !NULL The fileglob that is associated with the * Mach port. * * Notes: The caller must have a reference on the fileport. */ struct fileglob * fileport_port_to_fileglob(ipc_port_t port) { struct fileglob *fg = NULL; if (!IP_VALID(port)) return NULL; ip_lock(port); if (ip_active(port) && IKOT_FILEPORT == ip_kotype(port)) fg = (void *)port->ip_kobject; ip_unlock(port); return fg; }
void ipc_kobject_set( ipc_port_t port, ipc_kobject_t kobject, ipc_kobject_type_t type) { ip_lock(port); assert(ip_active(port) || (ip_kotype(port) == IKOT_PAGER_TERMINATING)); #if MACH_ASSERT port->ip_spares[2] = (port->ip_bits & IO_BITS_KOTYPE); #endif /* MACH_ASSERT */ port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type; port->ip_kobject = kobject; ip_unlock(port); }
ledger_t convert_port_to_ledger( ipc_port_t port) { ledger_t ledger = LEDGER_NULL; if (IP_VALID(port)) { ip_lock(port); if (ip_active(port) && (ip_kotype(port) == IKOT_LEDGER)) ledger = (ledger_t) port->ip_kobject; ip_unlock(port); } return ledger; }
host_t convert_port_to_host_security( ipc_port_t port) { host_t host = HOST_NULL; if (IP_VALID(port)) { ip_lock(port); if (ip_active(port) && (ip_kotype(port) == IKOT_HOST_SECURITY)) host = (host_t) port->ip_kobject; ip_unlock(port); } return host; }
processor_t convert_port_to_processor( ipc_port_t port) { processor_t processor = PROCESSOR_NULL; if (IP_VALID(port)) { ip_lock(port); if (ip_active(port) && (ip_kotype(port) == IKOT_PROCESSOR)) processor = (processor_t) port->ip_kobject; ip_unlock(port); } return processor; }
static void iokit_no_senders( mach_no_senders_notification_t * notification ) { ipc_port_t port; io_object_t obj = NULL; ipc_kobject_type_t type = IKOT_NONE; ipc_port_t notify; port = (ipc_port_t) notification->not_header.msgh_remote_port; // convert a port to io_object_t. if( IP_VALID(port)) { iokit_lock_port(port); if( ip_active(port)) { obj = (io_object_t) port->ip_kobject; type = ip_kotype( port ); if( (IKOT_IOKIT_OBJECT == type) || (IKOT_IOKIT_CONNECT == type)) iokit_add_reference( obj ); else obj = NULL; } iokit_unlock_port(port); if( obj ) { mach_port_mscount_t mscount = notification->not_count; if( KERN_SUCCESS != iokit_client_died( obj, port, type, &mscount )) { /* Re-request no-senders notifications on the port (if still active) */ ip_lock(port); if (ip_active(port)) { notify = ipc_port_make_sonce_locked(port); ipc_port_nsrequest( port, mscount + 1, notify, ¬ify); /* port unlocked */ if ( notify != IP_NULL) ipc_port_release_sonce(notify); } else { ip_unlock(port); } } iokit_remove_reference( obj ); } } }
void xmm_object_set( ipc_port_t memory_object, ipc_port_t xmm_object, boolean_t make_copy) { assert(! IP_IS_REMOTE(xmm_object)); assert(ip_kotype(xmm_object) == IKOT_XMM_OBJECT); assert(memory_object->ip_norma_xmm_object == IP_NULL); memory_object->ip_norma_xmm_object = ipc_port_make_send(xmm_object); if (make_copy) { memory_object->ip_norma_xmm_object_refs = 1; ipc_port_copy_send(xmm_object); } else { memory_object->ip_norma_xmm_object_refs = 0; } }
kern_return_t mk_timer_cancel_trap( struct mk_timer_cancel_trap_args *args) { mach_port_name_t name = args->name; mach_vm_address_t result_time_addr = args->result_time; uint64_t armed_time = 0; mk_timer_t timer; ipc_space_t myspace = current_space(); ipc_port_t port; kern_return_t result; result = ipc_port_translate_receive(myspace, name, &port); if (result != KERN_SUCCESS) return (result); if (ip_kotype(port) == IKOT_TIMER) { timer = (mk_timer_t)port->ip_kobject; assert(timer != NULL); simple_lock(&timer->lock); assert(timer->port == port); ip_unlock(port); if (timer->is_armed) { armed_time = timer->call_entry.deadline; if (thread_call_cancel(&timer->call_entry)) timer->active--; timer->is_armed = FALSE; } simple_unlock(&timer->lock); } else { ip_unlock(port); result = KERN_INVALID_ARGUMENT; } if (result == KERN_SUCCESS) if ( result_time_addr != 0 && copyout((void *)&armed_time, result_time_addr, sizeof (armed_time)) != 0 ) result = KERN_FAILURE; return (result); }
void xmm_object_nuke( ipc_port_t xmm_object) { xmm_obj_t mobj; /* * Get and disassociate mobj from xmm object port. */ assert(!IP_IS_REMOTE(xmm_object)); assert(ip_kotype(xmm_object) == IKOT_XMM_OBJECT); mobj = (xmm_obj_t) xmm_object->ip_kobject; ipc_kobject_set(xmm_object, IKO_NULL, IKOT_NONE); /* * Destroy xmm object port and mobj. */ xmm_object_destroy(xmm_object, mobj); }
/* * Routine: port_name_to_clock * Purpose: * Convert from a clock name to a clock pointer. */ clock_t port_name_to_clock( mach_port_name_t clock_name) { clock_t clock = CLOCK_NULL; ipc_space_t space; ipc_port_t port; if (clock_name == 0) return (clock); space = current_space(); if (ipc_port_translate_send(space, clock_name, &port) != KERN_SUCCESS) return (clock); if (ip_active(port) && (ip_kotype(port) == IKOT_CLOCK)) clock = (clock_t) port->ip_kobject; ip_unlock(port); return (clock); }