diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/mac/Framework/OnDemandServer.mm | 15 | ||||
-rw-r--r-- | src/client/mac/crash_generation/Inspector.h | 18 | ||||
-rw-r--r-- | src/client/mac/crash_generation/Inspector.mm | 43 |
3 files changed, 74 insertions, 2 deletions
diff --git a/src/client/mac/Framework/OnDemandServer.mm b/src/client/mac/Framework/OnDemandServer.mm index 03f54c44..f736abd4 100644 --- a/src/client/mac/Framework/OnDemandServer.mm +++ b/src/client/mac/Framework/OnDemandServer.mm @@ -86,6 +86,21 @@ kern_return_t OnDemandServer::Initialize(const char *server_command, return kr; } + // The inspector will be invoked with its bootstrap port set to the subset, + // but the sender will need access to the original bootstrap port. Although + // the original port is the subset's parent, bootstrap_parent can't be used + // because it requires extra privileges. Stash the original bootstrap port + // in the subset by registering it under a known name. The inspector will + // recover this port and set it as its own bootstrap port in Inspector.mm + // Inspector::ResetBootstrapPort. + kr = bootstrap_register(bootstrap_subset_port, + const_cast<char*>("BootstrapParentPort"), + bootstrap_port); + if (kr != KERN_SUCCESS) { + PRINT_BOOTSTRAP_RESULT(kr, "bootstrap_register(): "); + return kr; + } + kr = bootstrap_create_server(bootstrap_subset_port, const_cast<char*>(server_command), geteuid(), // server uid diff --git a/src/client/mac/crash_generation/Inspector.h b/src/client/mac/crash_generation/Inspector.h index 9d93b2a7..e6705819 100644 --- a/src/client/mac/crash_generation/Inspector.h +++ b/src/client/mac/crash_generation/Inspector.h @@ -33,6 +33,8 @@ #import "common/mac/SimpleStringDictionary.h" #import <Foundation/Foundation.h> +#include <mach/mach.h> + #import "client/mac/handler/minidump_generator.h" #define VERBOSE 0 @@ -163,6 +165,18 @@ class Inspector { void Inspect(const char *receive_port_name); private: + // The Inspector is invoked with its bootstrap port set to the bootstrap + // subset established in OnDemandServer.mm OnDemandServer::Initialize. + // For proper communication with the system, the sender (which will inherit + // the Inspector's bootstrap port) needs the per-session bootstrap namespace + // available directly in its bootstrap port. OnDemandServer stashed this + // port into the subset namespace under a special name. ResetBootstrapPort + // recovers this port and switches this task to use it as its own bootstrap + // (ensuring that children like the sender will inherit it), and saves the + // subset in bootstrap_subset_port_ for use by ServiceCheckIn and + // ServiceCheckOut. + void ResetBootstrapPort(); + kern_return_t ServiceCheckIn(const char *receive_port_name); kern_return_t ServiceCheckOut(const char *receive_port_name); @@ -174,6 +188,10 @@ class Inspector { void SetCrashTimeParameters(); + // The bootstrap port in which the inspector is registered and into which it + // must check in. + mach_port_t bootstrap_subset_port_; + mach_port_t service_rcv_port_; int exception_type_; diff --git a/src/client/mac/crash_generation/Inspector.mm b/src/client/mac/crash_generation/Inspector.mm index 1b0b97cb..77187082 100644 --- a/src/client/mac/crash_generation/Inspector.mm +++ b/src/client/mac/crash_generation/Inspector.mm @@ -203,6 +203,8 @@ void ConfigFile::WriteFile(const SimpleStringDictionary *configurationParameters //============================================================================= void Inspector::Inspect(const char *receive_port_name) { + ResetBootstrapPort(); + kern_return_t result = ServiceCheckIn(receive_port_name); if (result == KERN_SUCCESS) { @@ -241,10 +243,47 @@ void Inspector::Inspect(const char *receive_port_name) { } //============================================================================= +void Inspector::ResetBootstrapPort() { + // A reasonable default, in case anything fails. + bootstrap_subset_port_ = bootstrap_port; + + mach_port_t self_task = mach_task_self(); + + kern_return_t kr = task_get_bootstrap_port(self_task, + &bootstrap_subset_port_); + if (kr != KERN_SUCCESS) { + NSLog(@"ResetBootstrapPort: task_get_bootstrap_port failed: %s (%d)", + mach_error_string(kr), kr); + return; + } + + mach_port_t bootstrap_parent_port; + kr = bootstrap_look_up(bootstrap_subset_port_, + "BootstrapParentPort", + &bootstrap_parent_port); + if (kr != KERN_SUCCESS) { + NSLog(@"ResetBootstrapPort: bootstrap_look_up failed: %s (%d)", + bootstrap_strerror(kr), kr); + return; + } + + kr = task_set_bootstrap_port(self_task, bootstrap_parent_port); + if (kr != KERN_SUCCESS) { + NSLog(@"ResetBootstrapPort: task_set_bootstrap_port failed: %s (%d)", + mach_error_string(kr), kr); + return; + } + + // Some things access the bootstrap port through this global variable + // instead of calling task_get_bootstrap_port. + bootstrap_port = bootstrap_parent_port; +} + +//============================================================================= kern_return_t Inspector::ServiceCheckIn(const char *receive_port_name) { // We need to get the mach port representing this service, so we can // get information from the crashed process. - kern_return_t kr = bootstrap_check_in(bootstrap_port, + kern_return_t kr = bootstrap_check_in(bootstrap_subset_port_, (char*)receive_port_name, &service_rcv_port_); @@ -275,7 +314,7 @@ kern_return_t Inspector::ServiceCheckOut(const char *receive_port_name) { } // Unregister the service associated with the receive port. - kr = bootstrap_register(bootstrap_port, + kr = bootstrap_register(bootstrap_subset_port_, (char*)receive_port_name, MACH_PORT_NULL); |