int main(void) { ERR_FILE = fopen("/tmp/FortunateSonErrorFile.txt", "a"); fprintf(ERR_FILE, "Started with pid %d\n", getpid()); mach_port_t parent_recv_port = get_hex_fiend_receive_port(); // Get notified when the parent receive port dies mach_port_t my_task = mach_task_self(); mach_port_t notificationPort = MACH_PORT_NULL; CHECK_MACH_ERROR(mach_port_allocate(my_task, MACH_PORT_RIGHT_RECEIVE, ¬ificationPort)); mach_port_t old; CHECK_MACH_ERROR(mach_port_request_notification(my_task, parent_recv_port, MACH_NOTIFY_NO_SENDERS, 0/*sync*/, notificationPort, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old)); /* Make a port set */ mach_port_t portSet = MACH_PORT_NULL; CHECK_MACH_ERROR(mach_port_allocate(my_task, MACH_PORT_RIGHT_PORT_SET, &portSet)); CHECK_MACH_ERROR(mach_port_insert_member(my_task, parent_recv_port, portSet)); CHECK_MACH_ERROR(mach_port_insert_member(my_task, notificationPort, portSet)); run_server(portSet, notificationPort); /* Once run_server returns, we're done, so exit */ return 0; }
int _kernelrpc_mach_port_insert_member_trap(struct _kernelrpc_mach_port_insert_member_args *args) { task_t task = port_name_to_task(args->target); int rv = MACH_SEND_INVALID_DEST; if (task != current_task()) goto done; rv = mach_port_insert_member(task->itk_space, args->name, args->pset); done: if (task) task_deallocate(task); return (rv); }
void setup_server_ports(struct port_args *ports) { kern_return_t ret = 0; mach_port_t bsport; mach_port_t port; ports->req_size = MAX(sizeof(ipc_inline_message) + sizeof(u_int32_t) * num_ints, sizeof(ipc_complex_message)); ports->reply_size = sizeof(ipc_trivial_message) - sizeof(mach_msg_trailer_t); ports->req_msg = malloc(ports->req_size); ports->reply_msg = malloc(ports->reply_size); if (setcount > 0) { ports->set = (mach_port_t *)calloc(sizeof(mach_port_t), setcount); if (!ports->set) { fprintf(stderr, "calloc(%lu, %d) failed!\n", sizeof(mach_port_t), setcount); exit(1); } } if (stress_prepost) { ports->port_list = (mach_port_t *)calloc(sizeof(mach_port_t), portcount); if (!ports->port_list) { fprintf(stderr, "calloc(%lu, %d) failed!\n", sizeof(mach_port_t), portcount); exit(1); } } if (useset) { mach_port_t set; if (setcount < 1) { fprintf(stderr, "Can't use sets with a setcount of %d\n", setcount); exit(1); } for (int ns = 0; ns < setcount; ns++) { ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &ports->set[ns]); if (KERN_SUCCESS != ret) { mach_error("mach_port_allocate(SET): ", ret); exit(1); } if (verbose > 1) printf("SVR[%d] allocated set[%d] %#x\n", ports->server_num, ns, ports->set[ns]); set = ports->set[ns]; } /* receive on a port set (always use the first in the chain) */ ports->rcv_set = ports->set[0]; } /* stuff the portset(s) with ports */ for (int i = 0; i < portcount; i++) { ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); if (KERN_SUCCESS != ret) { mach_error("mach_port_allocate(PORT): ", ret); exit(1); } if (stress_prepost) ports->port_list[i] = port; if (useset) { /* insert the port into _all_ allocated lowest-level sets */ for (int ns = 0; ns < setcount; ns++) { if (verbose > 1) printf("SVR[%d] moving port %#x into set %#x...\n", ports->server_num, port, ports->set[ns]); ret = mach_port_insert_member(mach_task_self(), port, ports->set[ns]); if (KERN_SUCCESS != ret) { mach_error("mach_port_insert_member(): ", ret); exit(1); } } } } /* use the last one as the server's bootstrap port */ ports->port = port; if (stress_prepost) { /* insert a send right for _each_ port */ for (int i = 0; i < portcount; i++) { ret = mach_port_insert_right(mach_task_self(), ports->port_list[i], ports->port_list[i], MACH_MSG_TYPE_MAKE_SEND); if (KERN_SUCCESS != ret) { mach_error("mach_port_insert_right(): ", ret); exit(1); } } } else { ret = mach_port_insert_right(mach_task_self(), ports->port, ports->port, MACH_MSG_TYPE_MAKE_SEND); if (KERN_SUCCESS != ret) { mach_error("mach_port_insert_right(): ", ret); exit(1); } } ret = task_get_bootstrap_port(mach_task_self(), &bsport); if (KERN_SUCCESS != ret) { mach_error("task_get_bootstrap_port(): ", ret); exit(1); } if (verbose) { printf("server waiting for IPC messages from client on port '%s' (%#x).\n", server_port_name[ports->server_num], ports->port); } ret = bootstrap_register(bsport, server_port_name[ports->server_num], ports->port); if (KERN_SUCCESS != ret) { mach_error("bootstrap_register(): ", ret); exit(1); } }
void setup_server_ports(struct port_args *ports) { kern_return_t ret = 0; mach_port_t bsport; ports->req_size = MAX(sizeof(ipc_inline_message) + sizeof(u_int32_t) * num_ints, sizeof(ipc_complex_message)); ports->reply_size = sizeof(ipc_trivial_message) - sizeof(mach_msg_trailer_t); ports->req_msg = malloc(ports->req_size); ports->reply_msg = malloc(ports->reply_size); ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &(ports->port)); if (KERN_SUCCESS != ret) { mach_error("mach_port_allocate(): ", ret); exit(1); } ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &(ports->pset)); if (KERN_SUCCESS != ret) { mach_error("mach_port_allocate(): ", ret); exit(1); } ret = mach_port_insert_member(mach_task_self(), ports->port, ports->pset); if (KERN_SUCCESS != ret) { mach_error("mach_port_insert_member(): ", ret); exit(1); } ret = mach_port_insert_right(mach_task_self(), ports->port, ports->port, MACH_MSG_TYPE_MAKE_SEND); if (KERN_SUCCESS != ret) { mach_error("mach_port_insert_right(): ", ret); exit(1); } ret = task_get_bootstrap_port(mach_task_self(), &bsport); if (KERN_SUCCESS != ret) { mach_error("task_get_bootstrap_port(): ", ret); exit(1); } if (verbose) { printf("server waiting for IPC messages from client on port '%s'.\n", server_port_name[ports->server_num]); } ret = bootstrap_register(bsport, server_port_name[ports->server_num], ports->port); if (KERN_SUCCESS != ret) { mach_error("bootstrap_register(): ", ret); exit(1); } }
/* * kern_return_t * bootstrap_subset(mach_port_t bootstrap_port, * mach_port_t requestor_port, * mach_port_t *subset_port); * * Returns a new port to use as a bootstrap port. This port behaves * exactly like the previous bootstrap_port, except that ports dynamically * registered via bootstrap_register() are available only to users of this * specific subset_port. Lookups on the subset_port will return ports * registered with this port specifically, and ports registered with * ancestors of this subset_port. Duplications of services already * registered with an ancestor port may be registered with the subset port * are allowed. Services already advertised may then be effectively removed * by registering MACH_PORT_NULL for the service. * When it is detected that the requestor_port is destroied the subset * port and all services advertized by it are destroied as well. * * Errors: Returns appropriate kernel errors on rpc failure. */ kern_return_t x_bootstrap_subset( mach_port_t bootstrap_port, mach_port_t requestor_port, mach_port_t *subset_port) { kern_return_t result; bootstrap_info_t *bootstrap; bootstrap_info_t *subset; mach_port_t new_bootstrap_port; mach_port_t previous; debug("Subset create attempt: bootstrap %x, requestor: %x", bootstrap_port, requestor_port); bootstrap = lookup_bootstrap_by_port(bootstrap_port); if (!bootstrap || !active_bootstrap(bootstrap)) return BOOTSTRAP_NOT_PRIVILEGED; result = mach_port_allocate( mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &new_bootstrap_port); if (result != KERN_SUCCESS) kern_fatal(result, "mach_port_allocate"); result = mach_port_insert_right( mach_task_self(), new_bootstrap_port, new_bootstrap_port, MACH_MSG_TYPE_MAKE_SEND); if (result != KERN_SUCCESS) kern_fatal(result, "failed to insert send right"); result = mach_port_insert_member( mach_task_self(), new_bootstrap_port, bootstrap_port_set); if (result != KERN_SUCCESS) kern_fatal(result, "port_set_add"); subset = new_bootstrap(bootstrap, new_bootstrap_port, requestor_port); result = mach_port_request_notification( mach_task_self(), requestor_port, MACH_NOTIFY_DEAD_NAME, 0, notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous); if (result != KERN_SUCCESS) { kern_error(result, "mach_port_request_notification"); mach_port_deallocate(mach_task_self(), requestor_port); subset->requestor_port = MACH_PORT_NULL; deactivate_bootstrap(subset); } else if (previous != MACH_PORT_NULL) { debug("deallocating old notification port (%x) for requestor %x", previous, requestor_port); result = mach_port_deallocate( mach_task_self(), previous); if (result != KERN_SUCCESS) kern_fatal(result, "mach_port_deallocate"); } info("Created bootstrap subset %x parent %x requestor %x", new_bootstrap_port, bootstrap_port, requestor_port); *subset_port = new_bootstrap_port; return BOOTSTRAP_SUCCESS; }