1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
// Copyright (c) 2009 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 "chrome/common/sandbox_mac.h"
#include "base/debug_util.h"
#import <Cocoa/Cocoa.h>
extern "C" {
#include <sandbox.h>
}
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/json/string_escape.h"
#include "base/mac_util.h"
#include "base/scoped_cftyperef.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/string16.h"
#include "base/sys_info.h"
#include "base/sys_string_conversions.h"
#include "chrome/common/chrome_switches.h"
namespace sandbox {
// Warm up System APIs that empirically need to be accessed before the Sandbox
// is turned on.
// This method is layed out in blocks, each one containing a separate function
// that needs to be warmed up. The OS version on which we found the need to
// enable the function is also noted.
// This function is tested on the following OS versions:
// 10.5.6, 10.6.0
void SandboxWarmup() {
base::ScopedNSAutoreleasePool scoped_pool;
{ // CGColorSpaceCreateWithName(), CGBitmapContextCreate() - 10.5.6
scoped_cftyperef<CGColorSpaceRef> rgb_colorspace(
CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB));
// Allocate a 1x1 image.
char data[4];
scoped_cftyperef<CGContextRef> context(
CGBitmapContextCreate(data, 1, 1, 8, 1 * 4,
rgb_colorspace,
kCGImageAlphaPremultipliedFirst |
kCGBitmapByteOrder32Host));
// Load in the color profiles we'll need (as a side effect).
(void) mac_util::GetSRGBColorSpace();
(void) mac_util::GetSystemColorSpace();
// CGColorSpaceCreateSystemDefaultCMYK - 10.6
scoped_cftyperef<CGColorSpaceRef> cmyk_colorspace(
CGColorSpaceCreateWithName(kCGColorSpaceGenericCMYK));
}
{ // [-NSColor colorUsingColorSpaceName] - 10.5.6
NSColor* color = [NSColor controlTextColor];
[color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
}
{ // localtime() - 10.5.6
time_t tv = {0};
localtime(&tv);
}
{ // Gestalt() tries to read /System/Library/CoreServices/SystemVersion.plist
// on 10.5.6
int32 tmp;
base::SysInfo::OperatingSystemVersionNumbers(&tmp, &tmp, &tmp);
}
{ // CGImageSourceGetStatus() - 10.6
// Create a png with just enough data to get everything warmed up...
char png_header[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
NSData* data = [NSData dataWithBytes:png_header
length:arraysize(png_header)];
scoped_cftyperef<CGImageSourceRef> img(
CGImageSourceCreateWithData((CFDataRef)data,
NULL));
CGImageSourceGetStatus(img);
}
}
// Turns on the OS X sandbox for this process.
bool EnableSandbox(SandboxProcessType sandbox_type,
const FilePath& allowed_dir) {
// Sanity - currently only SANDBOX_TYPE_UTILITY supports a directory being
// passed in.
if (sandbox_type != SANDBOX_TYPE_UTILITY) {
DCHECK(allowed_dir.empty())
<< "Only SANDBOX_TYPE_UTILITY allows a custom directory parameter.";
} else {
DCHECK(!allowed_dir.empty())
<< "SANDBOX_TYPE_UTILITY "
<< "needs a custom directory parameter, but an empty one was provided.";
}
// We use a custom sandbox definition file to lock things down as
// tightly as possible.
// TODO(jeremy): Look at using include syntax to unify common parts of sandbox
// definition files.
NSString* sandbox_config_filename = nil;
switch (sandbox_type) {
case SANDBOX_TYPE_RENDERER:
sandbox_config_filename = @"renderer";
break;
case SANDBOX_TYPE_WORKER:
sandbox_config_filename = @"worker";
break;
case SANDBOX_TYPE_UTILITY:
sandbox_config_filename = @"utility";
break;
default:
NOTREACHED();
return false;
}
NSString* sandbox_profile_path =
[mac_util::MainAppBundle() pathForResource:sandbox_config_filename
ofType:@"sb"];
NSString* sandbox_data = [NSString
stringWithContentsOfFile:sandbox_profile_path
encoding:NSUTF8StringEncoding
error:nil];
if (!sandbox_data) {
LOG(ERROR) << "Failed to find the sandbox profile on disk";
return false;
}
// Enable verbose logging if enabled on the command line.
// (see renderer.sb for details).
const CommandLine *command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnableSandboxLogging)) {
sandbox_data = [sandbox_data
stringByReplacingOccurrencesOfString:@";ENABLE_LOGGING"
withString:@""];
}
if (!allowed_dir.empty()) {
NSString* allowed_dir_ns = base::SysUTF8ToNSString(allowed_dir.value());
sandbox_data = [sandbox_data
stringByReplacingOccurrencesOfString:@"DIR_TO_ALLOW_ACCESS"
withString:allowed_dir_ns];
}
int32 major_version, minor_version, bugfix_version;
base::SysInfo::OperatingSystemVersionNumbers(&major_version,
&minor_version, &bugfix_version);
if (major_version > 10 || (major_version == 10 && minor_version >= 6)) {
// 10.6-only Sandbox rules.
sandbox_data = [sandbox_data
stringByReplacingOccurrencesOfString:@";10.6_ONLY"
withString:@""];
// Splice the path of the user's home directory into the sandbox profile
// (see renderer.sb for details).
// This code is in the 10.6-only block because the sandbox syntax we use
// for this "subdir" is only supported on 10.6.
// If we ever need this on pre-10.6 OSs then we'll have to rethink the
// surrounding sandbox syntax.
string16 home_dir = base::SysNSStringToUTF16(NSHomeDirectory());
std::string home_dir_escaped;
base::JsonDoubleQuote(home_dir, false, &home_dir_escaped);
NSString* home_dir_escaped_ns = base::SysUTF8ToNSString(home_dir_escaped);
sandbox_data = [sandbox_data
stringByReplacingOccurrencesOfString:@"USER_HOMEDIR"
withString:home_dir_escaped_ns];
}
char* error_buff = NULL;
int error = sandbox_init([sandbox_data UTF8String], 0, &error_buff);
bool success = (error == 0 && error_buff == NULL);
if (error == -1) {
LOG(ERROR) << "Failed to Initialize Sandbox: " << error_buff;
}
sandbox_free_error(error_buff);
return success;
}
} // namespace sandbox
|