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; }
static void allocate_segv_handler() { #ifdef JULIA_ENABLE_THREADING arraylist_new(&suspended_threads, jl_n_threads); #endif pthread_t thread; pthread_attr_t attr; kern_return_t ret; mach_port_t self = mach_task_self(); ret = mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, &segv_port); HANDLE_MACH_ERROR("mach_port_allocate",ret); ret = mach_port_insert_right(self, segv_port, segv_port, MACH_MSG_TYPE_MAKE_SEND); HANDLE_MACH_ERROR("mach_port_insert_right",ret); // Alright, create a thread to serve as the listener for exceptions if (pthread_attr_init(&attr) != 0) { jl_error("pthread_attr_init failed"); } pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (pthread_create(&thread, &attr, mach_segv_listener, NULL) != 0) { jl_error("pthread_create failed"); } pthread_attr_destroy(&attr); for (int16_t tid = 0;tid < jl_n_threads;tid++) { attach_exception_port(pthread_mach_thread_np(jl_all_task_states[tid].system_id)); } }
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); }
EXPORT int start(mach_port_t task, pid_t infoPid) { kern_return_t kret; pthread_t tid[2]; interface* face = find_interface(task); kret = mach_port_allocate(current_task(), MACH_PORT_RIGHT_RECEIVE, &face->server_port); RETURN_ON_MACH_ERROR("[-start] mach_port_allocate failed", kret); kret = mach_port_insert_right(current_task(), face->server_port, face->server_port, MACH_MSG_TYPE_MAKE_SEND); RETURN_ON_MACH_ERROR("[-start] mach_port_insert_right failed", kret); kret = task_set_exception_ports(task, EXC_MASK_ALL, face->server_port, EXCEPTION_DEFAULT|MACH_EXCEPTION_CODES, THREAD_STATE_NONE); RETURN_ON_MACH_ERROR("[-start] task_set_exception_ports failed", kret); int err = pthread_create(&tid[0], NULL, (void *(*)(void*))kqueue_loop, (void *)(unsigned long long)infoPid); if (err != 0) DEBUG_PRINT("\n[-start] can't create thread :[%s]", strerror(err)); else DEBUG_PRINT("\n[-start] Thread created successfully %d\n", 0); err = pthread_create(&tid[1], NULL, (void *(*)(void*))exception_server, (void *(*)(void*))(unsigned long long)face->server_port); if (err != 0) DEBUG_PRINT("\n[-start] can't create thread :[%s]", strerror(err)); else DEBUG_PRINT("\n[-start] Thread created successfully %d\n", 0); return 1; }
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 int mach_lookup(const char *name, xpc_port_t *local, xpc_port_t *remote) { mach_port_t mp, rmp; kern_return_t kr; kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp); if (kr != KERN_SUCCESS) { errno = EPERM; return (-1); } kr = mach_port_insert_right(mach_task_self(), mp, mp, MACH_MSG_TYPE_MAKE_SEND); if (kr != KERN_SUCCESS) { errno = EPERM; return (-1); } kr = bootstrap_look_up(bootstrap_port, name, &rmp); if (kr != KERN_SUCCESS) { debugf("bootstrap_look_up failed kr=%d", kr); errno = EBUSY; return (-1); } *local = (xpc_port_t)mp; *remote = (xpc_port_t)rmp; return (0); }
void RegisterExceptionHandler(void) { mach_port_t task = mach_task_self(); mach_port_t handler_port; kern_return_t rc; pthread_t tid; int err; /* Use the same mask as Breakpad. */ exception_mask_t exception_mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT; rc = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &handler_port); CHECK(rc == KERN_SUCCESS); rc = mach_port_insert_right(task, handler_port, handler_port, MACH_MSG_TYPE_MAKE_SEND); CHECK(rc == KERN_SUCCESS); err = pthread_create(&tid, NULL, ExceptionHandlerThread, (void *) (uintptr_t) handler_port); CHECK(err == 0); err = pthread_detach(tid); CHECK(err == 0); rc = task_set_exception_ports(mach_task_self(), exception_mask, handler_port, EXCEPTION_DEFAULT, THREAD_STATE_NONE); CHECK(rc == KERN_SUCCESS); }
static mach_port_t checkin(char *service_name) { kern_return_t kr = KERN_SUCCESS; mach_port_t port = MACH_PORT_NULL; launch_data_t msg = NULL, reply = NULL, datum = NULL; if (NULL == (msg = launch_data_new_string(LAUNCH_KEY_CHECKIN))) { helplog(ASL_LEVEL_ERR, "Could not create checkin message for launchd."); goto fin; } if (NULL == (reply = launch_msg(msg))) { helplog(ASL_LEVEL_ERR, "Could not message launchd."); goto fin; } if (LAUNCH_DATA_ERRNO == launch_data_get_type(reply)) { if (launch_data_get_errno(reply) == EACCES) { launch_data_free(msg); launch_data_free(reply); return(MACH_PORT_NULL); } helplog(ASL_LEVEL_ERR, "Launchd checkin failed: %s.", strerror(launch_data_get_errno(reply))); goto fin; } if (NULL == (datum = launch_data_dict_lookup(reply, LAUNCH_JOBKEY_MACHSERVICES)) || LAUNCH_DATA_DICTIONARY != launch_data_get_type(datum)) { helplog(ASL_LEVEL_ERR, "Launchd reply does not contain %s dictionary.", LAUNCH_JOBKEY_MACHSERVICES); goto fin; } if (NULL == (datum = launch_data_dict_lookup(datum, service_name)) || LAUNCH_DATA_MACHPORT != launch_data_get_type(datum)) { helplog(ASL_LEVEL_ERR, "Launchd reply does not contain %s Mach port.", service_name); goto fin; } if (MACH_PORT_NULL == (port = launch_data_get_machport(datum))) { helplog(ASL_LEVEL_ERR, "Launchd gave me a null Mach port."); goto fin; } 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 fin; } fin: if (NULL != msg) launch_data_free(msg); if (NULL != reply) launch_data_free(reply); if (MACH_PORT_NULL == port) exit(EXIT_FAILURE); return port; }
int ethernet_open (char *dev_name, device_t master_device, struct port_bucket *etherport_bucket, struct port_class *etherreadclass) { error_t err; assert (ether_port == MACH_PORT_NULL); err = ports_create_port (etherreadclass, etherport_bucket, sizeof (struct port_info), &readpt); if (err) error (2, err, "ports_create_port"); readptname = ports_get_right (readpt); mach_port_insert_right (mach_task_self (), readptname, readptname, MACH_MSG_TYPE_MAKE_SEND); mach_port_set_qlimit (mach_task_self (), readptname, MACH_PORT_QLIMIT_MAX); err = device_open (master_device, D_WRITE | D_READ, "eth", ðer_port); mach_port_deallocate (mach_task_self (), master_device); if (err) error (2, err, "device_open: %s", dev_name); err = device_set_filter (ether_port, ports_get_right (readpt), MACH_MSG_TYPE_MAKE_SEND, 0, (unsigned short *)ether_filter, ether_filter_len); if (err) error (2, err, "device_set_filter: %s", dev_name); set_promisc (dev_name, ether_port, 1); return 0; }
bool MemoryProtectionExceptionHandler::install() { MOZ_ASSERT(!sExceptionHandlerInstalled); // If the exception handler is disabled, report success anyway. if (MemoryProtectionExceptionHandler::isDisabled()) return true; kern_return_t ret; mach_port_t task = mach_task_self(); // Allocate a new exception port with receive rights. sMachExceptionState.current = {}; MachExceptionParameters& current = sMachExceptionState.current; ret = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, ¤t.port); if (ret != KERN_SUCCESS) return false; // Give the new port send rights as well. ret = mach_port_insert_right(task, current.port, current.port, MACH_MSG_TYPE_MAKE_SEND); if (ret != KERN_SUCCESS) { mach_port_deallocate(task, current.port); current = {}; return false; } // Start the thread that will receive the messages from our exception port. if (!sMachExceptionState.handlerThread.init(MachExceptionHandler)) { mach_port_deallocate(task, current.port); current = {}; return false; } // Set the other properties of our new exception handler. current.mask = EXC_MASK_BAD_ACCESS; current.behavior = exception_behavior_t(EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES); current.flavor = THREAD_STATE_NONE; // Tell the task to use our exception handler, and save the previous one. sMachExceptionState.previous = {}; MachExceptionParameters& previous = sMachExceptionState.previous; mach_msg_type_number_t previousCount = 1; ret = task_swap_exception_ports(task, current.mask, current.port, current.behavior, current.flavor, &previous.mask, &previousCount, &previous.port, &previous.behavior, &previous.flavor); if (ret != KERN_SUCCESS) { TerminateMachExceptionHandlerThread(); mach_port_deallocate(task, current.port); previous = {}; current = {}; return false; } // We should have info on the previous exception handler, even if it's null. MOZ_ASSERT(previousCount == 1); sExceptionHandlerInstalled = true; return sExceptionHandlerInstalled; }
int ethernet_open (struct device *dev) { error_t err; device_t master_device; struct ether_device *edev = (struct ether_device *) dev->priv; assert (edev->ether_port == MACH_PORT_NULL); err = ports_create_port (etherreadclass, etherport_bucket, sizeof (struct port_info), &edev->readpt); assert_perror (err); edev->readptname = ports_get_right (edev->readpt); mach_port_insert_right (mach_task_self (), edev->readptname, edev->readptname, MACH_MSG_TYPE_MAKE_SEND); mach_port_set_qlimit (mach_task_self (), edev->readptname, MACH_PORT_QLIMIT_MAX); master_device = file_name_lookup (dev->name, O_READ | O_WRITE, 0); if (master_device != MACH_PORT_NULL) { /* The device name here is the path of a device file. */ err = device_open (master_device, D_WRITE | D_READ, "eth", &edev->ether_port); mach_port_deallocate (mach_task_self (), master_device); if (err) error (2, err, "device_open on %s", dev->name); err = device_set_filter (edev->ether_port, ports_get_right (edev->readpt), MACH_MSG_TYPE_MAKE_SEND, 0, bpf_ether_filter, bpf_ether_filter_len); if (err) error (2, err, "device_set_filter on %s", dev->name); } else { /* No, perhaps a Mach device? */ int file_errno = errno; err = get_privileged_ports (0, &master_device); if (err) { error (0, file_errno, "file_name_lookup %s", dev->name); error (2, err, "and cannot get device master port"); } err = device_open (master_device, D_WRITE | D_READ, dev->name, &edev->ether_port); mach_port_deallocate (mach_task_self (), master_device); if (err) { error (0, file_errno, "file_name_lookup %s", dev->name); error (2, err, "device_open(%s)", dev->name); } err = device_set_filter (edev->ether_port, ports_get_right (edev->readpt), MACH_MSG_TYPE_MAKE_SEND, 0, ether_filter, ether_filter_len); if (err) error (2, err, "device_set_filter on %s", dev->name); } return 0; }
void CEeExecutor::AddExceptionHandler() { assert(g_eeExecutor == nullptr); g_eeExecutor = this; #if defined(_WIN32) m_handler = AddVectoredExceptionHandler(TRUE, &CEeExecutor::HandleException); assert(m_handler != NULL); #elif defined(__ANDROID__) struct sigaction sigAction; sigAction.sa_handler = nullptr; sigAction.sa_sigaction = &HandleException; sigAction.sa_flags = SA_SIGINFO; sigemptyset(&sigAction.sa_mask); int result = sigaction(SIGSEGV, &sigAction, nullptr); assert(result >= 0); #elif defined(__APPLE__) kern_return_t result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &m_port); assert(result == KERN_SUCCESS); m_handlerThread = std::thread([this] () { HandlerThreadProc(); }); result = mach_port_insert_right(mach_task_self(), m_port, m_port, MACH_MSG_TYPE_MAKE_SEND); assert(result == KERN_SUCCESS); result = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, m_port, EXCEPTION_STATE | MACH_EXCEPTION_CODES, STATE_FLAVOR); assert(result == KERN_SUCCESS); result = mach_port_mod_refs(mach_task_self(), m_port, MACH_PORT_RIGHT_SEND, -1); assert(result == KERN_SUCCESS); #endif }
void Connection::setShouldCloseConnectionOnMachExceptions() { ASSERT(m_exceptionPort == MACH_PORT_NULL); if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &m_exceptionPort) != KERN_SUCCESS) ASSERT_NOT_REACHED(); if (mach_port_insert_right(mach_task_self(), m_exceptionPort, m_exceptionPort, MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS) ASSERT_NOT_REACHED(); }
int main (int argc, char **argv) { mach_port_t bootstrap; mach_port_t control; error_t err; /* Parse our options... */ argp_parse (&argp, argc, argv, 0, 0, 0); task_get_bootstrap_port (mach_task_self (), &bootstrap); if (bootstrap == MACH_PORT_NULL) error (1, 0, "Must be started as a translator"); linktarget = argv[1]; /* Reply to our parent */ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &control); mach_port_insert_right (mach_task_self (), control, control, MACH_MSG_TYPE_MAKE_SEND); err = fsys_startup (bootstrap, 0, control, MACH_MSG_TYPE_COPY_SEND, &realnode); mach_port_deallocate (mach_task_self (), control); mach_port_deallocate (mach_task_self (), bootstrap); if (err) error (1, err, "Starting up translator"); io_restrict_auth (realnode, &realnodenoauth, 0, 0, 0, 0); mach_port_deallocate (mach_task_self (), realnode); /* Mark us as important. */ mach_port_t proc = getproc (); if (proc == MACH_PORT_NULL) error (2, err, "cannot get a handle to our process"); err = proc_mark_important (proc); /* This might fail due to permissions or because the old proc server is still running, ignore any such errors. */ if (err && err != EPERM && err != EMIG_BAD_ID) error (2, err, "Cannot mark us as important"); mach_port_deallocate (mach_task_self (), proc); /* Launch */ while (1) { /* The timeout here is 10 minutes */ err = mach_msg_server_timeout (fsys_server, 0, control, MACH_RCV_TIMEOUT, 1000 * 60 * 10); if (err == MACH_RCV_TIMED_OUT) exit (0); } }
void darwin_arm_init_thread_exception_port() { // Called by each new OS thread to bind its EXC_BAD_ACCESS exception // to mach_exception_handler_port_set. int ret; mach_port_t port = MACH_PORT_NULL; ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); if (ret) { fprintf(stderr, "runtime/cgo: mach_port_allocate failed: %d\n", ret); abort(); } ret = mach_port_insert_right( mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); if (ret) { fprintf(stderr, "runtime/cgo: mach_port_insert_right failed: %d\n", ret); abort(); } ret = thread_set_exception_ports( mach_thread_self(), EXC_MASK_BAD_ACCESS, port, EXCEPTION_DEFAULT, THREAD_STATE_NONE); if (ret) { fprintf(stderr, "runtime/cgo: thread_set_exception_ports failed: %d\n", ret); abort(); } ret = pthread_mutex_lock(&mach_exception_handler_port_set_mu); if (ret) { fprintf(stderr, "runtime/cgo: pthread_mutex_lock failed: %d\n", ret); abort(); } ret = mach_port_move_member( mach_task_self(), port, mach_exception_handler_port_set); if (ret) { fprintf(stderr, "runtime/cgo: mach_port_move_member failed: %d\n", ret); abort(); } ret = pthread_mutex_unlock(&mach_exception_handler_port_set_mu); if (ret) { fprintf(stderr, "runtime/cgo: pthread_mutex_unlock failed: %d\n", ret); abort(); } }
/* * kern_return_t * bootstrap_create_service(mach_port_t bootstrap_port, * name_t service_name, * mach_port_t *service_port) * * Creates a service named "service_name" and returns send rights to that * port in "service_port." The port may later be checked in as if this * port were configured in the bootstrap configuration file. * * Errors: Returns appropriate kernel errors on rpc failure. * Returns BOOTSTRAP_NAME_IN_USE, if service already exists. */ kern_return_t x_bootstrap_create_service( mach_port_t bootstrap_port, name_t service_name, mach_port_t *service_port) { server_t *serverp; service_t *servicep; bootstrap_info_t *bootstrap; kern_return_t result; bootstrap = lookup_bootstrap_by_port(bootstrap_port); if (!bootstrap || !active_bootstrap(bootstrap)) return BOOTSTRAP_NOT_PRIVILEGED; debug("Service creation attempt for service %s bootstrap %x", service_name, bootstrap_port); servicep = lookup_service_by_name(bootstrap, service_name); if (servicep) { debug("Service creation attempt for service %s failed, " "service already exists", service_name); return BOOTSTRAP_NAME_IN_USE; } serverp = lookup_server_by_port(bootstrap_port); result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, service_port); if (result != KERN_SUCCESS) kern_fatal(result, "port_allocate"); result = mach_port_insert_right(mach_task_self(), *service_port, *service_port, MACH_MSG_TYPE_MAKE_SEND); if (result != KERN_SUCCESS) kern_fatal(result, "failed to insert send right"); if (serverp) serverp->activity++; servicep = new_service(bootstrap, service_name, *service_port, !ACTIVE, DECLARED, serverp); info("Created new service %x in bootstrap %x: %s", servicep->port, bootstrap->bootstrap_port, service_name); return BOOTSTRAP_SUCCESS; }
void mach_exn_init() { kern_return_t r; mach_port_t me; pthread_t thread; pthread_attr_t attr; exception_mask_t mask; me = mach_task_self(); r = mach_port_allocate(me,MACH_PORT_RIGHT_RECEIVE,&exception_port); if(r != MACH_MSG_SUCCESS) DIE("mach_port_allocate"); r = mach_port_insert_right(me,exception_port,exception_port, MACH_MSG_TYPE_MAKE_SEND); if(r != MACH_MSG_SUCCESS) DIE("mach_port_insert_right"); /* for others see mach/exception_types.h */ mask = EXC_MASK_BAD_ACCESS; /* get the old exception ports */ r = task_get_exception_ports( me, mask, old_exc_ports.masks, &old_exc_ports.count, old_exc_ports.ports, old_exc_ports.behaviors, old_exc_ports.flavors ); if(r != MACH_MSG_SUCCESS) DIE("task_get_exception_ports"); /* set the new exception ports */ r = task_set_exception_ports( me, mask, exception_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE ); if(r != MACH_MSG_SUCCESS) DIE("task_set_exception_ports"); if(pthread_attr_init(&attr) != 0) DIE("pthread_attr_init"); if(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED) != 0) DIE("pthread_attr_setdetachedstate"); if(pthread_create(&thread,&attr,exc_thread,NULL) != 0) DIE("pthread_create"); pthread_attr_destroy(&attr); }
/* tell the kernel that we want EXC_BAD_ACCESS exceptions sent to the exception port (which is being listened to do by the mach exception handling thread). */ kern_return_t mach_thread_init(mach_port_t thread_exception_port) { kern_return_t ret; mach_port_t current_mach_thread; /* allocate a named port for the thread */ FSHOW((stderr, "Allocating mach port %x\n", thread_exception_port)); ret = mach_port_allocate_name(current_mach_task, MACH_PORT_RIGHT_RECEIVE, thread_exception_port); if (ret) { lose("mach_port_allocate_name failed with return_code %d\n", ret); } /* establish the right for the thread_exception_port to send messages */ ret = mach_port_insert_right(current_mach_task, thread_exception_port, thread_exception_port, MACH_MSG_TYPE_MAKE_SEND); if (ret) { lose("mach_port_insert_right failed with return_code %d\n", ret); } current_mach_thread = mach_thread_self(); ret = thread_set_exception_ports(current_mach_thread, EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION, thread_exception_port, EXCEPTION_DEFAULT, THREAD_STATE_NONE); if (ret) { lose("thread_set_exception_ports failed with return_code %d\n", ret); } ret = mach_port_deallocate (current_mach_task, current_mach_thread); if (ret) { lose("mach_port_deallocate failed with return_code %d\n", ret); } ret = mach_port_move_member(current_mach_task, thread_exception_port, mach_exception_handler_port_set); if (ret) { lose("mach_port_move_member failed with return_code %d\n", ret); } return ret; }
int main() { kern_return_t kr = 0; mach_port_t exc_port; mach_port_t task = mach_task_self(); pthread_t exception_thread; int err; mach_msg_type_number_t maskCount = 1; exception_mask_t mask; exception_handler_t handler; exception_behavior_t behavior; thread_state_flavor_t flavor; if ((kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &exc_port)) != KERN_SUCCESS) { fprintf(stderr, "mach_port_allocate: %#x\n", kr); exit(1); } if ((kr = mach_port_insert_right(task, exc_port, exc_port, MACH_MSG_TYPE_MAKE_SEND)) != KERN_SUCCESS) { fprintf(stderr, "mach_port_allocate: %#x\n", kr); exit(1); } if ((kr = task_get_exception_ports(task, EXC_MASK_ALL, &mask, &maskCount, &handler, &behavior, &flavor)) != KERN_SUCCESS) { fprintf(stderr,"task_get_exception_ports: %#x\n", kr); exit(1); } if ((err = pthread_create(&exception_thread, NULL, server_thread, &exc_port)) != 0) { fprintf(stderr, "pthread_create server_thread: %s\n", strerror(err)); exit(1); } pthread_detach(exception_thread); if ((kr = task_set_exception_ports(task, EXC_MASK_ALL, exc_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, flavor)) != KERN_SUCCESS) { fprintf(stderr, "task_set_exception_ports: %#x\n", kr); exit(1); } puts("Starting exception stuff"); int a = 1; int b = 0; float c = a / b; int cat = *(int *)(0x13371337); printf("Have c %f and cat %d\n", c, cat); puts("End."); }
/* Create a new pager in USER_PAGER with NPAGES pages, and return a mapping to the memory in *USER. */ error_t user_pager_create (struct user_pager *user_pager, unsigned int npages, struct cons_display **user) { error_t err; struct user_pager_info *upi; upi = calloc (1, sizeof (struct user_pager_info) + sizeof (vm_address_t) * npages); if (!upi) return errno; upi->memobj_npages = npages; /* XXX Are the values 1 and MEMORY_OBJECT_COPY_DELAY correct? */ user_pager->pager = pager_create (upi, pager_bucket, 1, MEMORY_OBJECT_COPY_DELAY, 0); if (!user_pager->pager) { free (upi); return errno; } user_pager->memobj = pager_get_port (user_pager->pager); ports_port_deref (user_pager->pager); mach_port_insert_right (mach_task_self (), user_pager->memobj, user_pager->memobj, MACH_MSG_TYPE_MAKE_SEND); *user = 0; err = vm_map (mach_task_self (), (vm_address_t *) user, (vm_size_t) npages * vm_page_size, (vm_address_t) 0, 1 /* ! (flags & MAP_FIXED) */, user_pager->memobj, 0 /* (vm_offset_t) offset */, 0 /* ! (flags & MAP_SHARED) */, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE, VM_INHERIT_NONE); if (err) { /* UPI will be cleaned up by libpager. */ mach_port_deallocate (mach_task_self (), user_pager->memobj); return err; } return 0; }
dns_service_discovery_ref DNSServiceDomainEnumerationCreate (int registrationDomains, DNSServiceDomainEnumerationReply callBack, void *context) { mach_port_t serverPort = DNSServiceDiscoveryLookupServer(); mach_port_t clientPort; kern_return_t result; dns_service_discovery_ref return_t; struct a_requests *request; if (!serverPort) { return NULL; } result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort); if (result != KERN_SUCCESS) { printf("Mach port receive creation failed, %s\n", mach_error_string(result)); return NULL; } result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND); if (result != KERN_SUCCESS) { printf("Mach port send creation failed, %s\n", mach_error_string(result)); mach_port_destroy(mach_task_self(), clientPort); return NULL; } _increaseQueueLengthOnPort(clientPort); return_t = malloc(sizeof(dns_service_discovery_t)); return_t->port = clientPort; request = malloc(sizeof(struct a_requests)); request->client_port = clientPort; request->context = context; request->callout.enumCallback = callBack; result = DNSServiceDomainEnumerationCreate_rpc(serverPort, clientPort, registrationDomains); if (result != KERN_SUCCESS) { printf("There was an error creating an enumerator, %s\n", mach_error_string(result)); free(request); return NULL; } pthread_mutex_lock(&a_requests_lock); request->next = a_requests; a_requests = request; pthread_mutex_unlock(&a_requests_lock); return return_t; }
void EstablishDylanExceptionHandlers(void) { if (exception_port == MACH_PORT_NULL) { // Need a port we can receive exceptions on kern_return_t rc = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exception_port); if (rc != KERN_SUCCESS) { mach_error("mach_port_allocate send", rc); abort(); } // Need to be able to send on it too rc = mach_port_insert_right(mach_task_self(), exception_port, exception_port, MACH_MSG_TYPE_MAKE_SEND); if (rc != KERN_SUCCESS) { mach_error("mach_port_insert_right", rc); abort(); } // Spawn a thread to serve exception requests pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_t thread; int prc = pthread_create(&thread, &attr, catcher, NULL); pthread_attr_destroy(&attr); if (prc != 0) { fprintf(stderr, "%s: pthread_create returned %d\n", __func__, prc); abort(); } } // Set this thread's exception port kern_return_t rc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_ARITHMETIC|EXC_MASK_BREAKPOINT, exception_port, EXCEPTION_STATE_IDENTITY|MACH_EXCEPTION_CODES, THREAD_STATE_FLAVOR); if (rc != KERN_SUCCESS) { mach_error("thread_set_exception_ports", rc); abort(); } primitive_reset_float_environment(); }
void InstallExceptionHandler() { mach_port_t port; CheckKR("mach_port_allocate", mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port)); std::thread exc_thread(ExceptionThread, port); exc_thread.detach(); // Obtain a send right for thread_set_exception_ports to copy... CheckKR("mach_port_insert_right", mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND)); // Mach tries the following exception ports in order: thread, task, host. // Debuggers set the task port, so we grab the thread port. CheckKR("thread_set_exception_ports", thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, port, EXCEPTION_STATE | MACH_EXCEPTION_CODES, x86_THREAD_STATE64)); // ...and get rid of our copy so that MACH_NOTIFY_NO_SENDERS works. CheckKR("mach_port_mod_refs", mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, -1)); mach_port_t previous; CheckKR("mach_port_request_notification", mach_port_request_notification(mach_task_self(), port, MACH_NOTIFY_NO_SENDERS, 0, port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous)); }
void registerDarwinExceptionHandler(void) { // Create the Mach exception port mach_port_t self = mach_task_self(); assert(mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, &mach_ex_port) == KERN_SUCCESS); assert(mach_port_insert_right(self, mach_ex_port, mach_ex_port, MACH_MSG_TYPE_MAKE_SEND) == KERN_SUCCESS); // Create the thread which receives the exceptions pthread_t thread; pthread_attr_t attr; assert(!pthread_attr_init(&attr)); assert(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)); assert(!pthread_create(&thread, &attr, exceptionHandlerEntryPoint, NULL)); pthread_attr_destroy(&attr); assert(task_set_exception_ports(self, EXC_MASK_BAD_ACCESS, mach_ex_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE) == KERN_SUCCESS); }
/* Return the active translator control port for NODE. If there is no translator, active or passive, MACH_PORT_NULL is returned in CONTROL_PORT. If there is a translator, it is started if necessary, and returned in CONTROL_PORT. *DIR_PORT should be a port right to use as the new translators parent directory. If it is MACH_PORT_NULL, a port is created from DIR and PARENT_PORT and stored in *DIR_PORT; otherwise DIR and PARENT_PORT are not used. Neither NODE or DIR should be locked when calling this function. */ error_t treefs_node_get_active_trans (struct treefs_node *node, struct treefs_node *dir, mach_port_t parent_port, mach_port_t *control_port, mach_port_t *dir_port) { /* Fill in dir_port */ void make_dir_port () { pthread_mutex_lock (&dir->lock); *dir_port = treefs_node_make_right (dir, 0, parent_port, 0); mach_port_insert_right (mach_task_self (), *dir_port, *dir_port, MACH_MSG_TYPE_MAKE_SEND); pthread_mutex_unlock (&dir->lock); }
bool exception_handler_install_platform() { if (s_installed) { return true; } // allocate port to listen for exceptions if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &s_listen_port) != KERN_SUCCESS) { return false; } // http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html if (mach_port_insert_right(mach_task_self(), s_listen_port, s_listen_port, MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS) { return false; } // filter out any exception other than EXC_BAD_ACCESS // http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html if (task_set_exception_ports(mach_task_self(), exception_mask, s_listen_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE) != KERN_SUCCESS) { return false; } // launch thread to listen for exceptions pthread_attr_t attr; pthread_t thread; if (pthread_attr_init(&attr) != 0) { return false; } if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) { return false; } if (pthread_create(&thread, &attr, &mach_exception_thread, NULL) != 0) { return -1; } pthread_attr_destroy(&attr); s_installed = true; return true; }
/* Initialize the Mach exception handler thread. Return 0 if OK, -1 on error. */ static int mach_initialize () { mach_port_t self; exception_mask_t mask; pthread_attr_t attr; pthread_t thread; self = mach_task_self (); /* Allocate a port on which the thread shall listen for exceptions. */ if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port) != KERN_SUCCESS) return -1; /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html. */ if (mach_port_insert_right (self, our_exception_port, our_exception_port, MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS) return -1; /* The exceptions we want to catch. Only EXC_BAD_ACCESS is interesting for us (see above in function catch_exception_raise). */ mask = EXC_MASK_BAD_ACCESS; /* Create the thread listening on the exception port. */ if (pthread_attr_init (&attr) != 0) return -1; if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) != 0) return -1; if (pthread_create (&thread, &attr, mach_exception_thread, NULL) != 0) return -1; pthread_attr_destroy (&attr); /* Replace the exception port info for these exceptions with our own. Note that we replace the exception port for the entire task, not only for a particular thread. This has the effect that when our exception port gets the message, the thread specific exception port has already been asked, and we don't need to bother about it. See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html. */ if (task_set_exception_ports (self, mask, our_exception_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE) != KERN_SUCCESS) return -1; return 0; }
static bool xnu_create_exception_thread(RDebug *dbg) { kern_return_t kr; int ret; mach_port_t exception_port = MACH_PORT_NULL; // Got the mach port for the current process mach_port_t task_self = mach_task_self (); task_t task = pid_to_task (dbg->pid); if (task == -1) { eprintf ("error to get task for the debugging process" " xnu_start_exception_thread\n"); return false; } if (!MACH_PORT_VALID (task_self)) { eprintf ("error to get the task for the current process" " xnu_start_exception_thread\n"); return false; } // Allocate an exception port that we will use to track our child process kr = mach_port_allocate (task_self, MACH_PORT_RIGHT_RECEIVE, &exception_port); RETURN_ON_MACH_ERROR ("error to allocate mach_port exception\n", R_FALSE); // Add the ability to send messages on the new exception port kr = mach_port_insert_right (task_self, exception_port, exception_port, MACH_MSG_TYPE_MAKE_SEND); RETURN_ON_MACH_ERROR ("error to allocate insert right\n", R_FALSE); // Save the original state of the exception ports for our child process ret = xnu_save_exception_ports (dbg); if (ret == R_FALSE) { eprintf ("error to save exception port info\n"); return false; } // Set the ability to get all exceptions on this port kr = task_set_exception_ports (task, EXC_MASK_ALL, exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); RETURN_ON_MACH_ERROR ("error to set port to receive exceptions\n", R_FALSE); // Create the exception thread //TODO where to save the exception thread //TODO see options pthread_create ret = pthread_create (&dbg->ex->thread, NULL, xnu_exception_thread, dbg); if (ret) { perror ("pthread_create"); return false; } return true; }
bool TargetException::setExceptionCallback(ExceptionCallback callback) { m_callback = std::move(callback); auto kr = mach_port_allocate(mach_task_self(),MACH_PORT_RIGHT_RECEIVE,&m_exceptionPort); if (kr != KERN_SUCCESS) { log(QString("mach_port_allocate failde: %1").arg(mach_error_string(kr)), LogType::Error); return false; } kr = mach_port_insert_right(mach_task_self(), m_exceptionPort, m_exceptionPort, MACH_MSG_TYPE_MAKE_SEND); if (kr != KERN_SUCCESS) { log(QString("mach_port_insert_right failde: %1").arg(mach_error_string(kr)), LogType::Error); return false; } kr = task_get_exception_ports( g_task, EXC_MASK_ALL, m_oldExcPorts.masks, &m_oldExcPorts.count, m_oldExcPorts.ports, m_oldExcPorts.behaviors, m_oldExcPorts.flavors ); if (kr != KERN_SUCCESS) { log(QString("task_get_exception_ports failde: %1").arg(mach_error_string(kr)), LogType::Error); return false; } kr = task_set_exception_ports( g_task, EXC_MASK_ALL, m_exceptionPort, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE ); if (kr != KERN_SUCCESS) { log(QString("task_set_exception_ports failde: %1").arg(mach_error_string(kr)), LogType::Error); return false; } return true; }
bool xnu_create_exception_thread(RDebug *dbg) { #if __POWERPC__ return false; #else kern_return_t kr; mach_port_t exception_port = MACH_PORT_NULL; mach_port_t req_port; // Got the mach port for the current process mach_port_t task_self = mach_task_self (); task_t task = pid_to_task (dbg->pid); if (!task) { eprintf ("error to get task for the debuggee process" " xnu_start_exception_thread\n"); return false; } if (!MACH_PORT_VALID (task_self)) { eprintf ("error to get the task for the current process" " xnu_start_exception_thread\n"); return false; } // Allocate an exception port that we will use to track our child process kr = mach_port_allocate (task_self, MACH_PORT_RIGHT_RECEIVE, &exception_port); RETURN_ON_MACH_ERROR ("error to allocate mach_port exception\n", false); // Add the ability to send messages on the new exception port kr = mach_port_insert_right (task_self, exception_port, exception_port, MACH_MSG_TYPE_MAKE_SEND); RETURN_ON_MACH_ERROR ("error to allocate insert right\n", false); // Atomically swap out (and save) the child process's exception ports // for the one we just created. We'll want to receive all exceptions. ex.count = (sizeof (ex.ports) / sizeof (*ex.ports)); kr = task_swap_exception_ports (task, EXC_MASK_ALL, exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE, ex.masks, &ex.count, ex.ports, ex.behaviors, ex.flavors); RETURN_ON_MACH_ERROR ("failed to swap exception ports\n", false); //get notification when process die kr = mach_port_request_notification (task_self, task, MACH_NOTIFY_DEAD_NAME, 0, exception_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &req_port); if (kr != KERN_SUCCESS) { eprintf ("Termination notification request failed\n"); } ex.exception_port = exception_port; return true; #endif }