1# **Mac Sandbox V2 Design Doc**
2*Status: Final, Authors: kerrnel@chromium.org, rsesek@chromium.org, Last Updated: 2020-05-14*
3
4# **Objective**
5
6To improve security on macOS by sandboxing the currently unsandboxed
7warmup phase of Chromium child processes, and to remove legacy artifacts
8in the sandbox profiles by rewriting them to use the most modern
9profile features.
10
11# **Background**
12
13Chromium historically ran an unsandboxed warm up routine to acquire
14system resources, before entering the sandbox. This design doc
15provides a full implementation design and deployment strategy to
16sandbox the warmup phase. This document also provides a high level
17overview of the macOS provided sandbox.
18
19In the warm up phase, Chromium called system frameworks which
20acquired an unspecified number of resources before being sandboxed,
21and those resources change with every new OS update from Apple.
22This [2009 Chromium blog
23post](https://blog.chromium.org/2009/06/google-chrome-sandboxing-and-mac-os-x.html&sa=D&ust=1492473048358000&usg=AFQjCNGEbmCLUqoH9-BeudDcNf5NmW-UcQ)
24explains that the warmup phase exists because it was unknown how
25to determine what resources those APIs used at the time. By explicitly
26enumerating all resources in the sandbox profiles, it is possible
27to accurately audit Chromium's attack surface for each new macOS
28version.
29
30Anyone wishing to know more about the macOS sandbox profile language
31should read the [Apple Sandbox
32Guide](http://reverse.put.as/wp-content/uploads/2011/09/Apple-Sandbox-Guide-v1.0.pdf)
33from reverse.put.as, or see the Appendix of this doc.
34
35# **The V2 Sandbox Implementation**
36
37The V2 sandbox continues to use the OS provided sandboxing
38framework and the "deny resource access by default" policy that the
39V1 sandbox used. The major difference under the V2 sandbox architecture
40is the removal of the unsandboxed warmup phase.
41
42# **Compatibility and Security Risk**
43
44Chromium's sandbox incurs two levels of risk which must be weighed:
45compatibility risk and security risk. Compatibility risk is the
46risk that Apple changes the resources that a system framework
47accesses, causing Chromium's sandbox to block the access. Security
48risk is the possibility that Chromium will be compromised because the
49sandbox allowed access to dangerous resources.
50
51A more permissive sandbox profile reduces compatibility risk but
52increases security risk and vice versa. See
53[crbug.com/619981](https://bugs.chromium.org/p/chromium/issues/detail?id=619981)
54for an example of how even given the V1 unsandboxed warmup phase, the
55implementation already dealt with compatibility risk.
56
57The V1 sandbox also has greater security risk at the warmup
58time, since that phase is unsandboxed. Rather than incurring both
59compatibility and security risk during execution, the V2 sandbox
60shifts the risk profile to take on more compatibility risk, since
61the warmup phase is eliminated, but it eliminates security risk.
62
63# **Success Criteria**
64
65The V2 sandbox will be deemed a success when it has been deployed
66to stable users for all processes in Chromium, and Chromium does not
67lose functionality due to the new sandbox rules.
68
69# **Design Overview**
70
71The Chromium Helper executable will now receive a sandbox profile
72and list of sandbox parameters (for example, the location of the
73user's home directory). The Helper executable will then apply the
74sandbox profile, with the parameters, to the process and then
75continue its execution into the ChromeMain function.
76
77# **Detailed Design**
78
79## Executable Structure
80
81Both the main Chromium executable and all of the bundled Chromium Helper
82executables contain [a minimal amount of
83code](https://source.chromium.org/chromium/chromium/src/+/master:chrome/app/chrome_exe_main_mac.cc;drc=05219ddeb8130389da9ad634ba3e021a70bff393).
84The bulk of the code lives in the Chromium Framework library, which is
85`dlopen()`ed at runtime to call `ChromeMain()`, after applying the sandbox.
86
87This design choice has beneficial security properties: many system frameworks
88run static initializers, and some of these static initializers acquire and
89maintain access to files or Mach service ports. If the executables directly
90linked the Chromium Framework or the system frameworks, then those initializers
91would be able to run outside the sandbox, since static initializers run before
92`main()`. The Chromium and Helper executables instead only link
93`/usr/lib/libSystem.dylib` and the very small `//sandbox/mac` target, to bring
94in `/usr/lib/libsandbox.dylib`. After the executable applies the sandbox, the
95program then loads the Framework, which causes all the dependent system
96frameworks to load.
97
98## Sandbox Profile Principles
99
100The sandbox profiles will use the following principles when
101implementing the profiles for each process type.
102
103- The profiles deny resource access to anything not explicitly allowed.
104- Processes may access all system libraries and frameworks.
105- Explicitly list which system resources (files, folders, mach services,
106    sysctls, IPC, IOKit calls) Chromium may access. Analyze each resource access
107    for safety first.
108
109## Sandbox Design
110
111The V1 sandbox code lives in
112[sandbox_mac.mm](https://source.chromium.org/chromium/chromium/src/+/master:services/service_manager/sandbox/mac/sandbox_mac.mm;l=1;drc=efd8e880522dc1df3b8883648513016fab3d3956).
113This file will continue to exist until the V1 sandbox is removed for all process
114types. Chromium now uses the V2 sandbox for all process types except the GPU
115process.
116
117## Code Structure
118
119Chromium's architecture is multi-process with a main browser process
120and some number of helper processes which performs tasks such as
121rendering web pages, running GPU processes, or various utility
122functions. The main browser process launches the other processes
123using the "Google Chromium Helper" executable. The browser passes
124command line flags to the Helper executable indicating what type
125of process it should execute as.
126
127The browser creates a pipe to the Helper executable, and
128using that pipe, the Helper executable reads a protobuf message
129from the browser process. The profobuf message contains the
130profile string and a map of the sandbox parameters. Using the
131lightweight protobuf prevents the error prone parsing code for a
132whole parameters list from being re-implemented. This must happen
133in the main executable itself, as the process must be sandboxed
134before the framework is loaded.
135
136The Helper executable will immediately initialize the sandbox, using
137the profile and parameters, before continuing execution to the
138`ChromeMain()` function.
139
140# **Design Alternatives**
141
142One alternative design is the current design where process acquires
143numerous system resources early in the execution phase and then
144applies the sandbox. However, this means that we do not have a
145consistent and auditable way to track what resources Chromium is using
146over time. Chromium's attack surface can increase significantly with
147a new OS release, and we would not know. The new explicit profiles
148make the attack surface very auditable and easy to understand.
149
150Another alternative would have been the [Bootstrap
151Sandbox](https://docs.google.com/document/d/108sr6gBxqdrnzVPsb_4_JbDyW1V4-DRQUC4R8YvM40M/view)
152plan, which proposed intercepting all mach connections to limit the
153attack surface. However, with the rewritten launchd released in macOS
15410.10 Yosemite, messages could no longer be intercepted and forward.
155This design solves the same problem by sandboxing the warmup phase,
156and allowing the existing system sandbox to enforce the security.
157
158# **Appendix**
159
160## Sandbox Profile Language
161
162This document has referenced sandbox profiles, which are written
163in a subset of Scheme. This is a macOS supplied format called Sandbox
164Profile Language (SBPL). As there is no official OS-provided
165documentation for the SBPL, this design doc provides a short
166description below so that other engineers can understand the
167constructs that Chromium is leveraging.
168
169SBPL files accept parameters. A parameter is a way to pass variable
170information into the sandbox profile that is not known at compile-time,
171for example the location of the user's home directory. A short
172sample profile which uses parameters is below.
173
174
175```
176(version 1)
177(deny default)
178(allow file-read* (subpath (param "USER_HOME_DIR")))
179```
180
181This profile will allow the application to read all files in the
182user's home directory, and nothing else. The (subpath) directive
183says that it applies to all paths underneath the specified path,
184and not just the actual path. The following code will apply the
185sandbox, pass the parameters, and access a file in the home directory.
186
187
188```
189#import <Foundation/Foundation.h>
190#import <sandbox.h>
191#import <sys/stat.h>
192// sandbox_init* functions are not in the public header.
193int sandbox_init_with_parameters(const char *profile,
194                                 uint64_t flags,
195                                 const char *const parameters[],
196                                 char **errorbuf);
197
198int main(int argc, const char * argv[]) {
199  const char profile[] = "(version 1)" \
200      "(deny default)" \
201      "(allow file-read* (subpath (param \"USER_HOME_DIR\")))";
202
203  const char* home_dir = [NSHomeDirectory() UTF8String];
204  // Parameters are passed as an array containing key,value,NULL.
205  const char* parameters[] = { "USER_HOME_DIR", home_dir, NULL };
206
207  if (sandbox_init_with_parameters(profile, 0, parameters, NULL))
208    exit(1);
209
210  const char* vim_rc =
211      [[NSHomeDirectory() stringByAppendingString:@"/.vimrc"]
212          UTF8String];
213
214  struct stat sb;
215  if (stat(vim_rc, &sb) == 0)
216    printf(".vimrc file exists\n");
217
218  return 0;
219}
220```
221
222The following information must be collected as parameters for the
223sandbox profiles to function:
224
225*   Whether or not the sandbox should log failures
226*   The user's home directory
227*   Information about the specific OS version (10.9, 10.10, etc.)
228*   The path to the main `Google Chromium.app` bundle
229*   The PID of the Chromium process
230*   If applicable, the path to the permitted directory that the process can read and write to.
231
232The sandbox directives most commonly used in Chromium's V2 profiles
233are documented here for future reference.
234
235```(deny default)``` - All resource access is denied by default. The
236sandbox must list allow rules for all resources.
237
238```(path "/path")``` - Match exactly this path.
239
240```(subpath "/path")``` - Match this path and all subpaths of this
241path. ("/path", "/path/foo", etc.)
242
243```(allow process-exec*)``` - Allows the specified binary to be
244executed as a process.
245
246```(allow mach-lookup (global-name "com.apple.system.logger"))``` -
247Allows the process to communicate with the specified system service.
248
249```(allow sysctl-read)``` - Allow access to sysctl() to read property
250values.
251