kern_return_t ipc_object_rename( ipc_space_t space, mach_port_name_t oname, mach_port_name_t nname) { ipc_entry_t oentry, nentry; kern_return_t kr; kr = ipc_entry_alloc_name(space, nname, &nentry); if (kr != KERN_SUCCESS) return kr; /* space is write-locked and active */ if (ipc_right_inuse(space, nname, nentry)) { /* space is unlocked */ return KERN_NAME_EXISTS; } /* don't let ipc_entry_lookup see the uninitialized new entry */ if ((oname == nname) || ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) { ipc_entry_dealloc(space, nname, nentry); is_write_unlock(space); return KERN_INVALID_NAME; } kr = ipc_right_rename(space, oname, oentry, nname, nentry); /* space is unlocked */ return kr; }
kern_return_t ipc_object_alloc_name( ipc_space_t space, ipc_object_type_t otype, mach_port_type_t type, mach_port_urefs_t urefs, mach_port_name_t name, ipc_object_t *objectp) { ipc_object_t object; ipc_entry_t entry; kern_return_t kr; assert(otype < IOT_NUMBER); assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type); assert(type != MACH_PORT_TYPE_NONE); assert(urefs <= MACH_PORT_UREFS_MAX); object = io_alloc(otype); if (object == IO_NULL) return KERN_RESOURCE_SHORTAGE; if (otype == IOT_PORT) { 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; bzero((char *)pset, sizeof(*pset)); } io_lock_init(object); kr = ipc_entry_alloc_name(space, name, &entry); if (kr != KERN_SUCCESS) { io_free(otype, object); return kr; } /* space is write-locked */ if (ipc_right_inuse(space, name, entry)) { io_free(otype, object); return KERN_NAME_EXISTS; } entry->ie_bits |= type | urefs; entry->ie_object = object; io_lock(object); is_write_unlock(space); object->io_references = 1; /* for entry, not caller */ object->io_bits = io_makebits(TRUE, otype, 0); *objectp = object; return KERN_SUCCESS; }
kern_return_t ipc_object_alloc_dead_name( ipc_space_t space, mach_port_t name) { ipc_entry_t entry; kern_return_t kr; is_write_lock(space); kr = ipc_entry_alloc_name(space, name, &entry); if (kr != KERN_SUCCESS) { is_write_unlock(space); return kr; } if (ipc_right_inuse(space, name, entry)) return KERN_NAME_EXISTS; /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */ assert(entry->ie_object == IO_NULL); entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1; is_write_unlock(space); return KERN_SUCCESS; }
kern_return_t ipc_object_copyout_name( ipc_space_t space, ipc_object_t object, mach_msg_type_name_t msgt_name, boolean_t overflow, mach_port_name_t name) { mach_port_name_t oname; ipc_entry_t oentry; 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); kr = ipc_entry_alloc_name(space, name, &entry); if (kr != KERN_SUCCESS) return kr; /* space is write-locked and active */ if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && ipc_right_reverse(space, object, &oname, &oentry)) { /* object is locked and active */ if (name != oname) { io_unlock(object); if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) ipc_entry_dealloc(space, name, entry); is_write_unlock(space); return KERN_RIGHT_EXISTS; } assert(entry == oentry); assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); } else { if (ipc_right_inuse(space, name, entry)) return KERN_NAME_EXISTS; assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); assert(entry->ie_object == IO_NULL); io_lock(object); if (!io_active(object)) { io_unlock(object); ipc_entry_dealloc(space, name, entry); is_write_unlock(space); return KERN_INVALID_CAPABILITY; } entry->ie_object = object; } /* 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; }
kern_return_t ipc_object_copyout_name( ipc_space_t space, ipc_object_t object, mach_msg_type_name_t msgt_name, boolean_t overflow, mach_port_name_t name) { mach_port_name_t oname; ipc_entry_t oentry; ipc_entry_t entry; kern_return_t kr; assert(IO_VALID(object)); assert(io_otype(object) == IOT_PORT); kr = ipc_entry_alloc_name(space, name, &entry); if (kr != KERN_SUCCESS) return kr; /* space is write-locked and active */ if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) && ipc_right_reverse(space, object, &oname, &oentry)) { /* object is locked and active */ if (name != oname) { io_unlock(object); if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) ipc_entry_dealloc(space, name, entry); is_write_unlock(space); return KERN_RIGHT_EXISTS; } assert(entry == oentry); assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); } else { if (ipc_right_inuse(space, name, entry)) return KERN_NAME_EXISTS; assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE); assert(entry->ie_object == IO_NULL); io_lock(object); if (!io_active(object)) { io_unlock(object); ipc_entry_dealloc(space, name, entry); is_write_unlock(space); return KERN_INVALID_CAPABILITY; } entry->ie_object = object; } /* space is write-locked and active, object is locked and active */ kr = ipc_right_copyout(space, name, entry, msgt_name, overflow, object); /* object is unlocked */ is_write_unlock(space); return kr; }