kern_return_t ipc_object_translate( ipc_space_t space, mach_port_name_t name, mach_port_right_t right, ipc_object_t *objectp) { ipc_entry_t entry; ipc_object_t object; kern_return_t kr; 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(right)) == MACH_PORT_TYPE_NONE) { is_read_unlock(space); return KERN_INVALID_RIGHT; } object = entry->ie_object; assert(object != IO_NULL); io_lock(object); is_read_unlock(space); *objectp = object; return KERN_SUCCESS; }
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; }
kern_return_t mach_port_kernel_object( ipc_space_t space, mach_port_name_t name, unsigned int *typep, vm_offset_t *addrp) { ipc_entry_t entry; ipc_port_t port; kern_return_t kr; 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; } 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); *addrp = (vm_offset_t) port->ip_kobject; ip_unlock(port); return KERN_SUCCESS; }
kern_return_t mach_port_move_member( ipc_space_t space, mach_port_name_t member, mach_port_name_t after) { ipc_entry_t entry; ipc_port_t port; ipc_pset_t nset; kern_return_t kr; if (space == IS_NULL) return KERN_INVALID_TASK; if (!MACH_PORT_VALID(member)) return KERN_INVALID_RIGHT; if (after == MACH_PORT_DEAD) return KERN_INVALID_RIGHT; kr = ipc_right_lookup_read(space, member, &entry); if (kr != KERN_SUCCESS) return kr; /* space is read-locked and active */ if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) { is_read_unlock(space); return KERN_INVALID_RIGHT; } port = (ipc_port_t) entry->ie_object; assert(port != IP_NULL); if (after == MACH_PORT_NULL) nset = IPS_NULL; else { entry = ipc_entry_lookup(space, after); if (entry == IE_NULL) { is_read_unlock(space); return KERN_INVALID_NAME; } if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) { is_read_unlock(space); return KERN_INVALID_RIGHT; } nset = (ipc_pset_t) entry->ie_object; assert(nset != IPS_NULL); } ip_lock(port); ipc_pset_remove_from_all(port); if (nset != IPS_NULL) { ips_lock(nset); kr = ipc_pset_add(nset, port); ips_unlock(nset); } ip_unlock(port); is_read_unlock(space); return kr; }
kern_return_t mach_port_get_set_status( ipc_space_t space, mach_port_name_t name, mach_port_name_t **members, mach_msg_type_number_t *membersCnt) { ipc_entry_num_t actual; /* this many members */ ipc_entry_num_t maxnames; /* space for this many members */ kern_return_t kr; vm_size_t size; /* size of allocated memory */ vm_offset_t addr; /* allocated memory */ vm_map_copy_t memory; /* copied-in memory */ if (space == IS_NULL) return KERN_INVALID_TASK; if (!MACH_PORT_VALID(name)) return KERN_INVALID_RIGHT; size = PAGE_SIZE; /* initial guess */ for (;;) { ipc_tree_entry_t tentry; ipc_entry_t entry, table; ipc_entry_num_t tsize; mach_port_index_t index; mach_port_name_t *names; ipc_pset_t pset; kr = vm_allocate(ipc_kernel_map, &addr, size, TRUE); if (kr != KERN_SUCCESS) return KERN_RESOURCE_SHORTAGE; /* can't fault while we hold locks */ kr = vm_map_wire(ipc_kernel_map, addr, addr + size, VM_PROT_READ|VM_PROT_WRITE, FALSE); assert(kr == KERN_SUCCESS); kr = ipc_right_lookup_read(space, name, &entry); if (kr != KERN_SUCCESS) { kmem_free(ipc_kernel_map, addr, size); return kr; } /* space is read-locked and active */ if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_PORT_SET) { is_read_unlock(space); kmem_free(ipc_kernel_map, addr, size); return KERN_INVALID_RIGHT; } pset = (ipc_pset_t) entry->ie_object; assert(pset != IPS_NULL); /* the port set must be active */ names = (mach_port_name_t *) addr; maxnames = size / sizeof(mach_port_name_t); actual = 0; table = space->is_table; tsize = space->is_table_size; for (index = 0; index < tsize; index++) { ipc_entry_t ientry = &table[index]; if (ientry->ie_bits & MACH_PORT_TYPE_RECEIVE) { ipc_port_t port = (ipc_port_t) ientry->ie_object; mach_port_gst_helper(pset, port, maxnames, names, &actual); } } for (tentry = ipc_splay_traverse_start(&space->is_tree); tentry != ITE_NULL; tentry = ipc_splay_traverse_next(&space->is_tree,FALSE)) { ipc_entry_bits_t bits = tentry->ite_bits; assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE); if (bits & MACH_PORT_TYPE_RECEIVE) { ipc_port_t port = (ipc_port_t) tentry->ite_object; mach_port_gst_helper(pset, port, maxnames, names, &actual); } } ipc_splay_traverse_finish(&space->is_tree); is_read_unlock(space); if (actual <= maxnames) break; /* didn't have enough memory; allocate more */ kmem_free(ipc_kernel_map, addr, size); size = round_page_32(actual * sizeof(mach_port_name_t)) + PAGE_SIZE; } if (actual == 0) { memory = VM_MAP_COPY_NULL; kmem_free(ipc_kernel_map, addr, size); } else { vm_size_t size_used; vm_size_t vm_size_used; size_used = actual * sizeof(mach_port_name_t); vm_size_used = round_page_32(size_used); /* * Make used memory pageable and get it into * copied-in form. Free any unused memory. */ kr = vm_map_unwire(ipc_kernel_map, addr, addr + vm_size_used, FALSE); assert(kr == KERN_SUCCESS); kr = vm_map_copyin(ipc_kernel_map, addr, size_used, TRUE, &memory); assert(kr == KERN_SUCCESS); if (vm_size_used != size) kmem_free(ipc_kernel_map, addr + vm_size_used, size - vm_size_used); } *members = (mach_port_name_t *) memory; *membersCnt = actual; return KERN_SUCCESS; }