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

Side by Side Diff: components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc

Issue 250773003: NaCl Linux: create NaClSandbox class (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address nits. Created 6 years, 7 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/nacl/loader/sandbox_linux/nacl_sandbox_linux.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12
13 #include "base/basictypes.h"
14 #include "base/callback.h"
15 #include "base/command_line.h"
16 #include "base/compiler_specific.h"
17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/posix/eintr_wrapper.h"
20 #include "build/build_config.h"
21 #include "components/nacl/common/nacl_switches.h"
22 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h"
23 #include "components/nacl/loader/sandbox_linux/nacl_bpf_sandbox_linux.h"
24 #include "sandbox/linux/services/credentials.h"
25 #include "sandbox/linux/services/thread_helpers.h"
26 #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
27
28 namespace nacl {
29
30 namespace {
31
32 // This is a poor man's check on whether we are sandboxed.
33 bool IsSandboxed() {
34 int proc_fd = open("/proc/self/exe", O_RDONLY);
35 if (proc_fd >= 0) {
36 PCHECK(0 == IGNORE_EINTR(close(proc_fd)));
37 return false;
38 }
39 return true;
40 }
41
42 } // namespace
43
44 NaClSandbox::NaClSandbox()
45 : layer_one_enabled_(false),
46 layer_one_sealed_(false),
47 layer_two_enabled_(false),
48 layer_two_is_nonsfi_(false),
49 proc_fd_(-1) {
50 proc_fd_.reset(
51 HANDLE_EINTR(open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC)));
52 PCHECK(proc_fd_.is_valid());
53 }
54
55 NaClSandbox::~NaClSandbox() {
56 }
57
58 bool NaClSandbox::IsSingleThreaded() {
59 CHECK(proc_fd_.is_valid());
60 base::ScopedFD proc_self_task(HANDLE_EINTR(openat(
61 proc_fd_.get(), "self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC)));
62 PCHECK(proc_self_task.is_valid());
63 return sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get());
64 }
65
66 bool NaClSandbox::HasOpenDirectory() {
67 CHECK(proc_fd_.is_valid());
68 sandbox::Credentials credentials;
69 return credentials.HasOpenDirectory(proc_fd_.get());
70 }
71
72 void NaClSandbox::InitializeLayerOneSandbox() {
73 // Check that IsSandboxed() works. We should not be sandboxed at this point.
74 CHECK(!IsSandboxed()) << "Unexpectedly sandboxed!";
75 scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client(
76 sandbox::SetuidSandboxClient::Create());
77 // Close the file descriptor that is an artefact of how the setuid sandbox
78 // works.
79 PCHECK(0 == IGNORE_EINTR(close(
80 setuid_sandbox_client->GetUniqueToChildFileDescriptor())));
81 const bool suid_sandbox_child = setuid_sandbox_client->IsSuidSandboxChild();
82
83 if (suid_sandbox_child) {
84 // Make sure that no directory file descriptor is open, as it would bypass
85 // the setuid sandbox model.
86 CHECK(!HasOpenDirectory());
87
88 // Get sandboxed.
89 CHECK(setuid_sandbox_client->ChrootMe());
90 CHECK(IsSandboxed());
91 layer_one_enabled_ = true;
92 }
93 }
94
95 void NaClSandbox::InitializeLayerTwoSandbox(bool uses_nonsfi_mode) {
96 // seccomp-bpf only applies to the current thread, so it's critical to only
97 // have a single thread running here.
98 DCHECK(!layer_one_sealed_);
99 CHECK(IsSingleThreaded());
100 if (uses_nonsfi_mode) {
101 layer_two_enabled_ = nacl::nonsfi::InitializeBPFSandbox();
102 layer_two_is_nonsfi_ = true;
103 } else {
104 layer_two_enabled_ = nacl::InitializeBPFSandbox();
105 }
106 }
107
108 void NaClSandbox::SealLayerOneSandbox() {
109 if (!layer_two_enabled_) {
110 // If nothing prevents us, check that there is no superfluous directory
111 // open.
112 CHECK(!HasOpenDirectory());
113 }
114 proc_fd_.reset();
115 layer_one_sealed_ = true;
116 }
117
118 void NaClSandbox::CheckSandboxingStateWithPolicy() {
119 static const char kItIsDangerousMsg[] = " this is dangerous.";
120 static const char kItIsNotAllowedMsg[] =
121 " this is not allowed in this configuration.";
122
123 const bool no_sandbox_for_nonsfi_ok =
124 CommandLine::ForCurrentProcess()->HasSwitch(
125 switches::kNaClDangerousNoSandboxNonSfi);
126 const bool can_be_no_sandbox =
127 !layer_two_is_nonsfi_ || no_sandbox_for_nonsfi_ok;
128
129 if (!layer_one_enabled_ || !layer_one_sealed_) {
130 static const char kNoSuidMsg[] =
131 "The SUID sandbox is not engaged for NaCl:";
132 if (can_be_no_sandbox)
133 LOG(ERROR) << kNoSuidMsg << kItIsDangerousMsg;
134 else
135 LOG(FATAL) << kNoSuidMsg << kItIsNotAllowedMsg;
136 }
137
138 if (!layer_two_enabled_) {
139 static const char kNoBpfMsg[] =
140 "The seccomp-bpf sandbox is not engaged for NaCl:";
141 if (can_be_no_sandbox)
142 LOG(ERROR) << kNoBpfMsg << kItIsDangerousMsg;
143 else
144 LOG(FATAL) << kNoBpfMsg << kItIsNotAllowedMsg;
145 }
146 }
147
148 } // namespace nacl
OLDNEW
« no previous file with comments | « components/nacl/loader/sandbox_linux/nacl_sandbox_linux.h ('k') | sandbox/linux/services/credentials.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698