| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_ | 5 #ifndef SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_ |
| 6 #define SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_ | 6 #define SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_ |
| 7 | 7 |
| 8 #include <mach/mach.h> | 8 #include <mach/mach.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| 11 #include <string> | 11 #include <string> |
| 12 | 12 |
| 13 #include "base/mac/dispatch_source_mach.h" |
| 13 #include "base/mac/scoped_mach_port.h" | 14 #include "base/mac/scoped_mach_port.h" |
| 14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/process/process_handle.h" | 16 #include "base/process/process_handle.h" |
| 16 #include "base/synchronization/lock.h" | 17 #include "base/synchronization/lock.h" |
| 17 #include "sandbox/mac/policy.h" | 18 #include "sandbox/mac/policy.h" |
| 18 #include "sandbox/sandbox_export.h" | 19 #include "sandbox/sandbox_export.h" |
| 19 | 20 |
| 20 namespace sandbox { | 21 namespace sandbox { |
| 21 | 22 |
| 22 class LaunchdInterceptionServer; | 23 class LaunchdInterceptionServer; |
| 24 class PreExecDelegate; |
| 23 | 25 |
| 24 // The BootstrapSandbox is a second-layer sandbox for Mac. It is used to limit | 26 // The BootstrapSandbox is a second-layer sandbox for Mac. It is used to limit |
| 25 // the bootstrap namespace attack surface of child processes. The parent | 27 // the bootstrap namespace attack surface of child processes. The parent |
| 26 // process creates an instance of this class and registers policies that it | 28 // process creates an instance of this class and registers policies that it |
| 27 // can enforce on its children. | 29 // can enforce on its children. |
| 28 // | 30 // |
| 29 // With this sandbox, the parent process must replace the bootstrap port prior | 31 // With this sandbox, the parent process must create the client using the |
| 30 // to the sandboxed target's execution. This should be done by setting the | 32 // sandbox's PreExecDelegate, which will replace the bootstrap port of the |
| 31 // base::LaunchOptions.replacement_bootstrap_name to the | 33 // child process. Requests from the child that would normally go to launchd |
| 32 // server_bootstrap_name() of this class. Requests from the child that would | 34 // are filtered based on the specified per-process policies. If a request is |
| 33 // normally go to launchd are filtered based on the specified per-process | 35 // permitted by the policy, it is forwarded on to launchd for servicing. If it |
| 34 // policies. If a request is permitted by the policy, it is forwarded on to | 36 // is not, then the sandbox will reply with a primitive that does not grant |
| 35 // launchd for servicing. If it is not, then the sandbox will reply with a | 37 // additional capabilities to the receiver. |
| 36 // primitive that does not grant additional capabilities to the receiver. | |
| 37 // | |
| 38 // Clients that which to use the sandbox must inform it of the creation and | |
| 39 // death of child processes for which the sandbox should be enforced. The | |
| 40 // client of the sandbox is intended to be an unsandboxed parent process that | |
| 41 // fork()s sandboxed (and other unsandboxed) child processes. | |
| 42 // | 38 // |
| 43 // When the parent is ready to fork a new child process with this sandbox | 39 // When the parent is ready to fork a new child process with this sandbox |
| 44 // being enforced, it should use the pair of methods PrepareToForkWithPolicy() | 40 // being enforced, it should use NewClient() to create a PreExecDelegate for |
| 45 // and FinishedFork(), and call fork() between them. The first method will | 41 // a sandbox policy ID and set it to the base::LaunchOptions.pre_exec_delegate. |
| 46 // set the policy for the new process, and the second will finialize the | |
| 47 // association between the process ID and sandbox policy ID. | |
| 48 // | 42 // |
| 49 // All methods of this class may be called from any thread, but | 43 // When a child process exits, the parent should call InvalidateClient() to |
| 50 // PrepareToForkWithPolicy() and FinishedFork() must be non-nested and balanced. | 44 // clean up any mappings in this class. |
| 45 // |
| 46 // All methods of this class may be called from any thread. |
| 51 class SANDBOX_EXPORT BootstrapSandbox { | 47 class SANDBOX_EXPORT BootstrapSandbox { |
| 52 public: | 48 public: |
| 53 // Creates a new sandbox manager. Returns NULL on failure. | 49 // Creates a new sandbox manager. Returns NULL on failure. |
| 54 static scoped_ptr<BootstrapSandbox> Create(); | 50 static scoped_ptr<BootstrapSandbox> Create(); |
| 55 | 51 |
| 52 // For use in newly created child processes. Checks in with the bootstrap |
| 53 // sandbox manager running in the parent process. |sandbox_server_port| is |
| 54 // the Mach send right to the sandbox |check_in_server_| (in the child). |
| 55 // |sandbox_token| is the assigned token. On return, |bootstrap_port| is set |
| 56 // to a new Mach send right to be used in the child as the task's bootstrap |
| 57 // port. |
| 58 static bool ClientCheckIn(mach_port_t sandbox_server_port, |
| 59 uint64_t sandbox_token, |
| 60 mach_port_t* bootstrap_port); |
| 61 |
| 56 ~BootstrapSandbox(); | 62 ~BootstrapSandbox(); |
| 57 | 63 |
| 58 // Registers a bootstrap policy associated it with an identifier. The | 64 // Registers a bootstrap policy associated it with an identifier. The |
| 59 // |sandbox_policy_id| must be greater than 0. | 65 // |sandbox_policy_id| must be greater than 0. |
| 60 void RegisterSandboxPolicy(int sandbox_policy_id, | 66 void RegisterSandboxPolicy(int sandbox_policy_id, |
| 61 const BootstrapSandboxPolicy& policy); | 67 const BootstrapSandboxPolicy& policy); |
| 62 | 68 |
| 63 // Called in the parent prior to fork()ing a child. The policy registered | 69 // Creates a new PreExecDelegate to pass to base::LaunchOptions. This will |
| 64 // to |sandbox_policy_id| will be enforced on the new child. This must be | 70 // enforce the policy with |sandbox_policy_id| on the new process. |
| 65 // followed by a call to FinishedFork(). | 71 scoped_ptr<PreExecDelegate> NewClient(int sandbox_policy_id); |
| 66 void PrepareToForkWithPolicy(int sandbox_policy_id); | |
| 67 | 72 |
| 68 // Called in the parent after fork()ing a child. It records the |handle| | 73 // If a client did not launch properly, the sandbox provided to the |
| 69 // and associates it with the specified-above |sandbox_policy_id|. | 74 // PreExecDelegate should be invalidated using this method. |
| 70 // If fork() failed and a new child was not created, pass kNullProcessHandle. | 75 void RevokeToken(uint64_t token); |
| 71 void FinishedFork(base::ProcessHandle handle); | |
| 72 | 76 |
| 73 // Called in the parent when a process has died. It cleans up the references | 77 // Called in the parent when a process has died. It cleans up the references |
| 74 // to the process. | 78 // to the process. |
| 75 void ChildDied(base::ProcessHandle handle); | 79 void InvalidateClient(base::ProcessHandle handle); |
| 76 | 80 |
| 77 // Looks up the policy for a given process ID. If no policy is associated | 81 // Looks up the policy for a given process ID. If no policy is associated |
| 78 // with the |pid|, this returns NULL. | 82 // with the |pid|, this returns NULL. |
| 79 const BootstrapSandboxPolicy* PolicyForProcess(pid_t pid) const; | 83 const BootstrapSandboxPolicy* PolicyForProcess(pid_t pid) const; |
| 80 | 84 |
| 81 std::string server_bootstrap_name() const { return server_bootstrap_name_; } | 85 std::string server_bootstrap_name() const { return server_bootstrap_name_; } |
| 82 mach_port_t real_bootstrap_port() const { return real_bootstrap_port_; } | 86 mach_port_t real_bootstrap_port() const { return real_bootstrap_port_; } |
| 83 | 87 |
| 84 private: | 88 private: |
| 85 BootstrapSandbox(); | 89 BootstrapSandbox(); |
| 86 | 90 |
| 91 // Dispatch callout for when a client sends a message on the |
| 92 // |check_in_port_|. If the client message is valid, it will assign the |
| 93 // client from |awaiting_processes_| to |sandboxed_processes_|. |
| 94 void HandleChildCheckIn(); |
| 95 |
| 87 // The name in the system bootstrap server by which the |server_|'s port | 96 // The name in the system bootstrap server by which the |server_|'s port |
| 88 // is known. | 97 // is known. |
| 89 const std::string server_bootstrap_name_; | 98 const std::string server_bootstrap_name_; |
| 90 | 99 |
| 91 // The original bootstrap port of the process, which is connected to the | 100 // The original bootstrap port of the process, which is connected to the |
| 92 // real launchd server. | 101 // real launchd server. |
| 93 base::mac::ScopedMachSendRight real_bootstrap_port_; | 102 base::mac::ScopedMachSendRight real_bootstrap_port_; |
| 94 | 103 |
| 95 // The |lock_| protects all the following variables. | 104 // The |lock_| protects all the following variables. |
| 96 mutable base::Lock lock_; | 105 mutable base::Lock lock_; |
| 97 | 106 |
| 98 // The sandbox_policy_id that will be enforced for the new child. | |
| 99 int effective_policy_id_; | |
| 100 | |
| 101 // All the policies that have been registered with this sandbox manager. | 107 // All the policies that have been registered with this sandbox manager. |
| 102 std::map<int, const BootstrapSandboxPolicy> policies_; | 108 std::map<int, const BootstrapSandboxPolicy> policies_; |
| 103 | 109 |
| 104 // The association between process ID and sandbox policy ID. | 110 // The association between process ID and sandbox policy ID. |
| 105 std::map<base::ProcessHandle, int> sandboxed_processes_; | 111 std::map<base::ProcessHandle, int> sandboxed_processes_; |
| 106 | 112 |
| 113 // The association between a new process' sandbox token and its policy ID. |
| 114 // The entry is removed after the process checks in, and the mapping moves |
| 115 // to |sandboxed_processes_|. |
| 116 std::map<uint64_t, int> awaiting_processes_; |
| 117 |
| 107 // A Mach IPC message server that is used to intercept and filter bootstrap | 118 // A Mach IPC message server that is used to intercept and filter bootstrap |
| 108 // requests. | 119 // requests. |
| 109 scoped_ptr<LaunchdInterceptionServer> server_; | 120 scoped_ptr<LaunchdInterceptionServer> launchd_server_; |
| 121 |
| 122 // The port and dispatch source for receiving client check in messages sent |
| 123 // via ClientCheckIn(). |
| 124 base::mac::ScopedMachReceiveRight check_in_port_; |
| 125 scoped_ptr<base::DispatchSourceMach> check_in_server_; |
| 110 }; | 126 }; |
| 111 | 127 |
| 112 } // namespace sandbox | 128 } // namespace sandbox |
| 113 | 129 |
| 114 #endif // SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_ | 130 #endif // SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_ |
| OLD | NEW |