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

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

Issue 938223004: Linux sandbox: better APIs with /proc/ arguments (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix invalid proc_fd_ usage. Created 5 years, 10 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
OLDNEW
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 #include "components/nacl/loader/sandbox_linux/nacl_sandbox_linux.h" 5 #include "components/nacl/loader/sandbox_linux/nacl_sandbox_linux.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <sys/prctl.h> 9 #include <sys/prctl.h>
10 #include <sys/stat.h> 10 #include <sys/stat.h>
(...skipping 30 matching lines...) Expand all
41 // This is a poor man's check on whether we are sandboxed. 41 // This is a poor man's check on whether we are sandboxed.
42 bool IsSandboxed() { 42 bool IsSandboxed() {
43 int proc_fd = open("/proc/self/exe", O_RDONLY); 43 int proc_fd = open("/proc/self/exe", O_RDONLY);
44 if (proc_fd >= 0) { 44 if (proc_fd >= 0) {
45 PCHECK(0 == IGNORE_EINTR(close(proc_fd))); 45 PCHECK(0 == IGNORE_EINTR(close(proc_fd)));
46 return false; 46 return false;
47 } 47 }
48 return true; 48 return true;
49 } 49 }
50 50
51 // Open a new file descriptor to /proc/self/task/ by using
52 // |proc_fd|.
53 base::ScopedFD GetProcSelfTask(int proc_fd) {
54 base::ScopedFD proc_self_task(HANDLE_EINTR(
55 openat(proc_fd, "self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC)));
56 PCHECK(proc_self_task.is_valid());
57 return proc_self_task.Pass();
58 }
59
60 bool MaybeSetProcessNonDumpable() { 51 bool MaybeSetProcessNonDumpable() {
61 const base::CommandLine& command_line = 52 const base::CommandLine& command_line =
62 *base::CommandLine::ForCurrentProcess(); 53 *base::CommandLine::ForCurrentProcess();
63 if (command_line.HasSwitch(switches::kAllowSandboxDebugging)) { 54 if (command_line.HasSwitch(switches::kAllowSandboxDebugging)) {
64 return true; 55 return true;
65 } 56 }
66 57
67 if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) != 0) { 58 if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) != 0) {
68 PLOG(ERROR) << "Failed to set non-dumpable flag"; 59 PLOG(ERROR) << "Failed to set non-dumpable flag";
69 return false; 60 return false;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 proc_fd_.reset( 106 proc_fd_.reset(
116 HANDLE_EINTR(open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC))); 107 HANDLE_EINTR(open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC)));
117 PCHECK(proc_fd_.is_valid()); 108 PCHECK(proc_fd_.is_valid());
118 } 109 }
119 110
120 NaClSandbox::~NaClSandbox() { 111 NaClSandbox::~NaClSandbox() {
121 } 112 }
122 113
123 bool NaClSandbox::IsSingleThreaded() { 114 bool NaClSandbox::IsSingleThreaded() {
124 CHECK(proc_fd_.is_valid()); 115 CHECK(proc_fd_.is_valid());
125 base::ScopedFD proc_self_task(GetProcSelfTask(proc_fd_.get())); 116 return sandbox::ThreadHelpers::IsSingleThreaded(proc_fd_.get());
126 return sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get());
127 } 117 }
128 118
129 bool NaClSandbox::HasOpenDirectory() { 119 bool NaClSandbox::HasOpenDirectory() {
130 CHECK(proc_fd_.is_valid()); 120 CHECK(proc_fd_.is_valid());
131 return sandbox::ProcUtil::HasOpenDirectory(proc_fd_.get()); 121 return sandbox::ProcUtil::HasOpenDirectory(proc_fd_.get());
132 } 122 }
133 123
134 void NaClSandbox::InitializeLayerOneSandbox() { 124 void NaClSandbox::InitializeLayerOneSandbox() {
135 // Check that IsSandboxed() works. We should not be sandboxed at this point. 125 // Check that IsSandboxed() works. We should not be sandboxed at this point.
136 CHECK(!IsSandboxed()) << "Unexpectedly sandboxed!"; 126 CHECK(!IsSandboxed()) << "Unexpectedly sandboxed!";
137 127
138 if (setuid_sandbox_client_->IsSuidSandboxChild()) { 128 if (setuid_sandbox_client_->IsSuidSandboxChild()) {
139 setuid_sandbox_client_->CloseDummyFile(); 129 setuid_sandbox_client_->CloseDummyFile();
140 130
141 // Make sure that no directory file descriptor is open, as it would bypass 131 // Make sure that no directory file descriptor is open, as it would bypass
142 // the setuid sandbox model. 132 // the setuid sandbox model.
143 CHECK(!HasOpenDirectory()); 133 CHECK(!HasOpenDirectory());
144 134
145 // Get sandboxed. 135 // Get sandboxed.
146 CHECK(setuid_sandbox_client_->ChrootMe()); 136 CHECK(setuid_sandbox_client_->ChrootMe());
147 CHECK(MaybeSetProcessNonDumpable()); 137 CHECK(MaybeSetProcessNonDumpable());
148 CHECK(IsSandboxed()); 138 CHECK(IsSandboxed());
149 layer_one_enabled_ = true; 139 layer_one_enabled_ = true;
150 } else if (sandbox::NamespaceSandbox::InNewUserNamespace()) { 140 } else if (sandbox::NamespaceSandbox::InNewUserNamespace()) {
151 CHECK(sandbox::Credentials::MoveToNewUserNS()); 141 CHECK(sandbox::Credentials::MoveToNewUserNS());
152 // This relies on SealLayerOneSandbox() to be called later. 142 // This relies on SealLayerOneSandbox() to be called later since this
153 CHECK(!HasOpenDirectory()); 143 // class is keeping a file descriptor to /proc/.
154 CHECK(sandbox::Credentials::DropFileSystemAccess()); 144 CHECK(sandbox::Credentials::DropFileSystemAccess(proc_fd_.get()));
155 CHECK(IsSingleThreaded()); 145 CHECK(sandbox::Credentials::DropAllCapabilities(proc_fd_.get()));
156 CHECK(sandbox::Credentials::DropAllCapabilities());
157 CHECK(IsSandboxed()); 146 CHECK(IsSandboxed());
158 layer_one_enabled_ = true; 147 layer_one_enabled_ = true;
159 } 148 }
160 } 149 }
161 150
162 void NaClSandbox::CheckForExpectedNumberOfOpenFds() { 151 void NaClSandbox::CheckForExpectedNumberOfOpenFds() {
163 // We expect to have the following FDs open: 152 // We expect to have the following FDs open:
164 // 1-3) stdin, stdout, stderr. 153 // 1-3) stdin, stdout, stderr.
165 // 4) The /dev/urandom FD used by base::GetUrandomFD(). 154 // 4) The /dev/urandom FD used by base::GetUrandomFD().
166 // 5) A dummy pipe FD used to overwrite kSandboxIPCChannel. 155 // 5) A dummy pipe FD used to overwrite kSandboxIPCChannel.
(...skipping 15 matching lines...) Expand all
182 171
183 void NaClSandbox::InitializeLayerTwoSandbox(bool uses_nonsfi_mode) { 172 void NaClSandbox::InitializeLayerTwoSandbox(bool uses_nonsfi_mode) {
184 // seccomp-bpf only applies to the current thread, so it's critical to only 173 // seccomp-bpf only applies to the current thread, so it's critical to only
185 // have a single thread running here. 174 // have a single thread running here.
186 DCHECK(!layer_one_sealed_); 175 DCHECK(!layer_one_sealed_);
187 CHECK(IsSingleThreaded()); 176 CHECK(IsSingleThreaded());
188 CheckForExpectedNumberOfOpenFds(); 177 CheckForExpectedNumberOfOpenFds();
189 178
190 RestrictAddressSpaceUsage(); 179 RestrictAddressSpaceUsage();
191 180
192 base::ScopedFD proc_self_task(GetProcSelfTask(proc_fd_.get())); 181 // Pass proc_fd_ ownership to the BPF sandbox, which guarantees it will
193 182 // be closed. There is no point in keeping it around since the BPF policy
183 // will prevent its usage.
194 if (uses_nonsfi_mode) { 184 if (uses_nonsfi_mode) {
195 layer_two_enabled_ = 185 layer_two_enabled_ = nacl::nonsfi::InitializeBPFSandbox(proc_fd_.Pass());
196 nacl::nonsfi::InitializeBPFSandbox(proc_self_task.Pass());
197 layer_two_is_nonsfi_ = true; 186 layer_two_is_nonsfi_ = true;
198 } else { 187 } else {
199 layer_two_enabled_ = nacl::InitializeBPFSandbox(proc_self_task.Pass()); 188 layer_two_enabled_ = nacl::InitializeBPFSandbox(proc_fd_.Pass());
200 } 189 }
201 } 190 }
202 191
203 void NaClSandbox::SealLayerOneSandbox() { 192 void NaClSandbox::SealLayerOneSandbox() {
204 if (!layer_two_enabled_) { 193 if (proc_fd_.is_valid() && !layer_two_enabled_) {
205 // If nothing prevents us, check that there is no superfluous directory 194 // If nothing prevents us, check that there is no superfluous directory
206 // open. 195 // open.
207 CHECK(!HasOpenDirectory()); 196 CHECK(!HasOpenDirectory());
208 } 197 }
209 proc_fd_.reset(); 198 proc_fd_.reset();
210 layer_one_sealed_ = true; 199 layer_one_sealed_ = true;
211 } 200 }
212 201
213 void NaClSandbox::CheckSandboxingStateWithPolicy() { 202 void NaClSandbox::CheckSandboxingStateWithPolicy() {
214 static const char kItIsDangerousMsg[] = " this is dangerous."; 203 static const char kItIsDangerousMsg[] = " this is dangerous.";
(...skipping 19 matching lines...) Expand all
234 static const char kNoBpfMsg[] = 223 static const char kNoBpfMsg[] =
235 "The seccomp-bpf sandbox is not engaged for NaCl:"; 224 "The seccomp-bpf sandbox is not engaged for NaCl:";
236 if (can_be_no_sandbox) 225 if (can_be_no_sandbox)
237 LOG(ERROR) << kNoBpfMsg << kItIsDangerousMsg; 226 LOG(ERROR) << kNoBpfMsg << kItIsDangerousMsg;
238 else 227 else
239 LOG(FATAL) << kNoBpfMsg << kItIsNotAllowedMsg; 228 LOG(FATAL) << kNoBpfMsg << kItIsNotAllowedMsg;
240 } 229 }
241 } 230 }
242 231
243 } // namespace nacl 232 } // namespace nacl
OLDNEW
« no previous file with comments | « components/nacl/loader/sandbox_linux/nacl_bpf_sandbox_linux.cc ('k') | content/common/sandbox_linux/sandbox_init_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698