summaryrefslogtreecommitdiff
path: root/sandbox/mac/bootstrap_sandbox_unittest.mm
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/mac/bootstrap_sandbox_unittest.mm')
-rw-r--r--sandbox/mac/bootstrap_sandbox_unittest.mm518
1 files changed, 0 insertions, 518 deletions
diff --git a/sandbox/mac/bootstrap_sandbox_unittest.mm b/sandbox/mac/bootstrap_sandbox_unittest.mm
deleted file mode 100644
index 717f3f99f3..0000000000
--- a/sandbox/mac/bootstrap_sandbox_unittest.mm
+++ /dev/null
@@ -1,518 +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"
-#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;
- if (base::mac::IsOSSnowLeopard())
- policy.rules["com.apple.SecurityServer"] = Rule(POLICY_ALLOW);
- return policy;
- }
-
- void RunChildWithPolicy(int policy_id,
- const char* child_name,
- base::ProcessHandle* out_pid) {
- sandbox_->PrepareToForkWithPolicy(policy_id);
- base::LaunchOptions options;
- options.replacement_bootstrap_name = sandbox_->server_bootstrap_name();
- base::Process process = SpawnChildWithOptions(child_name, options);
- ASSERT_TRUE(process.IsValid());
- sandbox_->FinishedFork(process.Handle());
- int code = 0;
- EXPECT_TRUE(process.WaitForExit(&code));
- EXPECT_EQ(0, code);
- if (out_pid)
- *out_pid = process.Pid();
- }
-
- protected:
- scoped_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) {
- 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) {
- 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) {
- 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) {
- 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) {
- 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));
- // On 10.6, bootstrap_lookup2 may add an extra right to place it in a per-
- // process cache.
- if (base::mac::IsOSSnowLeopard())
- EXPECT_TRUE(send_rights == 3u || send_rights == 2u) << send_rights;
- else
- 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) {
- 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) {
- 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.
- sandbox_->PrepareToForkWithPolicy(kTestPolicyId);
- base::LaunchOptions options;
- options.replacement_bootstrap_name = sandbox_->server_bootstrap_name();
- base::Process process = SpawnChildWithOptions("ChildOutliveSandbox", options);
- ASSERT_TRUE(process.IsValid());
- sandbox_->FinishedFork(process.Handle());
-
- // 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