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 |