Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: content/common/sandbox_linux.cc

Issue 13814027: Linux: make current InitializeSandbox() private. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include <fcntl.h> 5 #include <fcntl.h>
6 #include <sys/resource.h> 6 #include <sys/resource.h>
7 #include <sys/stat.h> 7 #include <sys/stat.h>
8 #include <sys/time.h> 8 #include <sys/time.h>
9 #include <sys/types.h> 9 #include <sys/types.h>
10 10
11 #include <limits> 11 #include <limits>
12 12
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/file_util.h" 14 #include "base/file_util.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/singleton.h" 16 #include "base/memory/singleton.h"
17 #include "base/posix/eintr_wrapper.h" 17 #include "base/posix/eintr_wrapper.h"
18 #include "base/time.h" 18 #include "base/time.h"
19 #include "content/common/sandbox_linux.h" 19 #include "content/common/sandbox_linux.h"
20 #include "content/common/seccomp_sandbox.h" 20 #include "content/common/seccomp_sandbox.h"
21 #include "content/common/sandbox_seccomp_bpf_linux.h" 21 #include "content/common/sandbox_seccomp_bpf_linux.h"
22 #include "content/public/common/content_switches.h" 22 #include "content/public/common/content_switches.h"
23 #include "content/public/common/sandbox_linux.h" 23 #include "content/public/common/sandbox_linux.h"
24 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" 24 #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
25 25
26 using content::LinuxSandbox;
27
26 namespace { 28 namespace {
27 29
28 void LogSandboxStarted(const std::string& sandbox_name) { 30 void LogSandboxStarted(const std::string& sandbox_name) {
29 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 31 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
30 const std::string process_type = 32 const std::string process_type =
31 command_line.GetSwitchValueASCII(switches::kProcessType); 33 command_line.GetSwitchValueASCII(switches::kProcessType);
32 const std::string activated_sandbox = 34 const std::string activated_sandbox =
33 "Activated " + sandbox_name + " sandbox for process type: " + 35 "Activated " + sandbox_name + " sandbox for process type: " +
34 process_type + "."; 36 process_type + ".";
35 #if defined(OS_CHROMEOS) 37 #if defined(OS_CHROMEOS)
(...skipping 16 matching lines...) Expand all
52 #else 54 #else
53 // On by default. Allow turning off with a switch. 55 // On by default. Allow turning off with a switch.
54 return !command_line->HasSwitch(switches::kDisableSeccompSandbox); 56 return !command_line->HasSwitch(switches::kDisableSeccompSandbox);
55 #endif // NDEBUG 57 #endif // NDEBUG
56 #endif // SECCOMP_SANDBOX 58 #endif // SECCOMP_SANDBOX
57 return false; 59 return false;
58 } 60 }
59 61
60 // Our "policy" on whether or not to enable seccomp-legacy. Only renderers are 62 // Our "policy" on whether or not to enable seccomp-legacy. Only renderers are
61 // supported. 63 // supported.
62 bool ShouldEnableSeccompLegacy(const std::string& process_type) { 64 bool ShouldEnableSeccompLegacy(LinuxSandbox::SandboxConfig sandbox_config) {
63 if (IsSeccompLegacyDesired() && 65 if (IsSeccompLegacyDesired() &&
64 process_type == switches::kRendererProcess) { 66 sandbox_config == LinuxSandbox::SANDBOX_CONFIG_RENDERER) {
65 return true; 67 return true;
66 } else { 68 } else {
67 return false; 69 return false;
68 } 70 }
69 } 71 }
70 72
71 bool AddResourceLimit(int resource, rlim_t limit) { 73 bool AddResourceLimit(int resource, rlim_t limit) {
72 struct rlimit old_rlimit; 74 struct rlimit old_rlimit;
73 if (getrlimit(resource, &old_rlimit)) 75 if (getrlimit(resource, &old_rlimit))
74 return false; 76 return false;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 } else { 151 } else {
150 seccomp_bpf_supported_ = true; 152 seccomp_bpf_supported_ = true;
151 } 153 }
152 } 154 }
153 pre_initialized_ = true; 155 pre_initialized_ = true;
154 } 156 }
155 157
156 // Once we finally know our process type, we can cleanup proc_fd_ 158 // Once we finally know our process type, we can cleanup proc_fd_
157 // or pass it to seccomp-legacy. 159 // or pass it to seccomp-legacy.
158 void LinuxSandbox::PreinitializeSandboxFinish( 160 void LinuxSandbox::PreinitializeSandboxFinish(
159 const std::string& process_type) { 161 LinuxSandbox::SandboxConfig sandbox_config) {
160 CHECK(pre_initialized_); 162 CHECK(pre_initialized_);
161 if (proc_fd_ >= 0) { 163 if (proc_fd_ >= 0) {
162 if (ShouldEnableSeccompLegacy(process_type)) { 164 if (ShouldEnableSeccompLegacy(sandbox_config)) {
163 #if defined(SECCOMP_SANDBOX) 165 #if defined(SECCOMP_SANDBOX)
164 SeccompSandboxSetProcFd(proc_fd_); 166 SeccompSandboxSetProcFd(proc_fd_);
165 #endif 167 #endif
166 } else { 168 } else {
167 DCHECK_GE(proc_fd_, 0); 169 DCHECK_GE(proc_fd_, 0);
168 CHECK_EQ(HANDLE_EINTR(close(proc_fd_)), 0); 170 CHECK_EQ(HANDLE_EINTR(close(proc_fd_)), 0);
169 } 171 }
170 proc_fd_ = -1; 172 proc_fd_ = -1;
171 } 173 }
172 } 174 }
173 175
174 void LinuxSandbox::PreinitializeSandbox(const std::string& process_type) { 176 void LinuxSandbox::PreinitializeSandbox(
177 LinuxSandbox::SandboxConfig sandbox_config) {
175 PreinitializeSandboxBegin(); 178 PreinitializeSandboxBegin();
176 PreinitializeSandboxFinish(process_type); 179 PreinitializeSandboxFinish(sandbox_config);
180 }
181
182 bool LinuxSandbox::InitializeSandbox(
183 enum LinuxSandbox::SandboxConfig sandbox_config) {
184 bool seccomp_legacy_started = false;
185 bool seccomp_bpf_started = false;
186 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
187 const std::string process_type =
188 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
189 switches::kProcessType);
190
191 // No matter what, it's always an error to call InitializeSandbox() after
192 // threads have been created.
193 if (!linux_sandbox->IsSingleThreaded()) {
194 std::string error_message = "InitializeSandbox() called with multiple "
195 "threads in process " + process_type;
196 // TODO(jln): change this into a CHECK() once we are more comfortable it
197 // does not trigger.
198 LOG(ERROR) << error_message;
199 return false;
200 }
201
202 // Attempt to limit the future size of the address space of the process.
203 linux_sandbox->LimitAddressSpace(sandbox_config);
204
205 // First, try to enable seccomp-bpf.
206 seccomp_bpf_started = linux_sandbox->StartSeccompBpf(sandbox_config);
207
208 // If that fails, try to enable seccomp-legacy.
209 if (!seccomp_bpf_started) {
210 seccomp_legacy_started = linux_sandbox->StartSeccompLegacy(sandbox_config);
211 }
212
213 return seccomp_legacy_started || seccomp_bpf_started;
177 } 214 }
178 215
179 int LinuxSandbox::GetStatus() const { 216 int LinuxSandbox::GetStatus() const {
180 CHECK(pre_initialized_); 217 CHECK(pre_initialized_);
181 int sandbox_flags = 0; 218 int sandbox_flags = 0;
182 if (setuid_sandbox_client_->IsSandboxed()) { 219 if (setuid_sandbox_client_->IsSandboxed()) {
183 sandbox_flags |= kSandboxLinuxSUID; 220 sandbox_flags |= kSandboxLinuxSUID;
184 if (setuid_sandbox_client_->IsInNewPIDNamespace()) 221 if (setuid_sandbox_client_->IsInNewPIDNamespace())
185 sandbox_flags |= kSandboxLinuxPIDNS; 222 sandbox_flags |= kSandboxLinuxPIDNS;
186 if (setuid_sandbox_client_->IsInNewNETNamespace()) 223 if (setuid_sandbox_client_->IsInNewNETNamespace())
187 sandbox_flags |= kSandboxLinuxNetNS; 224 sandbox_flags |= kSandboxLinuxNetNS;
188 } 225 }
189 226
190 if (seccomp_bpf_supported() && 227 if (seccomp_bpf_supported() && SandboxSeccompBpf::ShouldEnableSeccompBpf(
191 SandboxSeccompBpf::ShouldEnableSeccompBpf(switches::kRendererProcess)) { 228 LinuxSandbox::SANDBOX_CONFIG_RENDERER)) {
192 // We report whether the sandbox will be activated when renderers go 229 // We report whether the sandbox will be activated when renderers go
193 // through sandbox initialization. 230 // through sandbox initialization.
194 sandbox_flags |= kSandboxLinuxSeccompBpf; 231 sandbox_flags |= kSandboxLinuxSeccompBpf;
195 } 232 }
196 233
197 // We only try to enable seccomp-legacy when seccomp-bpf is not supported 234 // We only try to enable seccomp-legacy when seccomp-bpf is not supported
198 // or not enabled. 235 // or not enabled.
199 if (!(sandbox_flags & kSandboxLinuxSeccompBpf) && 236 if (!(sandbox_flags & kSandboxLinuxSeccompBpf) &&
200 seccomp_legacy_supported() && 237 seccomp_legacy_supported() &&
201 ShouldEnableSeccompLegacy(switches::kRendererProcess)) { 238 ShouldEnableSeccompLegacy(LinuxSandbox::SANDBOX_CONFIG_RENDERER)) {
202 // Same here, what we report is what we will do for the renderer. 239 // Same here, what we report is what we will do for the renderer.
203 sandbox_flags |= kSandboxLinuxSeccompLegacy; 240 sandbox_flags |= kSandboxLinuxSeccompLegacy;
204 } 241 }
205 return sandbox_flags; 242 return sandbox_flags;
206 } 243 }
207 244
208 bool LinuxSandbox::IsSingleThreaded() const { 245 bool LinuxSandbox::IsSingleThreaded() const {
209 // TODO(jln): re-implement this properly and use our proc_fd_ if available. 246 // TODO(jln): re-implement this properly and use our proc_fd_ if available.
210 // Possibly racy, but it's ok because this is more of a debug check to catch 247 // Possibly racy, but it's ok because this is more of a debug check to catch
211 // new threaded situations arising during development. 248 // new threaded situations arising during development.
(...skipping 15 matching lines...) Expand all
227 bool LinuxSandbox::seccomp_bpf_started() const { 264 bool LinuxSandbox::seccomp_bpf_started() const {
228 return seccomp_bpf_started_; 265 return seccomp_bpf_started_;
229 } 266 }
230 267
231 sandbox::SetuidSandboxClient* 268 sandbox::SetuidSandboxClient*
232 LinuxSandbox::setuid_sandbox_client() const { 269 LinuxSandbox::setuid_sandbox_client() const {
233 return setuid_sandbox_client_.get(); 270 return setuid_sandbox_client_.get();
234 } 271 }
235 272
236 // For seccomp-legacy, we implement the policy inline, here. 273 // For seccomp-legacy, we implement the policy inline, here.
237 bool LinuxSandbox::StartSeccompLegacy(const std::string& process_type) { 274 bool LinuxSandbox::StartSeccompLegacy(
275 LinuxSandbox::SandboxConfig sandbox_config) {
238 if (!pre_initialized_) 276 if (!pre_initialized_)
239 PreinitializeSandbox(process_type); 277 PreinitializeSandbox(sandbox_config);
240 if (seccomp_legacy_supported() && ShouldEnableSeccompLegacy(process_type)) { 278 if (seccomp_legacy_supported() && ShouldEnableSeccompLegacy(sandbox_config)) {
241 // SupportsSeccompSandbox() returns a cached result, as we already 279 // SupportsSeccompSandbox() returns a cached result, as we already
242 // called it earlier in the PreinitializeSandbox(). Thus, it is OK for us 280 // called it earlier in the PreinitializeSandbox(). Thus, it is OK for us
243 // to not pass in a file descriptor for "/proc". 281 // to not pass in a file descriptor for "/proc".
244 #if defined(SECCOMP_SANDBOX) 282 #if defined(SECCOMP_SANDBOX)
245 if (SupportsSeccompSandbox(-1)) { 283 if (SupportsSeccompSandbox(-1)) {
246 StartSeccompSandbox(); 284 StartSeccompSandbox();
247 LogSandboxStarted("seccomp-legacy"); 285 LogSandboxStarted("seccomp-legacy");
248 return true; 286 return true;
249 } 287 }
250 #endif 288 #endif
251 } 289 }
252 return false; 290 return false;
253 } 291 }
254 292
255 // For seccomp-bpf, we use the SandboxSeccompBpf class. 293 // For seccomp-bpf, we use the SandboxSeccompBpf class.
256 bool LinuxSandbox::StartSeccompBpf(const std::string& process_type) { 294 bool LinuxSandbox::StartSeccompBpf(
295 LinuxSandbox::SandboxConfig sandbox_config) {
257 CHECK(!seccomp_bpf_started_); 296 CHECK(!seccomp_bpf_started_);
258 if (!pre_initialized_) 297 if (!pre_initialized_)
259 PreinitializeSandbox(process_type); 298 PreinitializeSandbox(sandbox_config);
260 if (seccomp_bpf_supported()) 299 if (seccomp_bpf_supported())
261 seccomp_bpf_started_ = SandboxSeccompBpf::StartSandbox(process_type); 300 seccomp_bpf_started_ = SandboxSeccompBpf::StartSandbox(sandbox_config);
262 301
263 if (seccomp_bpf_started_) 302 if (seccomp_bpf_started_)
264 LogSandboxStarted("seccomp-bpf"); 303 LogSandboxStarted("seccomp-bpf");
265 304
266 return seccomp_bpf_started_; 305 return seccomp_bpf_started_;
267 } 306 }
268 307
269 bool LinuxSandbox::seccomp_legacy_supported() const { 308 bool LinuxSandbox::seccomp_legacy_supported() const {
270 CHECK(pre_initialized_); 309 CHECK(pre_initialized_);
271 return seccomp_legacy_supported_; 310 return seccomp_legacy_supported_;
272 } 311 }
273 312
274 bool LinuxSandbox::seccomp_bpf_supported() const { 313 bool LinuxSandbox::seccomp_bpf_supported() const {
275 CHECK(pre_initialized_); 314 CHECK(pre_initialized_);
276 return seccomp_bpf_supported_; 315 return seccomp_bpf_supported_;
277 } 316 }
278 317
279 bool LinuxSandbox::LimitAddressSpace(const std::string& process_type) { 318 bool LinuxSandbox::LimitAddressSpace(
280 (void) process_type; 319 LinuxSandbox::SandboxConfig sandbox_config) {
320 (void) sandbox_config;
281 #if !defined(ADDRESS_SANITIZER) 321 #if !defined(ADDRESS_SANITIZER)
282 CommandLine* command_line = CommandLine::ForCurrentProcess(); 322 CommandLine* command_line = CommandLine::ForCurrentProcess();
283 if (command_line->HasSwitch(switches::kNoSandbox)) { 323 if (command_line->HasSwitch(switches::kNoSandbox)) {
284 return false; 324 return false;
285 } 325 }
286 326
287 // Limit the address space to 4GB. 327 // Limit the address space to 4GB.
288 // This is in the hope of making some kernel exploits more complex and less 328 // This is in the hope of making some kernel exploits more complex and less
289 // reliable. It also limits sprays a little on 64-bit. 329 // reliable. It also limits sprays a little on 64-bit.
290 rlim_t address_space_limit = std::numeric_limits<uint32_t>::max(); 330 rlim_t address_space_limit = std::numeric_limits<uint32_t>::max();
291 #if defined(__LP64__) 331 #if defined(__LP64__)
292 // On 64 bits, V8 and possibly others will reserve massive memory ranges and 332 // On 64 bits, V8 and possibly others will reserve massive memory ranges and
293 // rely on on-demand paging for allocation. Unfortunately, even 333 // rely on on-demand paging for allocation. Unfortunately, even
294 // MADV_DONTNEED ranges count towards RLIMIT_AS so this is not an option. 334 // MADV_DONTNEED ranges count towards RLIMIT_AS so this is not an option.
295 // See crbug.com/169327 for a discussion. 335 // See crbug.com/169327 for a discussion.
296 // For now, increase limit to 16GB for renderer and worker processes to 336 // For now, increase limit to 16GB for renderer and worker processes to
297 // accomodate. 337 // accomodate.
298 if (process_type == switches::kRendererProcess || 338 if (sandbox_config == LinuxSandbox::SANDBOX_CONFIG_RENDERER ||
299 process_type == switches::kWorkerProcess) { 339 sandbox_config == LinuxSandbox::SANDBOX_CONFIG_WORKER) {
300 address_space_limit = 1L << 34; 340 address_space_limit = 1L << 34;
301 } 341 }
302 #endif // defined(__LP64__) 342 #endif // defined(__LP64__)
303 343
304 // On all platforms, add a limit to the brk() heap that would prevent 344 // On all platforms, add a limit to the brk() heap that would prevent
305 // allocations that can't be index by an int. 345 // allocations that can't be index by an int.
306 const rlim_t kNewDataSegmentMaxSize = std::numeric_limits<int>::max(); 346 const rlim_t kNewDataSegmentMaxSize = std::numeric_limits<int>::max();
307 347
308 bool limited_as = AddResourceLimit(RLIMIT_AS, address_space_limit); 348 bool limited_as = AddResourceLimit(RLIMIT_AS, address_space_limit);
309 bool limited_data = AddResourceLimit(RLIMIT_DATA, kNewDataSegmentMaxSize); 349 bool limited_data = AddResourceLimit(RLIMIT_DATA, kNewDataSegmentMaxSize);
310 return limited_as && limited_data; 350 return limited_as && limited_data;
311 #else 351 #else
312 return false; 352 return false;
313 #endif // !defined(ADDRESS_SANITIZER) 353 #endif // !defined(ADDRESS_SANITIZER)
314 } 354 }
315 355
316 } // namespace content 356 } // namespace content
317 357
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698