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. |
Mark Mentovai
2015/09/17 19:45:15
Or you could make a new receive right for each cli
Robert Sesek
2015/09/17 20:27:24
That's what I want(ed) to do, but because a task's
| |
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 | |
68 // Called in the parent after fork()ing a child. It records the |handle| | |
69 // and associates it with the specified-above |sandbox_policy_id|. | |
70 // If fork() failed and a new child was not created, pass kNullProcessHandle. | |
71 void FinishedFork(base::ProcessHandle handle); | |
72 | 72 |
73 // Called in the parent when a process has died. It cleans up the references | 73 // Called in the parent when a process has died. It cleans up the references |
74 // to the process. | 74 // to the process. |
75 void ChildDied(base::ProcessHandle handle); | 75 void InvalidateClient(base::ProcessHandle handle); |
76 | 76 |
77 // Looks up the policy for a given process ID. If no policy is associated | 77 // Looks up the policy for a given process ID. If no policy is associated |
78 // with the |pid|, this returns NULL. | 78 // with the |pid|, this returns NULL. |
79 const BootstrapSandboxPolicy* PolicyForProcess(pid_t pid) const; | 79 const BootstrapSandboxPolicy* PolicyForProcess(pid_t pid) const; |
80 | 80 |
81 std::string server_bootstrap_name() const { return server_bootstrap_name_; } | 81 std::string server_bootstrap_name() const { return server_bootstrap_name_; } |
82 mach_port_t real_bootstrap_port() const { return real_bootstrap_port_; } | 82 mach_port_t real_bootstrap_port() const { return real_bootstrap_port_; } |
83 | 83 |
84 private: | 84 private: |
85 BootstrapSandbox(); | 85 BootstrapSandbox(); |
86 | 86 |
87 // Dispatch callout for when a client sends a message on the | |
88 // |check_in_port_|. If the client message is valid, it will assign the | |
89 // client from |awaiting_processes_| to |sandboxed_processes_|. | |
90 void HandleChildCheckIn(); | |
91 | |
87 // The name in the system bootstrap server by which the |server_|'s port | 92 // The name in the system bootstrap server by which the |server_|'s port |
88 // is known. | 93 // is known. |
89 const std::string server_bootstrap_name_; | 94 const std::string server_bootstrap_name_; |
90 | 95 |
91 // The original bootstrap port of the process, which is connected to the | 96 // The original bootstrap port of the process, which is connected to the |
92 // real launchd server. | 97 // real launchd server. |
93 base::mac::ScopedMachSendRight real_bootstrap_port_; | 98 base::mac::ScopedMachSendRight real_bootstrap_port_; |
94 | 99 |
95 // The |lock_| protects all the following variables. | 100 // The |lock_| protects all the following variables. |
96 mutable base::Lock lock_; | 101 mutable base::Lock lock_; |
97 | 102 |
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. | 103 // All the policies that have been registered with this sandbox manager. |
102 std::map<int, const BootstrapSandboxPolicy> policies_; | 104 std::map<int, const BootstrapSandboxPolicy> policies_; |
103 | 105 |
104 // The association between process ID and sandbox policy ID. | 106 // The association between process ID and sandbox policy ID. |
105 std::map<base::ProcessHandle, int> sandboxed_processes_; | 107 std::map<base::ProcessHandle, int> sandboxed_processes_; |
106 | 108 |
109 // The association between a new process' sandbox token and its policy ID. | |
110 // The entry is removed after the process checks in, and the mapping moves | |
111 // to |sandboxed_processes_|. | |
112 std::map<uint64_t, int> awaiting_processes_; | |
113 | |
107 // A Mach IPC message server that is used to intercept and filter bootstrap | 114 // A Mach IPC message server that is used to intercept and filter bootstrap |
108 // requests. | 115 // requests. |
109 scoped_ptr<LaunchdInterceptionServer> server_; | 116 scoped_ptr<LaunchdInterceptionServer> launchd_server_; |
117 | |
118 // The port and dispatch source for receiving client check in messages sent | |
119 // via ClientCheckIn(). | |
120 base::mac::ScopedMachReceiveRight check_in_port_; | |
121 scoped_ptr<base::DispatchSourceMach> check_in_server_; | |
110 }; | 122 }; |
111 | 123 |
112 } // namespace sandbox | 124 } // namespace sandbox |
113 | 125 |
114 #endif // SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_ | 126 #endif // SANDBOX_MAC_BOOTSTRAP_SANDBOX_H_ |
OLD | NEW |