aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/mac/Framework/OnDemandServer.mm15
-rw-r--r--src/client/mac/crash_generation/Inspector.h18
-rw-r--r--src/client/mac/crash_generation/Inspector.mm43
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);