Remove boostrap sandbox code.
The bootstrap sandbox was replaced by the V2 sandbox.
Bug: 762077
Change-Id: I2c9aeab22d29a42a2c800a53e0c8a5484e00c043
Reviewed-on: https://chromium-review.googlesource.com/647686
Reviewed-by: Jochen Eisinger <jochen@chromium.org>
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Commit-Queue: Greg Kerr <kerrnel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#501364}
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index dd8fc914..2d9bb52 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -446,8 +446,6 @@
"bluetooth/frame_connected_bluetooth_devices.h",
"bluetooth/web_bluetooth_service_impl.cc",
"bluetooth/web_bluetooth_service_impl.h",
- "bootstrap_sandbox_manager_mac.cc",
- "bootstrap_sandbox_manager_mac.h",
"broadcast_channel/broadcast_channel_provider.cc",
"broadcast_channel/broadcast_channel_provider.h",
"browser_child_process_host_impl.cc",
@@ -2091,7 +2089,6 @@
if (is_mac) {
deps += [
"//media",
- "//sandbox/mac:sandbox",
"//third_party/mozilla",
"//ui/accelerated_widget_mac",
]
diff --git a/content/browser/bootstrap_sandbox_manager_mac.cc b/content/browser/bootstrap_sandbox_manager_mac.cc
deleted file mode 100644
index 0941895..0000000
--- a/content/browser/bootstrap_sandbox_manager_mac.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/bootstrap_sandbox_manager_mac.h"
-
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "content/browser/mach_broker_mac.h"
-#include "content/common/sandbox_init_mac.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/child_process_data.h"
-#include "content/public/browser/render_process_host.h"
-#include "sandbox/mac/bootstrap_sandbox.h"
-
-namespace content {
-
-// static
-bool BootstrapSandboxManager::ShouldEnable() {
- return false;
-}
-
-// static
-BootstrapSandboxManager* BootstrapSandboxManager::GetInstance() {
- return base::Singleton<BootstrapSandboxManager>::get();
-}
-
-bool BootstrapSandboxManager::EnabledForSandbox(SandboxType sandbox_type) {
- return sandbox_type == SANDBOX_TYPE_RENDERER;
-}
-
-void BootstrapSandboxManager::BrowserChildProcessHostDisconnected(
- const ChildProcessData& data) {
- sandbox()->InvalidateClient(data.handle);
-}
-
-void BootstrapSandboxManager::BrowserChildProcessCrashed(
- const ChildProcessData& data,
- int exit_code) {
- sandbox()->InvalidateClient(data.handle);
-}
-
-void BootstrapSandboxManager::RenderProcessExited(
- RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) {
- sandbox()->InvalidateClient(host->GetHandle());
-}
-
-BootstrapSandboxManager::BootstrapSandboxManager()
- : sandbox_(sandbox::BootstrapSandbox::Create()) {
- CHECK(sandbox_.get());
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserChildProcessObserver::Add(this);
- RegisterSandboxPolicies();
-}
-
-BootstrapSandboxManager::~BootstrapSandboxManager() {
- BrowserChildProcessObserver::Remove(this);
-}
-
-void BootstrapSandboxManager::RegisterSandboxPolicies() {
- RegisterRendererPolicy();
-}
-
-void BootstrapSandboxManager::RegisterRendererPolicy() {
- sandbox::BootstrapSandboxPolicy policy;
- AddBaselinePolicy(&policy);
-
- // Permit font queries.
- policy.rules["com.apple.FontServer"] = sandbox::Rule(sandbox::POLICY_ALLOW);
- policy.rules["com.apple.FontObjectsServer"] =
- sandbox::Rule(sandbox::POLICY_ALLOW);
-
- // Allow access to the windowserver. This is needed to get the colorspace
- // during sandbox warmup. Since NSColorSpace conforms to NSCoding, this
- // should be plumbed over IPC instead <http://crbug.com/265709>.
- policy.rules["com.apple.windowserver.active"] =
- sandbox::Rule(sandbox::POLICY_ALLOW);
-
- // Allow access to launchservicesd on 10.10+ otherwise the renderer will crash
- // attempting to get its ASN. http://crbug.com/533537
- if (base::mac::IsAtLeastOS10_10()) {
- policy.rules["com.apple.coreservices.launchservicesd"] =
- sandbox::Rule(sandbox::POLICY_ALLOW);
- }
-
- sandbox_->RegisterSandboxPolicy(SANDBOX_TYPE_RENDERER, policy);
-}
-
-void BootstrapSandboxManager::AddBaselinePolicy(
- sandbox::BootstrapSandboxPolicy* policy) {
- auto& rules = policy->rules;
-
- // Allow the child to send its task port to the MachBroker.
- rules[MachBroker::GetMachPortName()] = sandbox::Rule(sandbox::POLICY_ALLOW);
-
- // Allow logging to the syslog.
- rules["com.apple.system.logger"] = sandbox::Rule(sandbox::POLICY_ALLOW);
-}
-
-} // namespace content
diff --git a/content/browser/bootstrap_sandbox_manager_mac.h b/content/browser/bootstrap_sandbox_manager_mac.h
deleted file mode 100644
index 33bdad3..0000000
--- a/content/browser/bootstrap_sandbox_manager_mac.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_BOOTSTRAP_SANDBOX_MANAGER_MAC_H_
-#define CONTENT_BROWSER_BOOTSTRAP_SANDBOX_MANAGER_MAC_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "content/public/browser/browser_child_process_observer.h"
-#include "content/public/browser/render_process_host_observer.h"
-#include "content/public/common/sandbox_type.h"
-
-namespace sandbox {
-class BootstrapSandbox;
-struct BootstrapSandboxPolicy;
-}
-
-namespace content {
-
-// This class is responsible for creating the BootstrapSandbox global
-// singleton, as well as registering all associated policies with it.
-//
-// This class is thread-safe.
-class BootstrapSandboxManager : public BrowserChildProcessObserver,
- public RenderProcessHostObserver {
- public:
- // Whether or not the bootstrap sandbox should be enabled globally.
- static bool ShouldEnable();
-
- // Gets the singleton instance. The first call to this function, which
- // instantiates the object, must be on the UI thread.
- static BootstrapSandboxManager* GetInstance();
-
- // Whether or not the bootstrap sandbox applies to the given sandbox type.
- bool EnabledForSandbox(SandboxType sandbox_type);
-
- // BrowserChildProcessObserver:
- void BrowserChildProcessHostDisconnected(
- const ChildProcessData& data) override;
- void BrowserChildProcessCrashed(
- const ChildProcessData& data,
- int exit_code) override;
-
- // RenderProcessHostObserver:
- void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override;
-
- sandbox::BootstrapSandbox* sandbox() const { return sandbox_.get(); }
-
- private:
- friend struct base::DefaultSingletonTraits<BootstrapSandboxManager>;
- BootstrapSandboxManager();
- ~BootstrapSandboxManager() override;
-
- void RegisterSandboxPolicies();
- void RegisterRendererPolicy();
-
- void AddBaselinePolicy(sandbox::BootstrapSandboxPolicy* policy);
-
- std::unique_ptr<sandbox::BootstrapSandbox> sandbox_;
-
- DISALLOW_COPY_AND_ASSIGN(BootstrapSandboxManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_BOOTSTRAP_SANDBOX_MANAGER_MAC_H_
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 31a250f..7c84a5e8 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -152,7 +152,6 @@
#if defined(OS_MACOSX)
#include "base/allocator/allocator_interception_mac.h"
#include "base/memory/memory_pressure_monitor_mac.h"
-#include "content/browser/bootstrap_sandbox_manager_mac.h"
#include "content/browser/cocoa/system_hotkey_helper_mac.h"
#include "content/browser/mach_broker_mac.h"
#include "content/browser/renderer_host/browser_compositor_view_mac.h"
@@ -783,14 +782,6 @@
}
#endif
-#if defined(OS_MACOSX)
- if (BootstrapSandboxManager::ShouldEnable()) {
- TRACE_EVENT0("startup",
- "BrowserMainLoop::Subsystem:BootstrapSandbox");
- CHECK(BootstrapSandboxManager::GetInstance());
- }
-#endif
-
if (parsed_command_line_.HasSwitch(
switches::kEnableAggressiveDOMStorageFlushing)) {
TRACE_EVENT0("startup",
diff --git a/content/browser/child_process_launcher_helper_mac.cc b/content/browser/child_process_launcher_helper_mac.cc
index 8da7dfb..463f147 100644
--- a/content/browser/child_process_launcher_helper_mac.cc
+++ b/content/browser/child_process_launcher_helper_mac.cc
@@ -7,7 +7,6 @@
#include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "base/posix/global_descriptors.h"
-#include "content/browser/bootstrap_sandbox_manager_mac.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/child_process_launcher_helper.h"
#include "content/browser/child_process_launcher_helper_posix.h"
@@ -21,8 +20,6 @@
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "sandbox/mac/bootstrap_sandbox.h"
-#include "sandbox/mac/pre_exec_delegate.h"
#include "sandbox/mac/seatbelt_exec.h"
namespace content {
@@ -95,19 +92,6 @@
// Make sure the MachBroker is running, and inform it to expect a check-in
// from the new process.
broker->EnsureRunning();
-
- const SandboxType sandbox_type = delegate_->GetSandboxType();
- std::unique_ptr<sandbox::PreExecDelegate> pre_exec_delegate;
- if (BootstrapSandboxManager::ShouldEnable()) {
- BootstrapSandboxManager* sandbox_manager =
- BootstrapSandboxManager::GetInstance();
- if (sandbox_manager->EnabledForSandbox(sandbox_type)) {
- pre_exec_delegate = sandbox_manager->sandbox()->NewClient(sandbox_type);
- }
- }
- // options now owns the pre_exec_delegate which will be delete on
- // AfterLaunchOnLauncherThread below.
- options->pre_exec_delegate = pre_exec_delegate.release();
}
ChildProcessLauncherHelper::Process
@@ -127,18 +111,9 @@
void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
const ChildProcessLauncherHelper::Process& process,
const base::LaunchOptions& options) {
- std::unique_ptr<sandbox::PreExecDelegate> pre_exec_delegate =
- base::WrapUnique(static_cast<sandbox::PreExecDelegate*>(
- options.pre_exec_delegate));
-
MachBroker* broker = MachBroker::GetInstance();
if (process.process.IsValid()) {
broker->AddPlaceholderForPid(process.process.Pid(), child_process_id());
- } else {
- if (pre_exec_delegate) {
- BootstrapSandboxManager::GetInstance()->sandbox()->RevokeToken(
- pre_exec_delegate->sandbox_token());
- }
}
// After updating the broker, release the lock and let the child's message be
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index b0aad8f4..9269c57 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -227,7 +227,6 @@
#endif
#if defined(OS_MACOSX)
-#include "content/browser/bootstrap_sandbox_manager_mac.h"
#include "content/browser/mach_broker_mac.h"
#endif
@@ -1326,10 +1325,6 @@
GetID(), storage_partition_impl_->GetServiceWorkerContext()));
AddObserver(indexed_db_factory_.get());
-#if defined(OS_MACOSX)
- if (BootstrapSandboxManager::ShouldEnable())
- AddObserver(BootstrapSandboxManager::GetInstance());
-#endif
InitializeChannelProxy();
}
diff --git a/sandbox/BUILD.gn b/sandbox/BUILD.gn
index bb5e767..82b42e8 100644
--- a/sandbox/BUILD.gn
+++ b/sandbox/BUILD.gn
@@ -21,7 +21,6 @@
]
} else if (is_mac) {
public_deps = [
- "//sandbox/mac:sandbox",
"//sandbox/mac:seatbelt",
]
} else if (is_linux || is_android) {
diff --git a/sandbox/mac/BUILD.gn b/sandbox/mac/BUILD.gn
index ab446273..e3f264c 100644
--- a/sandbox/mac/BUILD.gn
+++ b/sandbox/mac/BUILD.gn
@@ -6,36 +6,6 @@
import("//testing/test.gni")
import("//third_party/protobuf/proto_library.gni")
-component("sandbox") {
- sources = [
- "bootstrap_sandbox.cc",
- "bootstrap_sandbox.h",
- "launchd_interception_server.cc",
- "launchd_interception_server.h",
- "mach_message_server.cc",
- "mach_message_server.h",
- "message_server.h",
- "os_compatibility.cc",
- "os_compatibility.h",
- "policy.cc",
- "policy.h",
- "pre_exec_delegate.cc",
- "pre_exec_delegate.h",
- "xpc.h",
- "xpc_message_server.cc",
- "xpc_message_server.h",
- ]
-
- defines = [ "SANDBOX_IMPLEMENTATION" ]
- libs = [ "bsm" ]
- public_deps = [
- "//sandbox:sandbox_export",
- ]
- deps = [
- "//base",
- ]
-}
-
proto_library("seatbelt_proto") {
visibility = [ ":*" ]
sources = [
@@ -66,12 +36,9 @@
test("sandbox_mac_unittests") {
sources = [
- "bootstrap_sandbox_unittest.mm",
- "policy_unittest.cc",
"sandbox_mac_compiler_unittest.mm",
"sandbox_mac_compiler_v2_unittest.mm",
"sandbox_mac_seatbelt_exec_unittest.cc",
- "xpc_message_server_unittest.cc",
]
libs = [
@@ -80,7 +47,6 @@
]
deps = [
- ":sandbox",
":seatbelt",
":seatbelt_proto",
"//base",
diff --git a/sandbox/mac/bootstrap_sandbox.cc b/sandbox/mac/bootstrap_sandbox.cc
deleted file mode 100644
index f4fb1fa..0000000
--- a/sandbox/mac/bootstrap_sandbox.cc
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/mac/bootstrap_sandbox.h"
-
-#include <servers/bootstrap.h>
-#include <stdint.h>
-#include <unistd.h>
-
-#include "base/logging.h"
-#include "base/mac/foundation_util.h"
-#include "base/mac/mach_logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/rand_util.h"
-#include "base/strings/stringprintf.h"
-#include "sandbox/mac/launchd_interception_server.h"
-#include "sandbox/mac/pre_exec_delegate.h"
-
-namespace sandbox {
-
-namespace {
-
-struct SandboxCheckInRequest {
- mach_msg_header_t header;
- uint64_t token;
-};
-
-struct SandboxCheckInReply {
- mach_msg_header_t header;
- mach_msg_body_t body;
- mach_msg_port_descriptor_t bootstrap_port;
-};
-
-class ScopedCallMachMsgDestroy {
- public:
- explicit ScopedCallMachMsgDestroy(mach_msg_header_t* message)
- : message_(message) {}
-
- ~ScopedCallMachMsgDestroy() {
- if (message_)
- mach_msg_destroy(message_);
- }
-
- void Disarm() {
- message_ = nullptr;
- }
-
- private:
- mach_msg_header_t* message_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedCallMachMsgDestroy);
-};
-
-} // namespace
-
-// static
-std::unique_ptr<BootstrapSandbox> BootstrapSandbox::Create() {
- std::unique_ptr<BootstrapSandbox> null; // Used for early returns.
- std::unique_ptr<BootstrapSandbox> sandbox(new BootstrapSandbox());
- sandbox->launchd_server_.reset(new LaunchdInterceptionServer(sandbox.get()));
-
- // Check in with launchd to get the receive right for the server that is
- // published in the bootstrap namespace.
- mach_port_t port = MACH_PORT_NULL;
- kern_return_t kr = bootstrap_check_in(bootstrap_port,
- sandbox->server_bootstrap_name().c_str(), &port);
- if (kr != KERN_SUCCESS) {
- BOOTSTRAP_LOG(ERROR, kr)
- << "Failed to bootstrap_check_in the sandbox server.";
- return null;
- }
- sandbox->check_in_port_.reset(port);
-
- BootstrapSandbox* __block sandbox_ptr = sandbox.get();
- sandbox->check_in_server_.reset(new base::DispatchSourceMach(
- "org.chromium.sandbox.BootstrapClientManager",
- sandbox->check_in_port_.get(),
- ^{ sandbox_ptr->HandleChildCheckIn(); }));
- sandbox->check_in_server_->Resume();
-
- // Start the sandbox server.
- if (!sandbox->launchd_server_->Initialize(MACH_PORT_NULL))
- return null;
-
- return sandbox;
-}
-
-// Warning: This function must be safe to call in
-// PreExecDelegate::RunAsyncSafe().
-// static
-bool BootstrapSandbox::ClientCheckIn(mach_port_t sandbox_server_port,
- uint64_t sandbox_token,
- mach_port_t* new_bootstrap_port) {
- // Create a reply port for the check in message.
- mach_port_t reply_port;
- kern_return_t kr = mach_port_allocate(mach_task_self(),
- MACH_PORT_RIGHT_RECEIVE,
- &reply_port);
- if (kr != KERN_SUCCESS) {
- RAW_LOG(ERROR, "ClientCheckIn: mach_port_allocate failed");
- return false;
- }
- base::mac::ScopedMachReceiveRight scoped_reply_port(reply_port);
-
- // Check in with the sandbox server, presenting the |sandbox_token| in
- // exchange for a new task bootstrap port.
- union {
- SandboxCheckInRequest request;
- struct {
- SandboxCheckInReply reply;
- mach_msg_trailer_t trailer;
- };
- } msg = {};
- msg.request.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
- MACH_MSG_TYPE_MAKE_SEND_ONCE);
- msg.request.header.msgh_remote_port = sandbox_server_port;
- msg.request.header.msgh_local_port = reply_port;
- msg.request.header.msgh_size = sizeof(msg);
- msg.request.token = sandbox_token;
-
- kr = mach_msg(&msg.request.header, MACH_SEND_MSG | MACH_RCV_MSG,
- sizeof(msg.request), sizeof(msg), reply_port,
- MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- if (kr == KERN_SUCCESS) {
- *new_bootstrap_port = msg.reply.bootstrap_port.name;
- return true;
- } else {
- RAW_LOG(ERROR, "ClientCheckIn: mach_msg failed");
- return false;
- }
-}
-
-BootstrapSandbox::~BootstrapSandbox() {
-}
-
-void BootstrapSandbox::RegisterSandboxPolicy(
- int sandbox_policy_id,
- const BootstrapSandboxPolicy& policy) {
- CHECK(IsPolicyValid(policy));
- base::AutoLock lock(lock_);
- DCHECK(policies_.find(sandbox_policy_id) == policies_.end());
- policies_.insert(std::make_pair(sandbox_policy_id, policy));
-}
-
-std::unique_ptr<PreExecDelegate> BootstrapSandbox::NewClient(
- int sandbox_policy_id) {
- base::AutoLock lock(lock_);
-
- DCHECK(policies_.find(sandbox_policy_id) != policies_.end());
-
- uint64_t token;
- while (true) {
- token = base::RandUint64();
- if (awaiting_processes_.find(token) == awaiting_processes_.end())
- break;
- }
-
- awaiting_processes_[token] = sandbox_policy_id;
- return base::MakeUnique<PreExecDelegate>(server_bootstrap_name_, token);
-}
-
-void BootstrapSandbox::RevokeToken(uint64_t token) {
- base::AutoLock lock(lock_);
- const auto& it = awaiting_processes_.find(token);
- if (it != awaiting_processes_.end())
- awaiting_processes_.erase(it);
-}
-
-void BootstrapSandbox::InvalidateClient(base::ProcessHandle handle) {
- base::AutoLock lock(lock_);
- const auto& it = sandboxed_processes_.find(handle);
- if (it != sandboxed_processes_.end())
- sandboxed_processes_.erase(it);
-}
-
-const BootstrapSandboxPolicy* BootstrapSandbox::PolicyForProcess(
- pid_t pid) const {
- base::AutoLock lock(lock_);
- const auto& process = sandboxed_processes_.find(pid);
- if (process != sandboxed_processes_.end()) {
- return &policies_.find(process->second)->second;
- }
-
- return nullptr;
-}
-
-BootstrapSandbox::BootstrapSandbox()
- : server_bootstrap_name_(
- base::StringPrintf("%s.sandbox.%d", base::mac::BaseBundleID(),
- getpid())),
- real_bootstrap_port_(MACH_PORT_NULL) {
- mach_port_t port = MACH_PORT_NULL;
- kern_return_t kr = task_get_special_port(
- mach_task_self(), TASK_BOOTSTRAP_PORT, &port);
- MACH_CHECK(kr == KERN_SUCCESS, kr);
- real_bootstrap_port_.reset(port);
-}
-
-void BootstrapSandbox::HandleChildCheckIn() {
- struct {
- SandboxCheckInRequest request;
- mach_msg_audit_trailer_t trailer;
- } msg = {};
- msg.request.header.msgh_local_port = check_in_port_.get();
- msg.request.header.msgh_size = sizeof(msg.request);
- const mach_msg_option_t kOptions = MACH_RCV_MSG |
- MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) |
- MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT);
- kern_return_t kr = mach_msg(&msg.request.header, kOptions, 0,
- sizeof(msg), check_in_port_.get(),
- MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- if (kr != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "HandleChildCheckIn mach_msg MACH_RCV_MSG";
- return;
- }
-
- // Call mach_msg_destroy to clean up the reply send-once right.
- ScopedCallMachMsgDestroy message_destroyer(&msg.request.header);
- pid_t client_pid = audit_token_to_pid(msg.trailer.msgh_audit);
- {
- base::AutoLock lock(lock_);
-
- auto awaiting_it = awaiting_processes_.find(msg.request.token);
- if (awaiting_it == awaiting_processes_.end()) {
- LOG(ERROR) << "Received sandbox check-in message from unknown client.";
- return;
- }
-
- CHECK(sandboxed_processes_.find(client_pid) == sandboxed_processes_.end());
- sandboxed_processes_[client_pid] = awaiting_it->second;
- awaiting_processes_.erase(awaiting_it);
- }
-
- SandboxCheckInReply reply = {};
- reply.header.msgh_bits = MACH_MSGH_BITS_REMOTE(msg.request.header.msgh_bits) |
- MACH_MSGH_BITS_COMPLEX;
- reply.header.msgh_remote_port = msg.request.header.msgh_remote_port;
- reply.header.msgh_size = sizeof(reply);
- reply.body.msgh_descriptor_count = 1;
- reply.bootstrap_port.name = launchd_server_->server_port();
- reply.bootstrap_port.disposition = MACH_MSG_TYPE_MAKE_SEND;
- reply.bootstrap_port.type = MACH_MSG_PORT_DESCRIPTOR;
-
- kr = mach_msg(&reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT,
- sizeof(reply), 0, MACH_PORT_NULL, 100 /*ms*/, MACH_PORT_NULL);
- if (kr == KERN_SUCCESS) {
- message_destroyer.Disarm(); // The send-once was consumed at mach_msg().
- } else {
- {
- base::AutoLock lock(lock_);
- sandboxed_processes_.erase(client_pid);
- }
- MACH_LOG(ERROR, kr) << "HandleChildCheckIn mach_msg MACH_SEND_MSG";
- }
-}
-
-} // namespace sandbox
diff --git a/sandbox/mac/bootstrap_sandbox.h b/sandbox/mac/bootstrap_sandbox.h
deleted file mode 100644
index 793649ea..0000000
--- a/sandbox/mac/bootstrap_sandbox.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_
-#define SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_
-
-#include <mach/mach.h>
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "base/mac/dispatch_source_mach.h"
-#include "base/mac/scoped_mach_port.h"
-#include "base/process/process_handle.h"
-#include "base/synchronization/lock.h"
-#include "sandbox/mac/policy.h"
-#include "sandbox/sandbox_export.h"
-
-namespace sandbox {
-
-class LaunchdInterceptionServer;
-class PreExecDelegate;
-
-// The BootstrapSandbox is a second-layer sandbox for Mac. It is used to limit
-// the bootstrap namespace attack surface of child processes. The parent
-// process creates an instance of this class and registers policies that it
-// can enforce on its children.
-//
-// With this sandbox, the parent process must create the client using the
-// sandbox's PreExecDelegate, which will replace the bootstrap port of the
-// child process. Requests from the child that would normally go to launchd
-// are filtered based on the specified per-process policies. If a request is
-// permitted by the policy, it is forwarded on to launchd for servicing. If it
-// is not, then the sandbox will reply with a primitive that does not grant
-// additional capabilities to the receiver.
-//
-// When the parent is ready to fork a new child process with this sandbox
-// being enforced, it should use NewClient() to create a PreExecDelegate for
-// a sandbox policy ID and set it to the base::LaunchOptions.pre_exec_delegate.
-//
-// When a child process exits, the parent should call InvalidateClient() to
-// clean up any mappings in this class.
-//
-// All methods of this class may be called from any thread.
-class SANDBOX_EXPORT BootstrapSandbox {
- public:
- // Creates a new sandbox manager. Returns NULL on failure.
- static std::unique_ptr<BootstrapSandbox> Create();
-
- // For use in newly created child processes. Checks in with the bootstrap
- // sandbox manager running in the parent process. |sandbox_server_port| is
- // the Mach send right to the sandbox |check_in_server_| (in the child).
- // |sandbox_token| is the assigned token. On return, |bootstrap_port| is set
- // to a new Mach send right to be used in the child as the task's bootstrap
- // port.
- static bool ClientCheckIn(mach_port_t sandbox_server_port,
- uint64_t sandbox_token,
- mach_port_t* bootstrap_port);
-
- ~BootstrapSandbox();
-
- // Registers a bootstrap policy associated it with an identifier. The
- // |sandbox_policy_id| must be greater than 0.
- void RegisterSandboxPolicy(int sandbox_policy_id,
- const BootstrapSandboxPolicy& policy);
-
- // Creates a new PreExecDelegate to pass to base::LaunchOptions. This will
- // enforce the policy with |sandbox_policy_id| on the new process.
- std::unique_ptr<PreExecDelegate> NewClient(int sandbox_policy_id);
-
- // If a client did not launch properly, the sandbox provided to the
- // PreExecDelegate should be invalidated using this method.
- void RevokeToken(uint64_t token);
-
- // Called in the parent when a process has died. It cleans up the references
- // to the process.
- void InvalidateClient(base::ProcessHandle handle);
-
- // Looks up the policy for a given process ID. If no policy is associated
- // with the |pid|, this returns NULL.
- const BootstrapSandboxPolicy* PolicyForProcess(pid_t pid) const;
-
- std::string server_bootstrap_name() const { return server_bootstrap_name_; }
- mach_port_t real_bootstrap_port() const { return real_bootstrap_port_.get(); }
-
- private:
- BootstrapSandbox();
-
- // Dispatch callout for when a client sends a message on the
- // |check_in_port_|. If the client message is valid, it will assign the
- // client from |awaiting_processes_| to |sandboxed_processes_|.
- void HandleChildCheckIn();
-
- // The name in the system bootstrap server by which the |server_|'s port
- // is known.
- const std::string server_bootstrap_name_;
-
- // The original bootstrap port of the process, which is connected to the
- // real launchd server.
- base::mac::ScopedMachSendRight real_bootstrap_port_;
-
- // The |lock_| protects all the following variables.
- mutable base::Lock lock_;
-
- // All the policies that have been registered with this sandbox manager.
- std::map<int, const BootstrapSandboxPolicy> policies_;
-
- // The association between process ID and sandbox policy ID.
- std::map<base::ProcessHandle, int> sandboxed_processes_;
-
- // The association between a new process' sandbox token and its policy ID.
- // The entry is removed after the process checks in, and the mapping moves
- // to |sandboxed_processes_|.
- std::map<uint64_t, int> awaiting_processes_;
-
- // A Mach IPC message server that is used to intercept and filter bootstrap
- // requests.
- std::unique_ptr<LaunchdInterceptionServer> launchd_server_;
-
- // The port and dispatch source for receiving client check in messages sent
- // via ClientCheckIn().
- base::mac::ScopedMachReceiveRight check_in_port_;
- std::unique_ptr<base::DispatchSourceMach> check_in_server_;
-};
-
-} // namespace sandbox
-
-#endif // SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_
diff --git a/sandbox/mac/bootstrap_sandbox_unittest.mm b/sandbox/mac/bootstrap_sandbox_unittest.mm
deleted file mode 100644
index a6225a9..0000000
--- a/sandbox/mac/bootstrap_sandbox_unittest.mm
+++ /dev/null
@@ -1,549 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/mac/bootstrap_sandbox.h"
-
-#include <CoreFoundation/CoreFoundation.h>
-#import <Foundation/Foundation.h>
-#include <mach/mach.h>
-#include <servers/bootstrap.h>
-
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/mach_logging.h"
-#include "base/mac/scoped_mach_port.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/process/kill.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/test_timeouts.h"
-#include "sandbox/mac/pre_exec_delegate.h"
-#include "sandbox/mac/xpc.h"
-#import "testing/gtest_mac.h"
-#include "testing/multiprocess_func_list.h"
-
-NSString* const kTestNotification = @"org.chromium.bootstrap_sandbox_test";
-
-@interface DistributedNotificationObserver : NSObject {
- @private
- int receivedCount_;
- base::scoped_nsobject<NSString> object_;
-}
-- (int)receivedCount;
-- (NSString*)object;
-- (void)waitForNotification;
-@end
-
-@implementation DistributedNotificationObserver
-- (id)init {
- if ((self = [super init])) {
- [[NSDistributedNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(observeNotification:)
- name:kTestNotification
- object:nil];
- }
- return self;
-}
-
-- (void)dealloc {
- [[NSDistributedNotificationCenter defaultCenter]
- removeObserver:self
- name:kTestNotification
- object:nil];
- [super dealloc];
-}
-
-- (int)receivedCount {
- return receivedCount_;
-}
-
-- (NSString*)object {
- return object_.get();
-}
-
-- (void)waitForNotification {
- object_.reset();
- CFRunLoopRunInMode(kCFRunLoopDefaultMode,
- TestTimeouts::action_timeout().InSeconds(), false);
-}
-
-- (void)observeNotification:(NSNotification*)notification {
- ++receivedCount_;
- object_.reset([[notification object] copy]);
- CFRunLoopStop(CFRunLoopGetCurrent());
-}
-@end
-
-////////////////////////////////////////////////////////////////////////////////
-
-namespace sandbox {
-
-class BootstrapSandboxTest : public base::MultiProcessTest {
- public:
- void SetUp() override {
- base::MultiProcessTest::SetUp();
-
- sandbox_ = BootstrapSandbox::Create();
- ASSERT_TRUE(sandbox_.get());
- }
-
- BootstrapSandboxPolicy BaselinePolicy() {
- BootstrapSandboxPolicy policy;
- policy.rules["com.apple.cfprefsd.daemon"] = Rule(POLICY_ALLOW);
- return policy;
- }
-
- void RunChildWithPolicy(int policy_id,
- const char* child_name,
- base::ProcessHandle* out_pid) {
- std::unique_ptr<PreExecDelegate> pre_exec_delegate(
- sandbox_->NewClient(policy_id));
-
- base::LaunchOptions options;
- options.pre_exec_delegate = pre_exec_delegate.get();
-
- base::Process process = SpawnChildWithOptions(child_name, options);
- ASSERT_TRUE(process.IsValid());
- int code = 0;
- EXPECT_TRUE(process.WaitForExit(&code));
- EXPECT_EQ(0, code);
- if (out_pid)
- *out_pid = process.Pid();
- }
-
- protected:
- std::unique_ptr<BootstrapSandbox> sandbox_;
-};
-
-const char kNotificationTestMain[] = "PostNotification";
-
-// Run the test without the sandbox.
-TEST_F(BootstrapSandboxTest, DistributedNotifications_Unsandboxed) {
- base::scoped_nsobject<DistributedNotificationObserver> observer(
- [[DistributedNotificationObserver alloc] init]);
-
- base::Process process = SpawnChild(kNotificationTestMain);
- ASSERT_TRUE(process.IsValid());
- int code = 0;
- EXPECT_TRUE(process.WaitForExit(&code));
- EXPECT_EQ(0, code);
-
- [observer waitForNotification];
- EXPECT_EQ(1, [observer receivedCount]);
- EXPECT_EQ(process.Pid(), [[observer object] intValue]);
-}
-
-// Run the test with the sandbox enabled without notifications on the policy
-// whitelist.
-TEST_F(BootstrapSandboxTest, DistributedNotifications_SandboxDeny) {
- if (base::mac::IsAtLeastOS10_12()) {
- LOG(ERROR) << "BootstrapSandbox does not work on macOS Sierra or later.";
- return;
- }
-
- base::scoped_nsobject<DistributedNotificationObserver> observer(
- [[DistributedNotificationObserver alloc] init]);
-
- sandbox_->RegisterSandboxPolicy(1, BaselinePolicy());
- RunChildWithPolicy(1, kNotificationTestMain, NULL);
-
- [observer waitForNotification];
- EXPECT_EQ(0, [observer receivedCount]);
- EXPECT_EQ(nil, [observer object]);
-}
-
-// Run the test with notifications permitted.
-TEST_F(BootstrapSandboxTest, DistributedNotifications_SandboxAllow) {
- if (base::mac::IsAtLeastOS10_12()) {
- LOG(ERROR) << "BootstrapSandbox does not work on macOS Sierra or later.";
- return;
- }
-
- base::scoped_nsobject<DistributedNotificationObserver> observer(
- [[DistributedNotificationObserver alloc] init]);
-
- BootstrapSandboxPolicy policy(BaselinePolicy());
- // 10.9:
- policy.rules["com.apple.distributed_notifications@Uv3"] = Rule(POLICY_ALLOW);
- policy.rules["com.apple.distributed_notifications@1v3"] = Rule(POLICY_ALLOW);
- // 10.6:
- policy.rules["com.apple.system.notification_center"] = Rule(POLICY_ALLOW);
- policy.rules["com.apple.distributed_notifications.2"] = Rule(POLICY_ALLOW);
- sandbox_->RegisterSandboxPolicy(2, policy);
-
- base::ProcessHandle pid;
- RunChildWithPolicy(2, kNotificationTestMain, &pid);
-
- [observer waitForNotification];
- EXPECT_EQ(1, [observer receivedCount]);
- EXPECT_EQ(pid, [[observer object] intValue]);
-}
-
-MULTIPROCESS_TEST_MAIN(PostNotification) {
- [[NSDistributedNotificationCenter defaultCenter]
- postNotificationName:kTestNotification
- object:[NSString stringWithFormat:@"%d", getpid()]];
- return 0;
-}
-
-const char kTestServer[] = "org.chromium.test_bootstrap_server";
-
-TEST_F(BootstrapSandboxTest, PolicyDenyError) {
- if (base::mac::IsAtLeastOS10_12()) {
- LOG(ERROR) << "BootstrapSandbox does not work on macOS Sierra or later.";
- return;
- }
- BootstrapSandboxPolicy policy(BaselinePolicy());
- policy.rules[kTestServer] = Rule(POLICY_DENY_ERROR);
- sandbox_->RegisterSandboxPolicy(1, policy);
-
- RunChildWithPolicy(1, "PolicyDenyError", NULL);
-}
-
-MULTIPROCESS_TEST_MAIN(PolicyDenyError) {
- mach_port_t port = MACH_PORT_NULL;
- kern_return_t kr = bootstrap_look_up(bootstrap_port, kTestServer,
- &port);
- CHECK_EQ(BOOTSTRAP_UNKNOWN_SERVICE, kr);
- CHECK(port == MACH_PORT_NULL);
-
- kr = bootstrap_look_up(bootstrap_port, "org.chromium.some_other_server",
- &port);
- CHECK_EQ(BOOTSTRAP_UNKNOWN_SERVICE, kr);
- CHECK(port == MACH_PORT_NULL);
-
- return 0;
-}
-
-TEST_F(BootstrapSandboxTest, PolicyDenyDummyPort) {
- if (base::mac::IsAtLeastOS10_12()) {
- LOG(ERROR) << "BootstrapSandbox does not work on macOS Sierra or later.";
- return;
- }
- BootstrapSandboxPolicy policy(BaselinePolicy());
- policy.rules[kTestServer] = Rule(POLICY_DENY_DUMMY_PORT);
- sandbox_->RegisterSandboxPolicy(1, policy);
-
- RunChildWithPolicy(1, "PolicyDenyDummyPort", NULL);
-}
-
-MULTIPROCESS_TEST_MAIN(PolicyDenyDummyPort) {
- mach_port_t port = MACH_PORT_NULL;
- kern_return_t kr = bootstrap_look_up(bootstrap_port, kTestServer,
- &port);
- CHECK_EQ(KERN_SUCCESS, kr);
- CHECK(port != MACH_PORT_NULL);
- return 0;
-}
-
-struct SubstitutePortAckSend {
- mach_msg_header_t header;
- char buf[32];
-};
-
-struct SubstitutePortAckRecv : public SubstitutePortAckSend {
- mach_msg_trailer_t trailer;
-};
-
-const char kSubstituteAck[] = "Hello, this is doge!";
-
-TEST_F(BootstrapSandboxTest, PolicySubstitutePort) {
- if (base::mac::IsAtLeastOS10_12()) {
- LOG(ERROR) << "BootstrapSandbox does not work on macOS Sierra or later.";
- return;
- }
-
- mach_port_t task = mach_task_self();
-
- mach_port_t port;
- ASSERT_EQ(KERN_SUCCESS, mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE,
- &port));
- base::mac::ScopedMachReceiveRight scoped_port(port);
-
- mach_port_urefs_t send_rights = 0;
- ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
- &send_rights));
- EXPECT_EQ(0u, send_rights);
-
- ASSERT_EQ(KERN_SUCCESS, mach_port_insert_right(task, port, port,
- MACH_MSG_TYPE_MAKE_SEND));
- base::mac::ScopedMachSendRight scoped_port_send(port);
-
- send_rights = 0;
- ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
- &send_rights));
- EXPECT_EQ(1u, send_rights);
-
- BootstrapSandboxPolicy policy(BaselinePolicy());
- policy.rules[kTestServer] = Rule(port);
- sandbox_->RegisterSandboxPolicy(1, policy);
-
- RunChildWithPolicy(1, "PolicySubstitutePort", NULL);
-
- struct SubstitutePortAckRecv msg;
- bzero(&msg, sizeof(msg));
- msg.header.msgh_size = sizeof(msg);
- msg.header.msgh_local_port = port;
- kern_return_t kr = mach_msg(&msg.header, MACH_RCV_MSG, 0,
- msg.header.msgh_size, port,
- TestTimeouts::tiny_timeout().InMilliseconds(), MACH_PORT_NULL);
- EXPECT_EQ(KERN_SUCCESS, kr);
-
- send_rights = 0;
- ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
- &send_rights));
- EXPECT_EQ(1u, send_rights);
-
- EXPECT_EQ(0, strncmp(kSubstituteAck, msg.buf, sizeof(msg.buf)));
-}
-
-MULTIPROCESS_TEST_MAIN(PolicySubstitutePort) {
- mach_port_t port = MACH_PORT_NULL;
- kern_return_t kr = bootstrap_look_up(bootstrap_port, kTestServer, &port);
- CHECK_EQ(KERN_SUCCESS, kr);
- CHECK(port != MACH_PORT_NULL);
-
- struct SubstitutePortAckSend msg;
- bzero(&msg, sizeof(msg));
- msg.header.msgh_size = sizeof(msg);
- msg.header.msgh_remote_port = port;
- msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND);
- strncpy(msg.buf, kSubstituteAck, sizeof(msg.buf));
-
- CHECK_EQ(KERN_SUCCESS, mach_msg_send(&msg.header));
-
- return 0;
-}
-
-TEST_F(BootstrapSandboxTest, ForwardMessageInProcess) {
- mach_port_t task = mach_task_self();
-
- mach_port_t port;
- ASSERT_EQ(KERN_SUCCESS, mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE,
- &port));
- base::mac::ScopedMachReceiveRight scoped_port_recv(port);
-
- mach_port_urefs_t send_rights = 0;
- ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
- &send_rights));
- EXPECT_EQ(0u, send_rights);
-
- ASSERT_EQ(KERN_SUCCESS, mach_port_insert_right(task, port, port,
- MACH_MSG_TYPE_MAKE_SEND));
- base::mac::ScopedMachSendRight scoped_port_send(port);
-
- send_rights = 0;
- ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
- &send_rights));
- EXPECT_EQ(1u, send_rights);
-
- mach_port_t bp;
- ASSERT_EQ(KERN_SUCCESS, task_get_bootstrap_port(task, &bp));
- base::mac::ScopedMachSendRight scoped_bp(bp);
-
- char service_name[] = "org.chromium.sandbox.test.ForwardMessageInProcess";
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- kern_return_t kr = bootstrap_register(bp, service_name, port);
-#pragma GCC diagnostic pop
- EXPECT_EQ(KERN_SUCCESS, kr);
-
- send_rights = 0;
- ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
- &send_rights));
- EXPECT_EQ(1u, send_rights);
-
- mach_port_t service_port;
- EXPECT_EQ(KERN_SUCCESS, bootstrap_look_up(bp, service_name, &service_port));
- base::mac::ScopedMachSendRight scoped_service_port(service_port);
-
- send_rights = 0;
- ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
- &send_rights));
- EXPECT_EQ(2u, send_rights);
-}
-
-const char kDefaultRuleTestAllow[] =
- "org.chromium.sandbox.test.DefaultRuleAllow";
-const char kDefaultRuleTestDeny[] =
- "org.chromium.sandbox.test.DefaultRuleAllow.Deny";
-
-TEST_F(BootstrapSandboxTest, DefaultRuleAllow) {
- if (base::mac::IsAtLeastOS10_12()) {
- LOG(ERROR) << "BootstrapSandbox does not work on macOS Sierra or later.";
- return;
- }
-
- mach_port_t task = mach_task_self();
-
- mach_port_t port;
- ASSERT_EQ(KERN_SUCCESS, mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE,
- &port));
- base::mac::ScopedMachReceiveRight scoped_port_recv(port);
-
- ASSERT_EQ(KERN_SUCCESS, mach_port_insert_right(task, port, port,
- MACH_MSG_TYPE_MAKE_SEND));
- base::mac::ScopedMachSendRight scoped_port_send(port);
-
- BootstrapSandboxPolicy policy;
- policy.default_rule = Rule(POLICY_ALLOW);
- policy.rules[kDefaultRuleTestAllow] = Rule(port);
- policy.rules[kDefaultRuleTestDeny] = Rule(POLICY_DENY_ERROR);
- sandbox_->RegisterSandboxPolicy(3, policy);
-
- base::scoped_nsobject<DistributedNotificationObserver> observer(
- [[DistributedNotificationObserver alloc] init]);
-
- int pid = 0;
- RunChildWithPolicy(3, "DefaultRuleAllow", &pid);
- EXPECT_GT(pid, 0);
-
- [observer waitForNotification];
- EXPECT_EQ(1, [observer receivedCount]);
- EXPECT_EQ(pid, [[observer object] intValue]);
-
- struct SubstitutePortAckRecv msg;
- bzero(&msg, sizeof(msg));
- msg.header.msgh_size = sizeof(msg);
- msg.header.msgh_local_port = port;
- kern_return_t kr = mach_msg(&msg.header, MACH_RCV_MSG, 0,
- msg.header.msgh_size, port,
- TestTimeouts::tiny_timeout().InMilliseconds(), MACH_PORT_NULL);
- EXPECT_EQ(KERN_SUCCESS, kr);
-
- EXPECT_EQ(0, strncmp(kSubstituteAck, msg.buf, sizeof(msg.buf)));
-}
-
-MULTIPROCESS_TEST_MAIN(DefaultRuleAllow) {
- [[NSDistributedNotificationCenter defaultCenter]
- postNotificationName:kTestNotification
- object:[NSString stringWithFormat:@"%d", getpid()]];
-
- mach_port_t port = MACH_PORT_NULL;
- CHECK_EQ(BOOTSTRAP_UNKNOWN_SERVICE, bootstrap_look_up(bootstrap_port,
- const_cast<char*>(kDefaultRuleTestDeny), &port));
- CHECK(port == MACH_PORT_NULL);
-
- CHECK_EQ(KERN_SUCCESS, bootstrap_look_up(bootstrap_port,
- const_cast<char*>(kDefaultRuleTestAllow), &port));
- CHECK(port != MACH_PORT_NULL);
-
- struct SubstitutePortAckSend msg;
- bzero(&msg, sizeof(msg));
- msg.header.msgh_size = sizeof(msg);
- msg.header.msgh_remote_port = port;
- msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND);
- strncpy(msg.buf, kSubstituteAck, sizeof(msg.buf));
-
- CHECK_EQ(KERN_SUCCESS, mach_msg_send(&msg.header));
-
- return 0;
-}
-
-TEST_F(BootstrapSandboxTest, ChildOutliveSandbox) {
- if (base::mac::IsAtLeastOS10_12()) {
- LOG(ERROR) << "BootstrapSandbox does not work on macOS Sierra or later.";
- return;
- }
-
- const int kTestPolicyId = 1;
- mach_port_t task = mach_task_self();
-
- // Create a server port.
- mach_port_t port;
- ASSERT_EQ(KERN_SUCCESS, mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE,
- &port));
- base::mac::ScopedMachReceiveRight scoped_port_recv(port);
-
- ASSERT_EQ(KERN_SUCCESS, mach_port_insert_right(task, port, port,
- MACH_MSG_TYPE_MAKE_SEND));
- base::mac::ScopedMachSendRight scoped_port_send(port);
-
- // Set up the policy and register the port.
- BootstrapSandboxPolicy policy(BaselinePolicy());
- policy.rules["sync"] = Rule(port);
- sandbox_->RegisterSandboxPolicy(kTestPolicyId, policy);
-
- // Launch the child.
- std::unique_ptr<PreExecDelegate> pre_exec_delegate(
- sandbox_->NewClient(kTestPolicyId));
- base::LaunchOptions options;
- options.pre_exec_delegate = pre_exec_delegate.get();
- base::Process process = SpawnChildWithOptions("ChildOutliveSandbox", options);
- ASSERT_TRUE(process.IsValid());
-
- // Synchronize with the child.
- mach_msg_empty_rcv_t rcv_msg;
- bzero(&rcv_msg, sizeof(rcv_msg));
- kern_return_t kr = mach_msg(&rcv_msg.header, MACH_RCV_MSG, 0,
- sizeof(rcv_msg), port,
- TestTimeouts::tiny_timeout().InMilliseconds(), MACH_PORT_NULL);
- ASSERT_EQ(KERN_SUCCESS, kr) << mach_error_string(kr);
-
- // Destroy the sandbox.
- sandbox_.reset();
-
- // Synchronize again with the child.
- mach_msg_empty_send_t send_msg;
- bzero(&send_msg, sizeof(send_msg));
- send_msg.header.msgh_size = sizeof(send_msg);
- send_msg.header.msgh_remote_port = rcv_msg.header.msgh_remote_port;
- send_msg.header.msgh_bits =
- MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND_ONCE);
- kr = mach_msg(&send_msg.header, MACH_SEND_MSG, send_msg.header.msgh_size, 0,
- MACH_PORT_NULL, TestTimeouts::tiny_timeout().InMilliseconds(),
- MACH_PORT_NULL);
- EXPECT_EQ(KERN_SUCCESS, kr) << mach_error_string(kr);
-
- int code = 0;
- EXPECT_TRUE(process.WaitForExit(&code));
- EXPECT_EQ(0, code);
-}
-
-MULTIPROCESS_TEST_MAIN(ChildOutliveSandbox) {
- // Get the synchronization channel.
- mach_port_t port = MACH_PORT_NULL;
- CHECK_EQ(KERN_SUCCESS, bootstrap_look_up(bootstrap_port, "sync", &port));
-
- // Create a reply port.
- mach_port_t reply_port;
- CHECK_EQ(KERN_SUCCESS, mach_port_allocate(mach_task_self(),
- MACH_PORT_RIGHT_RECEIVE, &reply_port));
- base::mac::ScopedMachReceiveRight scoped_reply_port(reply_port);
-
- // Send a message to shutdown the sandbox.
- mach_msg_empty_send_t send_msg;
- bzero(&send_msg, sizeof(send_msg));
- send_msg.header.msgh_size = sizeof(send_msg);
- send_msg.header.msgh_local_port = reply_port;
- send_msg.header.msgh_remote_port = port;
- send_msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND,
- MACH_MSG_TYPE_MAKE_SEND_ONCE);
- kern_return_t kr = mach_msg_send(&send_msg.header);
- MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_msg_send";
-
- // Flood the server's message queue with messages. There should be some
- // pending when the sandbox is destroyed.
- for (int i = 0; i < 20; ++i) {
- mach_port_t tmp = MACH_PORT_NULL;
- std::string name = base::StringPrintf("test.%d", i);
- bootstrap_look_up(bootstrap_port, const_cast<char*>(name.c_str()), &tmp);
- }
-
- // Ack that the sandbox has been shutdown.
- mach_msg_empty_rcv_t rcv_msg;
- bzero(&rcv_msg, sizeof(rcv_msg));
- rcv_msg.header.msgh_size = sizeof(rcv_msg);
- rcv_msg.header.msgh_local_port = reply_port;
- kr = mach_msg_receive(&rcv_msg.header);
- MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_msg_receive";
-
- // Try to message the sandbox.
- bootstrap_look_up(bootstrap_port, "test", &port);
-
- return 0;
-}
-
-} // namespace sandbox
diff --git a/sandbox/mac/launchd_interception_server.cc b/sandbox/mac/launchd_interception_server.cc
deleted file mode 100644
index 167fbab5..0000000
--- a/sandbox/mac/launchd_interception_server.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/mac/launchd_interception_server.h"
-
-#include <servers/bootstrap.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/mach_logging.h"
-#include "sandbox/mac/bootstrap_sandbox.h"
-#include "sandbox/mac/mach_message_server.h"
-#include "sandbox/mac/os_compatibility.h"
-#include "sandbox/mac/xpc_message_server.h"
-
-namespace sandbox {
-
-// The buffer size for all launchd messages. This comes from
-// sizeof(union __RequestUnion__vproc_mig_job_subsystem) in launchd, and it
-// is larger than the __ReplyUnion.
-const mach_msg_size_t kBufferSize = 2096;
-
-LaunchdInterceptionServer::LaunchdInterceptionServer(
- const BootstrapSandbox* sandbox)
- : sandbox_(sandbox),
- xpc_launchd_(false),
- sandbox_port_(MACH_PORT_NULL),
- compat_shim_(OSCompatibility::CreateForPlatform()) {
-}
-
-LaunchdInterceptionServer::~LaunchdInterceptionServer() {
- message_server_->Shutdown();
-}
-
-bool LaunchdInterceptionServer::Initialize(mach_port_t server_receive_right) {
- mach_port_t task = mach_task_self();
- kern_return_t kr;
-
- // Allocate the dummy sandbox port.
- mach_port_t port;
- if ((kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &port)) !=
- KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Failed to allocate dummy sandbox port.";
- return false;
- }
- sandbox_port_.reset(port);
- if ((kr = mach_port_insert_right(task, sandbox_port_.get(),
- sandbox_port_.get(), MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS)) {
- MACH_LOG(ERROR, kr) << "Failed to allocate dummy sandbox port send right.";
- return false;
- }
- sandbox_send_port_.reset(sandbox_port_.get());
-
- if (base::mac::IsAtLeastOS10_10()) {
- message_server_.reset(new XPCMessageServer(this, server_receive_right));
- xpc_launchd_ = true;
- } else {
- message_server_.reset(
- new MachMessageServer(this, server_receive_right, kBufferSize));
- }
- return message_server_->Initialize();
-}
-
-void LaunchdInterceptionServer::DemuxMessage(IPCMessage request) {
- const uint64_t message_subsystem =
- compat_shim_->GetMessageSubsystem(request);
- const uint64_t message_id = compat_shim_->GetMessageID(request);
- VLOG(3) << "Incoming message #" << message_subsystem << "," << message_id;
-
- pid_t sender_pid = message_server_->GetMessageSenderPID(request);
- const BootstrapSandboxPolicy* policy =
- sandbox_->PolicyForProcess(sender_pid);
- if (policy == NULL) {
- // No sandbox policy is in place for the sender of this message, which
- // means it came from the unknown. Reject it.
- VLOG(3) << "Message from unknown pid " << sender_pid << " rejected.";
- message_server_->RejectMessage(request, MIG_REMOTE_ERROR);
- return;
- }
-
- if (compat_shim_->IsServiceLookUpRequest(request)) {
- // Filter messages sent via bootstrap_look_up to enforce the sandbox policy
- // over the bootstrap namespace.
- HandleLookUp(request, policy);
- } else if (compat_shim_->IsVprocSwapInteger(request)) {
- // Ensure that any vproc_swap_integer requests are safe.
- HandleSwapInteger(request);
- } else if (compat_shim_->IsXPCDomainManagement(request)) {
- // XPC domain management requests just require an ACK.
- message_server_->SendReply(message_server_->CreateReply(request));
- } else {
- // All other messages are not permitted.
- VLOG(1) << "Rejecting unhandled message #" << message_id;
- message_server_->RejectMessage(request, MIG_REMOTE_ERROR);
- }
-}
-
-void LaunchdInterceptionServer::HandleLookUp(
- IPCMessage request,
- const BootstrapSandboxPolicy* policy) {
- const std::string request_service_name(
- compat_shim_->GetServiceLookupName(request));
- VLOG(2) << "Incoming look_up2 request for " << request_service_name;
-
- // Find the Rule for this service. If a named rule is not found, use the
- // default specified by the policy.
- const BootstrapSandboxPolicy::NamedRules::const_iterator it =
- policy->rules.find(request_service_name);
- Rule rule(policy->default_rule);
- if (it != policy->rules.end())
- rule = it->second;
-
- if (rule.result == POLICY_ALLOW) {
- // This service is explicitly allowed, so this message will not be
- // intercepted by the sandbox.
- VLOG(1) << "Permitting and forwarding look_up2: " << request_service_name;
- ForwardMessage(request);
- } else if (rule.result == POLICY_DENY_ERROR) {
- // The child is not permitted to look up this service. Send a MIG error
- // reply to the client. Returning a NULL or unserviced port for a look up
- // can cause clients to crash or hang.
- VLOG(1) << "Denying look_up2 with MIG error: " << request_service_name;
- message_server_->RejectMessage(request, BOOTSTRAP_UNKNOWN_SERVICE);
- } else if (rule.result == POLICY_DENY_DUMMY_PORT ||
- rule.result == POLICY_SUBSTITUTE_PORT) {
- // The policy result is to deny access to the real service port, replying
- // with a sandboxed port in its stead. Use either the dummy sandbox_port_
- // or the one specified in the policy.
- VLOG(1) << "Intercepting look_up2 with a sandboxed service port: "
- << request_service_name;
-
- mach_port_t result_port;
- if (rule.result == POLICY_DENY_DUMMY_PORT)
- result_port = sandbox_port_.get();
- else
- result_port = rule.substitute_port;
-
- IPCMessage reply = message_server_->CreateReply(request);
- compat_shim_->WriteServiceLookUpReply(reply, result_port);
- // If the message was sent successfully, clear the result_port out of the
- // message so that it is not destroyed at the end of ReceiveMessage. The
- // above-inserted right has been moved out of the process, and destroying
- // the message will unref yet another right.
- if (message_server_->SendReply(reply))
- compat_shim_->WriteServiceLookUpReply(reply, MACH_PORT_NULL);
- } else {
- NOTREACHED();
- }
-}
-
-void LaunchdInterceptionServer::HandleSwapInteger(IPCMessage request) {
- // Only allow getting information out of launchd. Do not allow setting
- // values. Two commonly observed values that are retrieved are
- // VPROC_GSK_MGR_PID and VPROC_GSK_TRANSACTIONS_ENABLED.
- if (compat_shim_->IsSwapIntegerReadOnly(request)) {
- VLOG(2) << "Forwarding vproc swap_integer message.";
- ForwardMessage(request);
- } else {
- VLOG(2) << "Rejecting non-read-only swap_integer message.";
- message_server_->RejectMessage(request, BOOTSTRAP_NOT_PRIVILEGED);
- }
-}
-void LaunchdInterceptionServer::ForwardMessage(IPCMessage request) {
- // If launchd is using XPC, then when the request is forwarded, it must
- // contain a valid domain port. Because the client processes are sandboxed,
- // they have not had their launchd domains uncorked (and launchd will
- // reject the message as being from an invalid client). Instead, provide the
- // original bootstrap as the domain port, so launchd services the request
- // as if it were coming from the sandbox host process (this).
- if (xpc_launchd_) {
- // xpc_dictionary_set_mach_send increments the send right count.
- xpc_dictionary_set_mach_send(request.xpc, "domain-port",
- sandbox_->real_bootstrap_port());
- }
-
- message_server_->ForwardMessage(request, sandbox_->real_bootstrap_port());
-}
-
-} // namespace sandbox
diff --git a/sandbox/mac/launchd_interception_server.h b/sandbox/mac/launchd_interception_server.h
deleted file mode 100644
index 9ed38f1..0000000
--- a/sandbox/mac/launchd_interception_server.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_MAC_LAUNCHD_INTERCEPTION_SERVER_H_
-#define SANDBOX_MAC_LAUNCHD_INTERCEPTION_SERVER_H_
-
-#include <memory>
-
-#include <dispatch/dispatch.h>
-
-#include "base/mac/scoped_mach_port.h"
-#include "sandbox/mac/message_server.h"
-
-namespace sandbox {
-
-class BootstrapSandbox;
-struct BootstrapSandboxPolicy;
-class OSCompatibility;
-
-// This class is used to run a Mach IPC message server. This server can
-// hold the receive right for a bootstrap_port of a process, and it filters
-// a subset of the launchd/bootstrap IPC call set for sandboxing. It permits
-// or rejects requests based on the per-process policy specified in the
-// BootstrapSandbox.
-class LaunchdInterceptionServer : public MessageDemuxer {
- public:
- explicit LaunchdInterceptionServer(const BootstrapSandbox* sandbox);
- ~LaunchdInterceptionServer() override;
-
- // Initializes the class and starts running the message server. If the
- // |server_receive_right| is non-NULL, this class will take ownership of
- // the receive right and intercept messages sent to that port.
- bool Initialize(mach_port_t server_receive_right);
-
- // MessageDemuxer:
- void DemuxMessage(IPCMessage request) override;
-
- mach_port_t server_port() const { return message_server_->GetServerPort(); }
-
- private:
- // Given a look_up2 request message, this looks up the appropriate sandbox
- // policy for the service name then formulates and sends the reply message.
- void HandleLookUp(IPCMessage request, const BootstrapSandboxPolicy* policy);
-
- // Given a swap_integer request message, this verifies that it is safe, and
- // if so, forwards it on to launchd for servicing. If the request is unsafe,
- // it replies with an error.
- void HandleSwapInteger(IPCMessage request);
-
- // Forwards the original |request| on to real bootstrap server for handling.
- void ForwardMessage(IPCMessage request);
-
- // The sandbox for which this message server is running.
- const BootstrapSandbox* sandbox_;
-
- // The Mach IPC server.
- std::unique_ptr<MessageServer> message_server_;
-
- // Whether or not the system is using an XPC-based launchd.
- bool xpc_launchd_;
-
- // The Mach port handed out in reply to denied look up requests. All denied
- // requests share the same port, though nothing reads messages from it.
- base::mac::ScopedMachReceiveRight sandbox_port_;
- // The send right for the above |sandbox_port_|, used with
- // MACH_MSG_TYPE_COPY_SEND when handing out references to the dummy port.
- base::mac::ScopedMachSendRight sandbox_send_port_;
-
- // The compatibility shim that handles differences in message header IDs and
- // request/reply structures between different OS X versions.
- std::unique_ptr<OSCompatibility> compat_shim_;
-};
-
-} // namespace sandbox
-
-#endif // SANDBOX_MAC_LAUNCHD_INTERCEPTION_SERVER_H_
diff --git a/sandbox/mac/mach_message_server.cc b/sandbox/mac/mach_message_server.cc
deleted file mode 100644
index d627d45..0000000
--- a/sandbox/mac/mach_message_server.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/mac/mach_message_server.h"
-
-#include <bsm/libbsm.h>
-#include <servers/bootstrap.h>
-#include <stddef.h>
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/mac/mach_logging.h"
-#include "base/strings/stringprintf.h"
-
-namespace sandbox {
-
-MachMessageServer::MachMessageServer(
- MessageDemuxer* demuxer,
- mach_port_t server_receive_right,
- mach_msg_size_t buffer_size)
- : demuxer_(demuxer),
- server_port_(server_receive_right),
- buffer_size_(
- mach_vm_round_page(buffer_size + sizeof(mach_msg_audit_trailer_t))),
- did_forward_message_(false) {
- DCHECK(demuxer_);
-}
-
-MachMessageServer::~MachMessageServer() {
-}
-
-bool MachMessageServer::Initialize() {
- mach_port_t task = mach_task_self();
- kern_return_t kr;
-
- // Allocate a port for use as a new server port if one was not passed to the
- // constructor.
- if (!server_port_.is_valid()) {
- mach_port_t port;
- if ((kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &port)) !=
- KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Failed to allocate new server port.";
- return false;
- }
- server_port_.reset(port);
- }
-
- // Allocate the message request and reply buffers.
- const int kMachMsgMemoryFlags = VM_MAKE_TAG(VM_MEMORY_MACH_MSG) |
- VM_FLAGS_ANYWHERE;
- vm_address_t buffer = 0;
-
- kr = vm_allocate(task, &buffer, buffer_size_, kMachMsgMemoryFlags);
- if (kr != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Failed to allocate request buffer.";
- return false;
- }
- request_buffer_.reset(buffer, buffer_size_);
-
- kr = vm_allocate(task, &buffer, buffer_size_, kMachMsgMemoryFlags);
- if (kr != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Failed to allocate reply buffer.";
- return false;
- }
- reply_buffer_.reset(buffer, buffer_size_);
-
- // Set up the dispatch queue to service the bootstrap port.
- std::string label = base::StringPrintf(
- "org.chromium.sandbox.MachMessageServer.%p", demuxer_);
- dispatch_source_.reset(new base::DispatchSourceMach(
- label.c_str(), server_port_.get(), ^{ ReceiveMessage(); }));
- dispatch_source_->Resume();
-
- return true;
-}
-
-void MachMessageServer::Shutdown() {
- dispatch_source_.reset();
-}
-
-pid_t MachMessageServer::GetMessageSenderPID(IPCMessage request) {
- // Get the PID of the task that sent this request. This requires getting at
- // the trailer of the message, from the header.
- mach_msg_audit_trailer_t* trailer =
- reinterpret_cast<mach_msg_audit_trailer_t*>(
- reinterpret_cast<vm_address_t>(request.mach) +
- round_msg(request.mach->msgh_size));
-
- pid_t sender_pid = audit_token_to_pid(trailer->msgh_audit);
-
- return sender_pid;
-}
-
-IPCMessage MachMessageServer::CreateReply(IPCMessage request_message) {
- mach_msg_header_t* request = request_message.mach;
-
- IPCMessage reply_message;
- mach_msg_header_t* reply = reply_message.mach =
- reinterpret_cast<mach_msg_header_t*>(reply_buffer_.address());
- bzero(reply, buffer_size_);
-
- reply->msgh_bits = MACH_MSGH_BITS_REMOTE(reply->msgh_bits);
- // Since mach_msg will automatically swap the request and reply ports,
- // undo that.
- reply->msgh_remote_port = request->msgh_remote_port;
- reply->msgh_local_port = MACH_PORT_NULL;
- // MIG servers simply add 100 to the request ID to generate the reply ID.
- reply->msgh_id = request->msgh_id + 100;
-
- return reply_message;
-}
-
-bool MachMessageServer::SendReply(IPCMessage reply) {
- kern_return_t kr = mach_msg(reply.mach, MACH_SEND_MSG,
- reply.mach->msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
- MACH_PORT_NULL);
- MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr)
- << "Unable to send intercepted reply message.";
- return kr == KERN_SUCCESS;
-}
-
-void MachMessageServer::ForwardMessage(IPCMessage message,
- mach_port_t destination) {
- mach_msg_header_t* request = message.mach;
- request->msgh_local_port = request->msgh_remote_port;
- request->msgh_remote_port = destination;
- // Preserve the msgh_bits that do not deal with the local and remote ports.
- request->msgh_bits = (request->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
- MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MOVE_SEND_ONCE);
- kern_return_t kr = mach_msg_send(request);
- if (kr == KERN_SUCCESS) {
- did_forward_message_ = true;
- } else {
- MACH_LOG(ERROR, kr) << "Unable to forward message to the real launchd.";
- }
-}
-
-void MachMessageServer::RejectMessage(IPCMessage request, int error_code) {
- IPCMessage reply = CreateReply(request);
- mig_reply_error_t* error_reply =
- reinterpret_cast<mig_reply_error_t*>(reply.mach);
- error_reply->Head.msgh_size = sizeof(mig_reply_error_t);
- error_reply->Head.msgh_bits =
- MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND_ONCE);
- error_reply->NDR = NDR_record;
- error_reply->RetCode = error_code;
- SendReply(reply);
-}
-
-mach_port_t MachMessageServer::GetServerPort() const {
- return server_port_.get();
-}
-
-void MachMessageServer::ReceiveMessage() {
- const mach_msg_options_t kRcvOptions = MACH_RCV_MSG |
- MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) |
- MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT);
-
- mach_msg_header_t* request =
- reinterpret_cast<mach_msg_header_t*>(request_buffer_.address());
- mach_msg_header_t* reply =
- reinterpret_cast<mach_msg_header_t*>(reply_buffer_.address());
-
- // Zero out the buffers from handling any previous message.
- bzero(request, buffer_size_);
- bzero(reply, buffer_size_);
- did_forward_message_ = false;
-
- // A Mach message server-once. The system library to run a message server
- // cannot be used here, because some requests are conditionally forwarded
- // to another server.
- kern_return_t kr = mach_msg(request, kRcvOptions, 0, buffer_size_,
- server_port_.get(), MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- if (kr != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Unable to receive message.";
- return;
- }
-
- // Process the message.
- IPCMessage request_message = { request };
- demuxer_->DemuxMessage(request_message);
-
- // Free any descriptors in the message body. If the message was forwarded,
- // any descriptors would have been moved out of the process on send. If the
- // forwarded message was sent from the process hosting this sandbox server,
- // destroying the message could also destroy rights held outside the scope of
- // this message server.
- if (!did_forward_message_) {
- mach_msg_destroy(request);
- mach_msg_destroy(reply);
- }
-}
-
-} // namespace sandbox
diff --git a/sandbox/mac/mach_message_server.h b/sandbox/mac/mach_message_server.h
deleted file mode 100644
index ace30ec..0000000
--- a/sandbox/mac/mach_message_server.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_MAC_MACH_MESSAGE_SERVER_H_
-#define SANDBOX_MAC_MACH_MESSAGE_SERVER_H_
-
-#include <mach/mach.h>
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/mac/dispatch_source_mach.h"
-#include "base/mac/scoped_mach_port.h"
-#include "base/mac/scoped_mach_vm.h"
-#include "sandbox/mac/message_server.h"
-
-namespace sandbox {
-
-// A Mach message server that operates a receive port. Messages are received
-// and then passed to the MessageDemuxer for handling. The Demuxer
-// can use the server class to send a reply, forward the message to a
-// different port, or reply to the message with a MIG error.
-class MachMessageServer : public MessageServer {
- public:
- // Creates a new Mach message server that will send messages to |demuxer|
- // for handling. If the |server_receive_right| is non-NULL, this class will
- // take ownership of the port and it will be used to receive messages.
- // Otherwise the server will create a new receive right.
- // The maximum size of messages is specified by |buffer_size|.
- MachMessageServer(MessageDemuxer* demuxer,
- mach_port_t server_receive_right,
- mach_msg_size_t buffer_size);
- ~MachMessageServer() override;
-
- // MessageServer:
- bool Initialize() override;
- void Shutdown() override;
- pid_t GetMessageSenderPID(IPCMessage request) override;
- IPCMessage CreateReply(IPCMessage request) override;
- bool SendReply(IPCMessage reply) override;
- void ForwardMessage(IPCMessage request, mach_port_t destination) override;
- // Replies to the message with the specified |error_code| as a MIG
- // error_reply RetCode.
- void RejectMessage(IPCMessage request, int error_code) override;
- mach_port_t GetServerPort() const override;
-
- private:
- // Event handler for the |server_source_| that reads a message from the queue
- // and processes it.
- void ReceiveMessage();
-
- // The demuxer delegate. Weak.
- MessageDemuxer* demuxer_;
-
- // The Mach port on which the server is receiving requests.
- base::mac::ScopedMachReceiveRight server_port_;
-
- // The size of the two message buffers below.
- const mach_msg_size_t buffer_size_;
-
- // Request and reply buffers used in ReceiveMessage.
- base::mac::ScopedMachVM request_buffer_;
- base::mac::ScopedMachVM reply_buffer_;
-
- // MACH_RECV dispatch source that handles the |server_port_|.
- std::unique_ptr<base::DispatchSourceMach> dispatch_source_;
-
- // Whether or not ForwardMessage() was called during ReceiveMessage().
- bool did_forward_message_;
-};
-
-} // namespace sandbox
-
-#endif // SANDBOX_MAC_MACH_MESSAGE_SERVER_H_
diff --git a/sandbox/mac/message_server.h b/sandbox/mac/message_server.h
deleted file mode 100644
index 6ee119b..0000000
--- a/sandbox/mac/message_server.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_MAC_MESSAGE_SERVER_H_
-#define SANDBOX_MAC_MESSAGE_SERVER_H_
-
-#include <mach/mach.h>
-#include <unistd.h>
-
-#include "sandbox/mac/xpc.h"
-
-namespace sandbox {
-
-// A message received by a MessageServer. Each concrete implementation of
-// that interface will handle the fields of this union appropriately.
-// Consumers should treat this as an opaque handle.
-union IPCMessage {
- mach_msg_header_t* mach;
- xpc_object_t xpc;
-};
-
-// A delegate interface for MessageServer that handles processing of
-// incoming intercepted IPC messages.
-class MessageDemuxer {
- public:
- // Handle a |request| message. The message is owned by the server. Use the
- // server's methods to create and send a reply message.
- virtual void DemuxMessage(IPCMessage request) = 0;
-
- protected:
- virtual ~MessageDemuxer() {}
-};
-
-// An interaface for an IPC server that implements Mach messaging semantics.
-// The concrete implementation may be powered by raw Mach messages, XPC, or
-// some other technology. This interface is the abstraction on top of those
-// that enables message interception.
-class MessageServer {
- public:
- virtual ~MessageServer() {}
-
- // Initializes the class and starts running the message server. If this
- // returns false, no other methods may be called on this class.
- virtual bool Initialize() = 0;
-
- // Blocks the calling thread while the server shuts down. This prevents
- // the server from receiving new messages. After this method is called,
- // no other methods may be called on this class.
- virtual void Shutdown() = 0;
-
- // Given a received request message, returns the PID of the sending process.
- virtual pid_t GetMessageSenderPID(IPCMessage request) = 0;
-
- // Creates a reply message from a request message. The result is owned by
- // the server.
- virtual IPCMessage CreateReply(IPCMessage request) = 0;
-
- // Sends a reply message. Returns true if the message was sent successfully.
- virtual bool SendReply(IPCMessage reply) = 0;
-
- // Forwards the original |request| to the |destination| for handling.
- virtual void ForwardMessage(IPCMessage request, mach_port_t destination) = 0;
-
- // Replies to the received |request| message by creating a reply and setting
- // the specified |error_code| in a field that is interpreted by the
- // underlying IPC system.
- virtual void RejectMessage(IPCMessage request, int error_code) = 0;
-
- // Returns the Mach port on which the MessageServer is listening.
- virtual mach_port_t GetServerPort() const = 0;
-};
-
-} // namespace sandbox
-
-#endif // SANDBOX_MAC_MESSAGE_SERVER_H_
diff --git a/sandbox/mac/os_compatibility.cc b/sandbox/mac/os_compatibility.cc
deleted file mode 100644
index e15e9cfa..0000000
--- a/sandbox/mac/os_compatibility.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/mac/os_compatibility.h"
-
-#include <servers/bootstrap.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <unistd.h>
-
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "base/memory/ptr_util.h"
-#include "sandbox/mac/xpc.h"
-
-namespace sandbox {
-
-namespace {
-
-#pragma pack(push, 4)
-// Verified from launchd-329.3.3 (10.6.8).
-// look_up2_reply_10_7 is the same as the 10_6 version.
-struct look_up2_reply_10_7 {
- mach_msg_header_t Head;
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t service_port;
-};
-
-// Verified from:
-// launchd-392.39 (10.7.5)
-// launchd-442.26.2 (10.8.5)
-// launchd-842.1.4 (10.9.0)
-struct look_up2_request_10_7 {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- name_t servicename;
- pid_t targetpid;
- uuid_t instanceid;
- uint64_t flags;
-};
-
-// Verified from:
-// launchd-329.3.3 (10.6.8)
-// launchd-392.39 (10.7.5)
-// launchd-442.26.2 (10.8.5)
-// launchd-842.1.4 (10.9.0)
-typedef int vproc_gsk_t; // Defined as an enum in liblaunch/vproc_priv.h.
-struct swap_integer_request_10_7 {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- vproc_gsk_t inkey;
- vproc_gsk_t outkey;
- int64_t inval;
-};
-#pragma pack(pop)
-
-class OSCompatibility_10_7 : public OSCompatibility {
- public:
- OSCompatibility_10_7() {}
- ~OSCompatibility_10_7() override {}
-
- uint64_t GetMessageSubsystem(const IPCMessage message) override {
- return (message.mach->msgh_id / 100) * 100;
- }
-
- uint64_t GetMessageID(const IPCMessage message) override {
- return message.mach->msgh_id;
- }
-
- bool IsServiceLookUpRequest(const IPCMessage message) override {
- return GetMessageID(message) == 404;
- }
-
- bool IsVprocSwapInteger(const IPCMessage message) override {
- return GetMessageID(message) == 416;
- }
-
- bool IsXPCDomainManagement(const IPCMessage message) override {
- return false;
- }
-
- std::string GetServiceLookupName(const IPCMessage message) override {
- return GetRequestName<look_up2_request_10_7>(message);
- }
-
- void WriteServiceLookUpReply(IPCMessage message,
- mach_port_t service_port) override {
- auto* reply = reinterpret_cast<look_up2_reply_10_7*>(message.mach);
- reply->Head.msgh_size = sizeof(*reply);
- reply->Head.msgh_bits =
- MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
- MACH_MSGH_BITS_COMPLEX;
- reply->msgh_body.msgh_descriptor_count = 1;
- reply->service_port.name = service_port;
- reply->service_port.disposition = MACH_MSG_TYPE_COPY_SEND;
- reply->service_port.type = MACH_MSG_PORT_DESCRIPTOR;
- }
-
- bool IsSwapIntegerReadOnly(const IPCMessage message) override {
- auto* request =
- reinterpret_cast<const swap_integer_request_10_7*>(message.mach);
- return request->inkey == 0 && request->inval == 0 && request->outkey != 0;
- }
-
- protected:
- // The 10.6 and 10.7 implementations are the same except for struct offsets,
- // so provide this templatized helper.
- template <typename R>
- static std::string GetRequestName(const IPCMessage message) {
- mach_msg_header_t* header = message.mach;
- DCHECK_EQ(sizeof(R), header->msgh_size);
- const R* request = reinterpret_cast<const R*>(header);
- // Make sure the name is properly NUL-terminated.
- const size_t name_length =
- strnlen(request->servicename, BOOTSTRAP_MAX_NAME_LEN);
- std::string name = std::string(request->servicename, name_length);
- return name;
- }
-};
-
-class OSCompatibility_10_10 : public OSCompatibility {
- public:
- OSCompatibility_10_10() {}
- ~OSCompatibility_10_10() override {}
-
- uint64_t GetMessageSubsystem(const IPCMessage message) override {
- return xpc_dictionary_get_uint64(message.xpc, "subsystem");
- }
-
- uint64_t GetMessageID(const IPCMessage message) override {
- return xpc_dictionary_get_uint64(message.xpc, "routine");
- }
-
- bool IsServiceLookUpRequest(const IPCMessage message) override {
- uint64_t subsystem = GetMessageSubsystem(message);
- uint64_t id = GetMessageID(message);
- // Lookup requests in XPC can either go through the Mach bootstrap subsytem
- // (5) from bootstrap_look_up(), or the XPC domain subsystem (3) for
- // xpc_connection_create(). Both use the same message format.
- return (subsystem == 5 && id == 207) || (subsystem == 3 && id == 804);
- }
-
- bool IsVprocSwapInteger(const IPCMessage message) override {
- return GetMessageSubsystem(message) == 6 && GetMessageID(message) == 301;
- }
-
- bool IsXPCDomainManagement(const IPCMessage message) override {
- return GetMessageSubsystem(message) == 3;
- }
-
- std::string GetServiceLookupName(const IPCMessage message) override {
- const char* name = xpc_dictionary_get_string(message.xpc, "name");
- const size_t name_length = strnlen(name, BOOTSTRAP_MAX_NAME_LEN);
- return std::string(name, name_length);
- }
-
- void WriteServiceLookUpReply(IPCMessage message,
- mach_port_t service_port) override {
- xpc_dictionary_set_mach_send(message.xpc, "port", service_port);
- }
-
- bool IsSwapIntegerReadOnly(const IPCMessage message) override {
- return xpc_dictionary_get_bool(message.xpc, "set") == false &&
- xpc_dictionary_get_uint64(message.xpc, "ingsk") == 0 &&
- xpc_dictionary_get_int64(message.xpc, "in") == 0;
- }
-};
-
-} // namespace
-
-// static
-std::unique_ptr<OSCompatibility> OSCompatibility::CreateForPlatform() {
- if (base::mac::IsOS10_9())
- return base::WrapUnique(new OSCompatibility_10_7());
- else
- return base::WrapUnique(new OSCompatibility_10_10());
-}
-
-OSCompatibility::~OSCompatibility() {}
-
-} // namespace sandbox
diff --git a/sandbox/mac/os_compatibility.h b/sandbox/mac/os_compatibility.h
deleted file mode 100644
index c341888..0000000
--- a/sandbox/mac/os_compatibility.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file is used to handle differences in Mach message IDs and structures
-// that occur between different OS versions. The Mach messages that the sandbox
-// is interested in are decoded using information derived from the open-source
-// libraries, i.e. <http://www.opensource.apple.com/source/launchd/>. While
-// these messages definitions are open source, they are not considered part of
-// the stable OS API, and so differences do exist between OS versions.
-
-#ifndef SANDBOX_MAC_OS_COMPATIBILITY_H_
-#define SANDBOX_MAC_OS_COMPATIBILITY_H_
-
-#include <mach/mach.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "sandbox/mac/message_server.h"
-
-namespace sandbox {
-
-class OSCompatibility {
- public:
- // Creates an OSCompatibility instance for the current OS X version.
- static std::unique_ptr<OSCompatibility> CreateForPlatform();
-
- virtual ~OSCompatibility();
-
- // Gets the message and subsystem ID of an IPC message.
- virtual uint64_t GetMessageSubsystem(const IPCMessage message) = 0;
- virtual uint64_t GetMessageID(const IPCMessage message) = 0;
-
- // Returns true if the message is a Launchd look up request.
- virtual bool IsServiceLookUpRequest(const IPCMessage message) = 0;
-
- // Returns true if the message is a Launchd vproc swap_integer request.
- virtual bool IsVprocSwapInteger(const IPCMessage message) = 0;
-
- // Returns true if the message is an XPC domain management message.
- virtual bool IsXPCDomainManagement(const IPCMessage message) = 0;
-
- // A function to take a look_up2 message and return the string service name
- // that was requested via the message.
- virtual std::string GetServiceLookupName(const IPCMessage message) = 0;
-
- // A function to formulate a reply to a look_up2 message, given the reply
- // message and the port to return as the service.
- virtual void WriteServiceLookUpReply(IPCMessage reply,
- mach_port_t service_port) = 0;
-
- // A function to take a swap_integer message and return true if the message
- // is only getting the value of a key, neither setting it directly, nor
- // swapping two keys.
- virtual bool IsSwapIntegerReadOnly(const IPCMessage message) = 0;
-};
-
-} // namespace sandbox
-
-#endif // SANDBOX_MAC_OS_COMPATIBILITY_H_
diff --git a/sandbox/mac/policy.cc b/sandbox/mac/policy.cc
deleted file mode 100644
index d9ff109..0000000
--- a/sandbox/mac/policy.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/mac/policy.h"
-
-namespace sandbox {
-
-Rule::Rule()
- : result(POLICY_DECISION_INVALID),
- substitute_port(MACH_PORT_NULL) {
-}
-
-Rule::Rule(PolicyDecision result)
- : result(result),
- substitute_port(MACH_PORT_NULL) {
-}
-
-Rule::Rule(mach_port_t override_port)
- : result(POLICY_SUBSTITUTE_PORT),
- substitute_port(override_port) {
-}
-
-BootstrapSandboxPolicy::BootstrapSandboxPolicy()
- : default_rule(POLICY_DENY_ERROR) {
-}
-
-BootstrapSandboxPolicy::BootstrapSandboxPolicy(
- const BootstrapSandboxPolicy& other) = default;
-
-BootstrapSandboxPolicy::~BootstrapSandboxPolicy() {}
-
-static bool IsRuleValid(const Rule& rule) {
- if (!(rule.result > POLICY_DECISION_INVALID &&
- rule.result < POLICY_DECISION_LAST)) {
- return false;
- }
- if (rule.result == POLICY_SUBSTITUTE_PORT) {
- if (rule.substitute_port == MACH_PORT_NULL)
- return false;
- } else {
- if (rule.substitute_port != MACH_PORT_NULL)
- return false;
- }
- return true;
-}
-
-bool IsPolicyValid(const BootstrapSandboxPolicy& policy) {
- if (!IsRuleValid(policy.default_rule))
- return false;
-
- for (const auto& pair : policy.rules) {
- if (!IsRuleValid(pair.second))
- return false;
- }
- return true;
-}
-
-} // namespace sandbox
diff --git a/sandbox/mac/policy.h b/sandbox/mac/policy.h
deleted file mode 100644
index 4726038..0000000
--- a/sandbox/mac/policy.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_MAC_POLICY_H_
-#define SANDBOX_MAC_POLICY_H_
-
-#include <mach/mach.h>
-
-#include <map>
-#include <string>
-
-#include "sandbox/sandbox_export.h"
-
-namespace sandbox {
-
-enum PolicyDecision {
- POLICY_DECISION_INVALID,
- // Explicitly allows the real service to be looked up from launchd.
- POLICY_ALLOW,
- // Deny the look up request by replying with a MIG error. This is the
- // default behavior for servers not given an explicit rule.
- POLICY_DENY_ERROR,
- // Deny the look up request with a well-formed reply containing a
- // Mach port with a send right, messages to which will be ignored.
- POLICY_DENY_DUMMY_PORT,
- // Reply to the look up request with a send right to the substitute_port
- // specified in the Rule.
- POLICY_SUBSTITUTE_PORT,
- POLICY_DECISION_LAST,
-};
-
-// A Rule expresses the action to take when a service port is requested via
-// bootstrap_look_up. If |result| is not POLICY_SUBSTITUTE_PORT, then
-// |substitute_port| must be NULL. If result is POLICY_SUBSTITUTE_PORT, then
-// |substitute_port| must not be NULL.
-struct SANDBOX_EXPORT Rule {
- Rule();
- explicit Rule(PolicyDecision result);
- explicit Rule(mach_port_t override_port);
-
- PolicyDecision result;
-
- // The Rule does not take ownership of this port, but additional send rights
- // will be allocated to it before it is sent to a client. This name must
- // denote a send right that can duplicated with MACH_MSG_TYPE_COPY_SEND.
- mach_port_t substitute_port;
-};
-
-// A policy object manages the rules enforced on a target sandboxed process.
-struct SANDBOX_EXPORT BootstrapSandboxPolicy {
- typedef std::map<std::string, Rule> NamedRules;
-
- BootstrapSandboxPolicy();
- BootstrapSandboxPolicy(const BootstrapSandboxPolicy& other);
- ~BootstrapSandboxPolicy();
-
- // The default action to take if the server name being looked up is not
- // present in |rules|.
- Rule default_rule;
-
- // A map of bootstrap server names to policy Rules.
- NamedRules rules;
-};
-
-// Checks that a policy is well-formed.
-SANDBOX_EXPORT bool IsPolicyValid(const BootstrapSandboxPolicy& policy);
-
-} // namespace sandbox
-
-#endif // SANDBOX_MAC_POLICY_H_
diff --git a/sandbox/mac/policy_unittest.cc b/sandbox/mac/policy_unittest.cc
deleted file mode 100644
index 54e0e74..0000000
--- a/sandbox/mac/policy_unittest.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/mac/policy.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace sandbox {
-
-TEST(PolicyTest, ValidEmptyPolicy) {
- EXPECT_TRUE(IsPolicyValid(BootstrapSandboxPolicy()));
-}
-
-TEST(PolicyTest, ValidPolicy) {
- BootstrapSandboxPolicy policy;
- policy.rules["allow"] = Rule(POLICY_ALLOW);
- policy.rules["deny_error"] = Rule(POLICY_DENY_ERROR);
- policy.rules["deny_dummy"] = Rule(POLICY_DENY_DUMMY_PORT);
- policy.rules["substitue"] = Rule(mach_task_self());
- EXPECT_TRUE(IsPolicyValid(policy));
-}
-
-TEST(PolicyTest, InvalidPolicyEmptyRule) {
- Rule rule;
- BootstrapSandboxPolicy policy;
- policy.rules["test"] = rule;
- EXPECT_FALSE(IsPolicyValid(policy));
-}
-
-TEST(PolicyTest, InvalidPolicySubstitue) {
- Rule rule(POLICY_SUBSTITUTE_PORT);
- BootstrapSandboxPolicy policy;
- policy.rules["test"] = rule;
- EXPECT_FALSE(IsPolicyValid(policy));
-}
-
-TEST(PolicyTest, InvalidPolicyWithPortAllow) {
- Rule rule(POLICY_ALLOW);
- rule.substitute_port = mach_task_self();
- BootstrapSandboxPolicy policy;
- policy.rules["allow"] = rule;
- EXPECT_FALSE(IsPolicyValid(policy));
-}
-
-TEST(PolicyTest, InvalidPolicyWithPortDenyError) {
- Rule rule(POLICY_DENY_ERROR);
- rule.substitute_port = mach_task_self();
- BootstrapSandboxPolicy policy;
- policy.rules["deny_error"] = rule;
- EXPECT_FALSE(IsPolicyValid(policy));
-}
-
-TEST(PolicyTest, InvalidPolicyWithPortDummy) {
- Rule rule(POLICY_DENY_DUMMY_PORT);
- rule.substitute_port = mach_task_self();
- BootstrapSandboxPolicy policy;
- policy.rules["deny_dummy"] = rule;
- EXPECT_FALSE(IsPolicyValid(policy));
-}
-
-TEST(PolicyTest, InvalidPolicyDefaultRule) {
- BootstrapSandboxPolicy policy;
- policy.default_rule = Rule();
- EXPECT_FALSE(IsPolicyValid(policy));
-}
-
-TEST(PolicyTest, InvalidPolicyDefaultRuleSubstitue) {
- BootstrapSandboxPolicy policy;
- policy.default_rule = Rule(POLICY_SUBSTITUTE_PORT);
- EXPECT_FALSE(IsPolicyValid(policy));
-}
-
-TEST(PolicyTest, InvalidPolicyDefaultRuleWithPortAllow) {
- Rule rule(POLICY_ALLOW);
- rule.substitute_port = mach_task_self();
- BootstrapSandboxPolicy policy;
- policy.default_rule = rule;
- EXPECT_FALSE(IsPolicyValid(policy));
-}
-
-TEST(PolicyTest, InvalidPolicyDefaultRuleWithPortDenyError) {
- Rule rule(POLICY_DENY_ERROR);
- rule.substitute_port = mach_task_self();
- BootstrapSandboxPolicy policy;
- policy.default_rule = rule;
- EXPECT_FALSE(IsPolicyValid(policy));
-}
-
-TEST(PolicyTest, InvalidPolicyDefaultRuleWithPortDummy) {
- Rule rule(POLICY_DENY_DUMMY_PORT);
- rule.substitute_port = mach_task_self();
- BootstrapSandboxPolicy policy;
- policy.default_rule = rule;
- EXPECT_FALSE(IsPolicyValid(policy));
-}
-
-} // namespace sandbox
diff --git a/sandbox/mac/pre_exec_delegate.cc b/sandbox/mac/pre_exec_delegate.cc
deleted file mode 100644
index 1aac68be..0000000
--- a/sandbox/mac/pre_exec_delegate.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/mac/pre_exec_delegate.h"
-
-#include <mach/mach.h>
-#include <servers/bootstrap.h>
-#include <stdint.h>
-
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "sandbox/mac/bootstrap_sandbox.h"
-#include "sandbox/mac/xpc.h"
-
-namespace sandbox {
-
-PreExecDelegate::PreExecDelegate(
- const std::string& sandbox_server_bootstrap_name,
- uint64_t sandbox_token)
- : sandbox_server_bootstrap_name_(sandbox_server_bootstrap_name),
- sandbox_server_bootstrap_name_ptr_(
- sandbox_server_bootstrap_name_.c_str()),
- sandbox_token_(sandbox_token),
- is_yosemite_or_later_(base::mac::IsAtLeastOS10_10()),
- look_up_message_(CreateBootstrapLookUpMessage()) {}
-
-PreExecDelegate::~PreExecDelegate() {}
-
-void PreExecDelegate::RunAsyncSafe() {
- mach_port_t sandbox_server_port = MACH_PORT_NULL;
- kern_return_t kr = DoBootstrapLookUp(&sandbox_server_port);
- if (kr != KERN_SUCCESS)
- RAW_LOG(FATAL, "Failed to look up bootstrap sandbox server port.");
-
- mach_port_t new_bootstrap_port = MACH_PORT_NULL;
- if (!BootstrapSandbox::ClientCheckIn(sandbox_server_port,
- sandbox_token_,
- &new_bootstrap_port)) {
- RAW_LOG(FATAL, "Failed to check in with sandbox server.");
- }
-
- kr = task_set_bootstrap_port(mach_task_self(), new_bootstrap_port);
- if (kr != KERN_SUCCESS)
- RAW_LOG(FATAL, "Failed to replace bootstrap port.");
-
- // On OS X 10.10 and higher, libxpc uses the port stash to transfer the
- // XPC root port. This is effectively the same connection as the Mach
- // bootstrap port, but not transferred using the task special port.
- // Therefore, stash the replacement bootstrap port, so that on 10.10 it
- // will be retrieved by the XPC code and used as a replacement for the
- // XPC root port as well.
- if (is_yosemite_or_later_) {
- kr = mach_ports_register(mach_task_self(), &new_bootstrap_port, 1);
- if (kr != KERN_SUCCESS)
- RAW_LOG(ERROR, "Failed to register replacement bootstrap port.");
- }
-}
-
-xpc_object_t PreExecDelegate::CreateBootstrapLookUpMessage() {
- if (is_yosemite_or_later_) {
- xpc_object_t dictionary = xpc_dictionary_create(nullptr, nullptr, 0);
- xpc_dictionary_set_uint64(dictionary, "type", 7);
- xpc_dictionary_set_uint64(dictionary, "handle", 0);
- xpc_dictionary_set_string(dictionary, "name",
- sandbox_server_bootstrap_name_ptr_);
- xpc_dictionary_set_int64(dictionary, "targetpid", 0);
- xpc_dictionary_set_uint64(dictionary, "flags", 0);
- xpc_dictionary_set_uint64(dictionary, "subsystem", 5);
- xpc_dictionary_set_uint64(dictionary, "routine", 207);
- // Add a NULL port so that the slot in the dictionary is already
- // allocated.
- xpc_dictionary_set_mach_send(dictionary, "domain-port", MACH_PORT_NULL);
- return dictionary;
- }
-
- return nullptr;
-}
-
-kern_return_t PreExecDelegate::DoBootstrapLookUp(mach_port_t* out_port) {
- if (is_yosemite_or_later_) {
- xpc_dictionary_set_mach_send(look_up_message_, "domain-port",
- bootstrap_port);
-
- // |pipe| cannot be created pre-fork() since the |bootstrap_port| will
- // be invalidated. Deliberately leak |pipe| as well.
- xpc_pipe_t pipe = xpc_pipe_create_from_port(bootstrap_port, 0);
- xpc_object_t reply;
- int rv = xpc_pipe_routine(pipe, look_up_message_, &reply);
- if (rv != 0) {
- return xpc_dictionary_get_int64(reply, "error");
- } else {
- xpc_object_t port_value = xpc_dictionary_get_value(reply, "port");
- *out_port = xpc_mach_send_get_right(port_value);
- return *out_port != MACH_PORT_NULL ? KERN_SUCCESS : KERN_INVALID_RIGHT;
- }
- } else {
- // On non-XPC launchd systems, bootstrap_look_up() is MIG-based and
- // generally safe.
- return bootstrap_look_up(bootstrap_port,
- sandbox_server_bootstrap_name_ptr_, out_port);
- }
-}
-
-} // namespace sandbox
diff --git a/sandbox/mac/pre_exec_delegate.h b/sandbox/mac/pre_exec_delegate.h
deleted file mode 100644
index 4ed41db8..0000000
--- a/sandbox/mac/pre_exec_delegate.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_MAC_PRE_EXEC_DELEGATE_H_
-#define SANDBOX_MAC_PRE_EXEC_DELEGATE_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/process/launch.h"
-#include "sandbox/mac/xpc.h"
-
-namespace sandbox {
-
-// This PreExecDelegate will communicate with the BootstrapSandbox running
-// the Mach server registered under |sandbox_server_bootstrap_name|. It will
-// check in with th BootstrapSandbox using the |sandbox_token| and will
-// replace the task's bootstrap port with one provided by the sandbox.
-class PreExecDelegate : public base::LaunchOptions::PreExecDelegate {
- public:
- PreExecDelegate(const std::string& sandbox_server_bootstrap_name,
- uint64_t sandbox_token);
- ~PreExecDelegate() override;
-
- void RunAsyncSafe() override;
-
- uint64_t sandbox_token() const { return sandbox_token_; }
-
- private:
- // Allocates the bootstrap_look_up IPC message prior to fork().
- xpc_object_t CreateBootstrapLookUpMessage();
-
- // Performs a bootstrap_look_up(), either using the pre-allocated message
- // or the normal routine, depending on the OS X system version.
- kern_return_t DoBootstrapLookUp(mach_port_t* out_port);
-
- const std::string sandbox_server_bootstrap_name_;
- const char* const sandbox_server_bootstrap_name_ptr_;
- const uint64_t sandbox_token_;
- const bool is_yosemite_or_later_;
-
- // If is_yosemite_or_later_, this field is used to hold the pre-allocated XPC
- // object needed to interact with the bootstrap server in RunAsyncSafe().
- // This is deliberately leaked in the fork()ed process.
- xpc_object_t look_up_message_;
-
- DISALLOW_COPY_AND_ASSIGN(PreExecDelegate);
-};
-
-} // namespace sandbox
-
-#endif // SANDBOX_MAC_PRE_EXEC_DELEGATE_H_
diff --git a/sandbox/mac/xpc.h b/sandbox/mac/xpc.h
deleted file mode 100644
index 44ec8a1..0000000
--- a/sandbox/mac/xpc.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file provides forward declarations for private XPC symbols.
-
-#ifndef SANDBOX_MAC_XPC_H_
-#define SANDBOX_MAC_XPC_H_
-
-#include <AvailabilityMacros.h>
-#include <mach/mach.h>
-#include <bsm/libbsm.h>
-#include <xpc/xpc.h>
-
-#include "sandbox/sandbox_export.h"
-
-extern "C" {
-// Declare private types.
-typedef struct _xpc_pipe_s* xpc_pipe_t;
-
-// Signatures for private XPC functions.
-// Dictionary manipulation.
-void xpc_dictionary_set_mach_send(xpc_object_t dictionary,
- const char* name,
- mach_port_t port);
-void xpc_dictionary_get_audit_token(xpc_object_t dictionary,
- audit_token_t* token);
-
-// Raw object getters.
-mach_port_t xpc_mach_send_get_right(xpc_object_t value);
-
-// Pipe methods.
-xpc_pipe_t xpc_pipe_create_from_port(mach_port_t port, int flags);
-int xpc_pipe_receive(mach_port_t port, xpc_object_t* message);
-int xpc_pipe_routine(xpc_pipe_t pipe,
- xpc_object_t request,
- xpc_object_t* reply);
-int xpc_pipe_routine_reply(xpc_object_t reply);
-int xpc_pipe_simpleroutine(xpc_pipe_t pipe, xpc_object_t message);
-int xpc_pipe_routine_forward(xpc_pipe_t forward_to, xpc_object_t request);
-} // extern "C"
-
-#endif // SANDBOX_MAC_XPC_H_
diff --git a/sandbox/mac/xpc_message_server.cc b/sandbox/mac/xpc_message_server.cc
deleted file mode 100644
index 858c7dd..0000000
--- a/sandbox/mac/xpc_message_server.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/mac/xpc_message_server.h"
-
-#include <bsm/libbsm.h>
-
-#include <string>
-
-#include "base/mac/mach_logging.h"
-#include "base/strings/stringprintf.h"
-#include "sandbox/mac/xpc.h"
-
-namespace sandbox {
-
-XPCMessageServer::XPCMessageServer(MessageDemuxer* demuxer,
- mach_port_t server_receive_right)
- : demuxer_(demuxer),
- server_port_(server_receive_right),
- reply_message_(NULL) {}
-
-XPCMessageServer::~XPCMessageServer() {
-}
-
-bool XPCMessageServer::Initialize() {
- // Allocate a port for use as a new server port if one was not passed to the
- // constructor.
- if (!server_port_.is_valid()) {
- mach_port_t port;
- kern_return_t kr;
- if ((kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
- &port)) != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Failed to allocate new server port.";
- return false;
- }
- server_port_.reset(port);
- }
-
- std::string label = base::StringPrintf(
- "org.chromium.sandbox.XPCMessageServer.%p", demuxer_);
- dispatch_source_.reset(new base::DispatchSourceMach(
- label.c_str(), server_port_.get(), ^{ ReceiveMessage(); }));
- dispatch_source_->Resume();
-
- return true;
-}
-
-void XPCMessageServer::Shutdown() {
- dispatch_source_.reset();
-}
-
-pid_t XPCMessageServer::GetMessageSenderPID(IPCMessage request) {
- audit_token_t token;
- xpc_dictionary_get_audit_token(request.xpc, &token);
- pid_t sender_pid = audit_token_to_pid(token);
- return sender_pid;
-}
-
-IPCMessage XPCMessageServer::CreateReply(IPCMessage request) {
- if (!reply_message_)
- reply_message_ = xpc_dictionary_create_reply(request.xpc);
-
- IPCMessage reply;
- reply.xpc = reply_message_;
- return reply;
-}
-
-bool XPCMessageServer::SendReply(IPCMessage reply) {
- if (!reply.xpc)
- return false;
-
- int rv = xpc_pipe_routine_reply(reply.xpc);
- if (rv) {
- LOG(ERROR) << "Failed to xpc_pipe_routine_reply(): " << rv;
- return false;
- }
- return true;
-}
-
-void XPCMessageServer::ForwardMessage(IPCMessage request,
- mach_port_t destination) {
- xpc_pipe_t pipe = xpc_pipe_create_from_port(destination, 0);
- int rv = xpc_pipe_routine_forward(pipe, request.xpc);
- if (rv) {
- LOG(ERROR) << "Failed to xpc_pipe_routine_forward(): " << rv;
- }
- xpc_release(pipe);
-}
-
-void XPCMessageServer::RejectMessage(IPCMessage request, int error_code) {
- IPCMessage reply = CreateReply(request);
- // The message wasn't expecting a reply, so rejecting means ignoring it.
- if (reply.xpc) {
- xpc_dictionary_set_int64(reply.xpc, "error", error_code);
- SendReply(reply);
- }
-}
-
-mach_port_t XPCMessageServer::GetServerPort() const {
- return server_port_.get();
-}
-
-void XPCMessageServer::ReceiveMessage() {
- IPCMessage request;
- int rv = xpc_pipe_receive(server_port_.get(), &request.xpc);
- if (rv) {
- LOG(ERROR) << "Failed to xpc_pipe_receive(): " << rv;
- return;
- }
-
- demuxer_->DemuxMessage(request);
-
- xpc_release(request.xpc);
- if (reply_message_) {
- xpc_release(reply_message_);
- reply_message_ = NULL;
- }
-}
-
-} // namespace sandbox
diff --git a/sandbox/mac/xpc_message_server.h b/sandbox/mac/xpc_message_server.h
deleted file mode 100644
index 9342ef06..0000000
--- a/sandbox/mac/xpc_message_server.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_MAC_XPC_MESSAGE_SERVER_H_
-#define SANDBOX_MAC_XPC_MESSAGE_SERVER_H_
-
-#include <AvailabilityMacros.h>
-
-#include <memory>
-
-#include "base/mac/dispatch_source_mach.h"
-#include "base/mac/scoped_mach_port.h"
-#include "base/macros.h"
-#include "sandbox/mac/message_server.h"
-#include "sandbox/mac/xpc.h"
-#include "sandbox/sandbox_export.h"
-
-namespace sandbox {
-
-// An implementation of MessageServer that uses XPC pipes to read and write XPC
-// messages from a Mach port.
-class SANDBOX_EXPORT XPCMessageServer : public MessageServer {
- public:
- // Creates a new XPC message server that will send messages to |demuxer|
- // for handling. If the |server_receive_right| is non-NULL, this class will
- // take ownership of the port and it will be used to receive messages.
- // Otherwise the server will create a new receive right on which to listen.
- XPCMessageServer(MessageDemuxer* demuxer,
- mach_port_t server_receive_right);
- ~XPCMessageServer() override;
-
- // MessageServer:
- bool Initialize() override;
- void Shutdown() override;
- pid_t GetMessageSenderPID(IPCMessage request) override;
- IPCMessage CreateReply(IPCMessage request) override;
- bool SendReply(IPCMessage reply) override;
- void ForwardMessage(IPCMessage request, mach_port_t destination) override;
- // Creates an error reply message with a field "error" set to |error_code|.
- void RejectMessage(IPCMessage request, int error_code) override;
- mach_port_t GetServerPort() const override;
-
- private:
- // Reads a message from the XPC pipe.
- void ReceiveMessage();
-
- // The demuxer delegate. Weak.
- MessageDemuxer* demuxer_;
-
- // The Mach port on which the server is receiving requests.
- base::mac::ScopedMachReceiveRight server_port_;
-
- // MACH_RECV dispatch source that handles the |server_port_|.
- std::unique_ptr<base::DispatchSourceMach> dispatch_source_;
-
- // The reply message, if one has been created.
- xpc_object_t reply_message_;
-
- DISALLOW_COPY_AND_ASSIGN(XPCMessageServer);
-};
-
-} // namespace sandbox
-
-#endif // SANDBOX_MAC_XPC_MESSAGE_SERVER_H_
diff --git a/sandbox/mac/xpc_message_server_unittest.cc b/sandbox/mac/xpc_message_server_unittest.cc
deleted file mode 100644
index 551db3c0..0000000
--- a/sandbox/mac/xpc_message_server_unittest.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/mac/xpc_message_server.h"
-
-#include <Block.h>
-#include <mach/mach.h>
-#include <servers/bootstrap.h>
-#include <stdint.h>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_mach_port.h"
-#include "base/process/kill.h"
-#include "base/test/multiprocess_test.h"
-#include "sandbox/mac/xpc.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace sandbox {
-
-// A MessageDemuxer that manages a test server and executes a block for every
-// message.
-class BlockDemuxer : public MessageDemuxer {
- public:
- BlockDemuxer()
- : demux_block_(NULL),
- server_(this, MACH_PORT_NULL),
- pipe_(NULL) {
- }
-
- ~BlockDemuxer() override {
- if (pipe_)
- xpc_release(pipe_);
- if (demux_block_)
- Block_release(demux_block_);
- }
-
- // Starts running the server, given a block to handle incoming IPC messages.
- bool Initialize(void (^demux_block)(IPCMessage request)) {
- if (!server_.Initialize())
- return false;
-
- // Create a send right on the port so that the XPC pipe can be created.
- if (mach_port_insert_right(mach_task_self(), server_.GetServerPort(),
- server_.GetServerPort(), MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS) {
- return false;
- }
- scoped_send_right_.reset(server_.GetServerPort());
-
- demux_block_ = Block_copy(demux_block);
- pipe_ = xpc_pipe_create_from_port(server_.GetServerPort(), 0);
-
- return true;
- }
-
- void DemuxMessage(IPCMessage request) override {
- demux_block_(request);
- }
-
- xpc_pipe_t pipe() { return pipe_; }
-
- XPCMessageServer* server() { return &server_; }
-
- private:
- void (^demux_block_)(IPCMessage request);
-
- XPCMessageServer server_;
-
- base::mac::ScopedMachSendRight scoped_send_right_;
-
- xpc_pipe_t pipe_;
-};
-
-TEST(XPCMessageServerTest, ReceiveMessage) {
- BlockDemuxer fixture;
- XPCMessageServer* server = fixture.server();
-
- uint64_t __block value = 0;
- ASSERT_TRUE(fixture.Initialize(^(IPCMessage request) {
- value = xpc_dictionary_get_uint64(request.xpc, "test_value");
- server->SendReply(server->CreateReply(request));
- }));
-
- xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0);
- xpc_dictionary_set_uint64(request, "test_value", 42);
-
- xpc_object_t reply;
- EXPECT_EQ(0, xpc_pipe_routine(fixture.pipe(), request, &reply));
-
- EXPECT_EQ(42u, value);
-
- xpc_release(request);
- xpc_release(reply);
-}
-
-TEST(XPCMessageServerTest, RejectMessage) {
- BlockDemuxer fixture;
- XPCMessageServer* server = fixture.server();
- ASSERT_TRUE(fixture.Initialize(^(IPCMessage request) {
- server->RejectMessage(request, EPERM);
- }));
-
- xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0);
- xpc_object_t reply;
- EXPECT_EQ(0, xpc_pipe_routine(fixture.pipe(), request, &reply));
-
- EXPECT_EQ(EPERM, xpc_dictionary_get_int64(reply, "error"));
-
- xpc_release(request);
- xpc_release(reply);
-}
-
-TEST(XPCMessageServerTest, RejectMessageSimpleRoutine) {
- BlockDemuxer fixture;
- XPCMessageServer* server = fixture.server();
- ASSERT_TRUE(fixture.Initialize(^(IPCMessage request) {
- server->RejectMessage(request, -99);
- }));
-
- // Create a message that is not expecting a reply.
- xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0);
- EXPECT_EQ(0, xpc_pipe_simpleroutine(fixture.pipe(), request));
-
- xpc_release(request);
-}
-
-char kGetSenderPID[] = "org.chromium.sandbox.test.GetSenderPID";
-
-TEST(XPCMessageServerTest, GetSenderPID) {
- BlockDemuxer fixture;
- XPCMessageServer* server = fixture.server();
-
- pid_t __block sender_pid = 0;
- int64_t __block child_pid = 0;
- ASSERT_TRUE(fixture.Initialize(^(IPCMessage request) {
- sender_pid = server->GetMessageSenderPID(request);
- child_pid = xpc_dictionary_get_int64(request.xpc, "child_pid");
- }));
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- kern_return_t kr = bootstrap_register(bootstrap_port, kGetSenderPID,
- server->GetServerPort());
-#pragma GCC diagnostic pop
- ASSERT_EQ(KERN_SUCCESS, kr);
-
- base::Process child = base::SpawnMultiProcessTestChild(
- "GetSenderPID", base::GetMultiProcessTestChildBaseCommandLine(),
- base::LaunchOptions());
- ASSERT_TRUE(child.IsValid());
-
- int exit_code = -1;
- ASSERT_TRUE(child.WaitForExit(&exit_code));
- EXPECT_EQ(0, exit_code);
-
- EXPECT_EQ(child.Pid(), sender_pid);
- EXPECT_EQ(child.Pid(), child_pid);
- EXPECT_EQ(sender_pid, child_pid);
-}
-
-MULTIPROCESS_TEST_MAIN(GetSenderPID) {
- mach_port_t port = MACH_PORT_NULL;
- CHECK_EQ(KERN_SUCCESS, bootstrap_look_up(bootstrap_port, kGetSenderPID,
- &port));
- base::mac::ScopedMachSendRight scoped_port(port);
-
- xpc_pipe_t pipe = xpc_pipe_create_from_port(port, 0);
-
- xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
- xpc_dictionary_set_int64(message, "child_pid", getpid());
- CHECK_EQ(0, xpc_pipe_simpleroutine(pipe, message));
-
- xpc_release(message);
- xpc_release(pipe);
-
- return 0;
-}
-
-TEST(XPCMessageServerTest, ForwardMessage) {
- BlockDemuxer first;
- XPCMessageServer* first_server = first.server();
-
- BlockDemuxer second;
- XPCMessageServer* second_server = second.server();
-
- ASSERT_TRUE(first.Initialize(^(IPCMessage request) {
- xpc_dictionary_set_int64(request.xpc, "seen_by_first", 1);
- first_server->ForwardMessage(request, second_server->GetServerPort());
- }));
- ASSERT_TRUE(second.Initialize(^(IPCMessage request) {
- IPCMessage reply = second_server->CreateReply(request);
- xpc_dictionary_set_int64(reply.xpc, "seen_by_first",
- xpc_dictionary_get_int64(request.xpc, "seen_by_first"));
- xpc_dictionary_set_int64(reply.xpc, "seen_by_second", 2);
- second_server->SendReply(reply);
- }));
-
- xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0);
- xpc_object_t reply;
- ASSERT_EQ(0, xpc_pipe_routine(first.pipe(), request, &reply));
-
- EXPECT_EQ(1, xpc_dictionary_get_int64(reply, "seen_by_first"));
- EXPECT_EQ(2, xpc_dictionary_get_int64(reply, "seen_by_second"));
-
- xpc_release(request);
- xpc_release(reply);
-}
-
-} // namespace sandbox