void setup_shared_port() { kern_return_t err; // get a send right to the port we're going to overwrite so that we can both // restore it for ourselves and send it to our child err = task_get_special_port(mach_task_self(), STOLEN_SPECIAL_PORT, &saved_special_port); MACH_ERR("saving original special port value", err); // allocate the shared port we want our child to have a send right to err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &shared_port_parent); MACH_ERR("allocating shared port", err); // insert the send right err = mach_port_insert_right(mach_task_self(), shared_port_parent, shared_port_parent, MACH_MSG_TYPE_MAKE_SEND); MACH_ERR("inserting MAKE_SEND into shared port", err); // stash the port in the STOLEN_SPECIAL_PORT slot such that the send right survives the fork err = task_set_special_port(mach_task_self(), STOLEN_SPECIAL_PORT, shared_port_parent); MACH_ERR("setting special port", err); }
void mach_init_ports(void) { mach_port_array_t ports; mach_msg_type_number_t ports_count; kern_return_t kr; /* * Find those ports important to every task. */ kr = task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, &bootstrap_port); if (kr != KERN_SUCCESS) return; kr = mach_ports_lookup(mach_task_self(), &ports, &ports_count); if ((kr != KERN_SUCCESS) || (ports_count < MACH_PORTS_SLOTS_USED)) return; name_server_port = ports[NAME_SERVER_SLOT]; environment_port = ports[ENVIRONMENT_SLOT]; service_port = ports[SERVICE_SLOT]; /* get rid of out-of-line data so brk has a chance of working */ (void) vm_deallocate(mach_task_self(), (vm_offset_t) ports, (vm_size_t) (ports_count * sizeof *ports)); }
mach_port_t sharkctl_create_port(void) { mach_port_t bootstrap_port, shark_port = 0; task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, &bootstrap_port); bootstrap_look_up(bootstrap_port, "CHUD_IPC", &shark_port); return shark_port; }
mach_port_t recover_shared_port_child() { kern_return_t err; // grab the shared port which our parent stashed somewhere in the special ports mach_port_t shared_port_child = MACH_PORT_NULL; err = task_get_special_port(mach_task_self(), STOLEN_SPECIAL_PORT, &shared_port_child); MACH_ERR("child getting stashed port", err); LOG("child got stashed port"); // say hello to our parent and send a reply port so it can send us back the special port to restore // allocate a reply port mach_port_t reply_port; err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &reply_port); MACH_ERR("child allocating reply port", err); // send the reply port in a hello message simple_msg_send_t msg = {0}; msg.header.msgh_size = sizeof(msg); msg.header.msgh_local_port = reply_port; msg.header.msgh_remote_port = shared_port_child; msg.header.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); err = mach_msg_send(&msg.header); MACH_ERR("child sending task port message", err); LOG("child sent hello message to parent over shared port"); // wait for a message on the reply port containing the stolen port to restore port_msg_rcv_t stolen_port_msg = {0}; err = mach_msg(&stolen_port_msg.header, MACH_RCV_MSG, 0, sizeof(stolen_port_msg), reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); MACH_ERR("child receiving stolen port\n", err); // extract the port right from the message mach_port_t stolen_port_to_restore = stolen_port_msg.port.name; if (stolen_port_to_restore == MACH_PORT_NULL) { FAIL("child received invalid stolen port to restore"); } // restore the special port for the child err = task_set_special_port(mach_task_self(), STOLEN_SPECIAL_PORT, stolen_port_to_restore); MACH_ERR("child restoring special port", err); LOG("child restored stolen port"); return shared_port_child; }
// use the other task port to try to get a send right to the host-priv port mach_port_t get_host_priv(mach_port_t other_task) { mach_port_t our_host = mach_host_self(); mach_port_t other_host = MACH_PORT_NULL; kern_return_t err = task_get_special_port(other_task, TASK_HOST_PORT, &other_host); if (err != KERN_SUCCESS) { printf("failed to get other task's host port\n"); return MACH_PORT_NULL; } if (other_host != MACH_PORT_NULL && other_host != our_host) { printf("got the host priv port, dankeschoen!\n"); return other_host; } printf("other task has the same host port as us\n"); return MACH_PORT_NULL; }
int main() { kern_return_t kr; mach_port_t bport, port, pset; struct msg_recv message; struct msg_send reply; struct kevent64_s kev; int kq, r; task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, &bport); syslog(LOG_ERR, "bootstrap port: %d", bport); kr = bootstrap_check_in(bootstrap_port, "mach.service-test", &port); if (kr != KERN_SUCCESS) { syslog(LOG_ERR, "bootstrap_check_in: kr=%d", kr); exit(1); } syslog(LOG_ERR, "service port: %d", port); kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &pset); if (kr != KERN_SUCCESS) { syslog(LOG_ERR, "mach_port_allocate: kr=%d", kr); exit(1); } kr = mach_port_move_member(mach_task_self(), port, pset); if (kr != KERN_SUCCESS) { syslog(LOG_ERR, "mach_port_move_member: kr=%d", kr); exit(1); } kq = kqueue(); syslog(LOG_ERR, "kqueue fd: %d", kq); memset(&kev, 0, sizeof(struct kevent64_s)); EV_SET64(&kev, pset, EVFILT_MACHPORT, EV_ADD | EV_ENABLE, 0, 0, 0, 0, 0); if (kevent64(kq, &kev, 1, NULL, 0, 0, NULL) < 0) { syslog(LOG_ERR, "kevent64: %s (%d)", strerror(errno), errno); return 0; } for (;;) { message.hdr.msgh_local_port = port; message.hdr.msgh_size = sizeof(struct msg_recv); r = kevent64(kq, NULL, 0, &kev, 1, 0, NULL); if (r < 0) { syslog(LOG_ERR, "kevent64 failed: %s (%d)", strerror(errno), errno); continue; } syslog(LOG_ERR, "kevent64: events=%d", r); kr = mach_msg_receive((mach_msg_header_t *)&message); if (kr != KERN_SUCCESS) syslog(LOG_ERR, "mach_msg_receive failure: kr=%d", kr); else syslog(LOG_ERR, "received message on port %d: body=%s", message.hdr.msgh_remote_port, message.body); memset(&reply, 0, sizeof(struct msg_send)); sprintf(&reply.body[0], "hello buddy"); reply.hdr.msgh_local_port = MACH_PORT_NULL; reply.hdr.msgh_remote_port = message.hdr.msgh_remote_port; reply.hdr.msgh_size = sizeof(struct msg_send); reply.hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); kr = mach_msg_send((mach_msg_header_t *)&reply); if (kr != KERN_SUCCESS) syslog(LOG_ERR, "mach_msg_send failure: kr=%d", kr); } }