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

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

Issue 733303004: Linux sandbox: change API to start the sandbox (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 6 years, 1 month 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 (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 <dirent.h> 5 #include <dirent.h>
6 #include <fcntl.h> 6 #include <fcntl.h>
7 #include <sys/resource.h> 7 #include <sys/resource.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 #include <sys/time.h> 9 #include <sys/time.h>
10 #include <sys/types.h> 10 #include <sys/types.h>
11 #include <unistd.h> 11 #include <unistd.h>
12 12
13 #include <limits> 13 #include <limits>
14 #include <string>
15 #include <vector>
14 16
15 #include "base/bind.h" 17 #include "base/bind.h"
16 #include "base/callback_helpers.h" 18 #include "base/callback_helpers.h"
17 #include "base/command_line.h" 19 #include "base/command_line.h"
18 #include "base/debug/stack_trace.h" 20 #include "base/debug/stack_trace.h"
19 #include "base/files/scoped_file.h" 21 #include "base/files/scoped_file.h"
20 #include "base/logging.h" 22 #include "base/logging.h"
21 #include "base/macros.h" 23 #include "base/macros.h"
22 #include "base/memory/scoped_ptr.h" 24 #include "base/memory/scoped_ptr.h"
23 #include "base/memory/singleton.h" 25 #include "base/memory/singleton.h"
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 #endif 85 #endif
84 } 86 }
85 87
86 // Try to open /proc/self/task/ with the help of |proc_fd|. |proc_fd| can be 88 // Try to open /proc/self/task/ with the help of |proc_fd|. |proc_fd| can be
87 // -1. Will return -1 on error and set errno like open(2). 89 // -1. Will return -1 on error and set errno like open(2).
88 int OpenProcTaskFd(int proc_fd) { 90 int OpenProcTaskFd(int proc_fd) {
89 int proc_self_task = -1; 91 int proc_self_task = -1;
90 if (proc_fd >= 0) { 92 if (proc_fd >= 0) {
91 // If a handle to /proc is available, use it. This allows to bypass file 93 // If a handle to /proc is available, use it. This allows to bypass file
92 // system restrictions. 94 // system restrictions.
93 proc_self_task = openat(proc_fd, "self/task/", O_RDONLY | O_DIRECTORY); 95 proc_self_task =
96 openat(proc_fd, "self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
94 } else { 97 } else {
95 // Otherwise, make an attempt to access the file system directly. 98 // Otherwise, make an attempt to access the file system directly.
96 proc_self_task = open("/proc/self/task/", O_RDONLY | O_DIRECTORY); 99 proc_self_task =
100 open("/proc/self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
97 } 101 }
98 return proc_self_task; 102 return proc_self_task;
99 } 103 }
100 104
101 } // namespace 105 } // namespace
102 106
103 namespace content { 107 namespace content {
104 108
105 LinuxSandbox::LinuxSandbox() 109 LinuxSandbox::LinuxSandbox()
106 : proc_fd_(-1), 110 : proc_fd_(-1),
(...skipping 30 matching lines...) Expand all
137 // This should not fork, not launch threads, not open a directory. 141 // This should not fork, not launch threads, not open a directory.
138 __sanitizer_sandbox_on_notify(sanitizer_args()); 142 __sanitizer_sandbox_on_notify(sanitizer_args());
139 sanitizer_args_.reset(); 143 sanitizer_args_.reset();
140 #endif 144 #endif
141 145
142 #if !defined(NDEBUG) 146 #if !defined(NDEBUG)
143 // The in-process stack dumping needs to open /proc/self/maps and cache 147 // The in-process stack dumping needs to open /proc/self/maps and cache
144 // its contents before the sandbox is enabled. It also pre-opens the 148 // its contents before the sandbox is enabled. It also pre-opens the
145 // object files that are already loaded in the process address space. 149 // object files that are already loaded in the process address space.
146 base::debug::EnableInProcessStackDumpingForSandbox(); 150 base::debug::EnableInProcessStackDumpingForSandbox();
151 #endif // !defined(NDEBUG)
147 152
148 // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't 153 // Open proc_fd_. It would break the security of the setuid sandbox if it was
149 // produce a sandbox escape in Release mode. 154 // not closed.
155 // If LinuxSandbox::PreinitializeSandbox() runs, InitializeSandbox() must run
mdempsky 2014/11/24 21:58:23 Can we CHECK this in ~LinuxSandbox()?
jln (very slow on Chromium) 2014/11/24 22:45:48 Done.
156 // as well.
150 proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC); 157 proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
151 CHECK_GE(proc_fd_, 0); 158 CHECK_GE(proc_fd_, 0);
152 #endif // !defined(NDEBUG)
153 // We "pre-warm" the code that detects supports for seccomp BPF. 159 // We "pre-warm" the code that detects supports for seccomp BPF.
154 if (SandboxSeccompBPF::IsSeccompBPFDesired()) { 160 if (SandboxSeccompBPF::IsSeccompBPFDesired()) {
155 if (!SandboxSeccompBPF::SupportsSandbox()) { 161 if (!SandboxSeccompBPF::SupportsSandbox()) {
156 VLOG(1) << "Lacking support for seccomp-bpf sandbox."; 162 VLOG(1) << "Lacking support for seccomp-bpf sandbox.";
157 } else { 163 } else {
158 seccomp_bpf_supported_ = true; 164 seccomp_bpf_supported_ = true;
159 } 165 }
160 } 166 }
161 167
162 // Yama is a "global", system-level status. We assume it will not regress 168 // Yama is a "global", system-level status. We assume it will not regress
163 // after startup. 169 // after startup.
164 const int yama_status = Yama::GetStatus(); 170 const int yama_status = Yama::GetStatus();
165 yama_is_enforcing_ = (yama_status & Yama::STATUS_PRESENT) && 171 yama_is_enforcing_ = (yama_status & Yama::STATUS_PRESENT) &&
166 (yama_status & Yama::STATUS_ENFORCING); 172 (yama_status & Yama::STATUS_ENFORCING);
167 pre_initialized_ = true; 173 pre_initialized_ = true;
168 } 174 }
169 175
176 std::vector<int> LinuxSandbox::GetFileDescriptorsToClose() {
177 return std::vector<int>{proc_fd_};
178 }
179
170 bool LinuxSandbox::InitializeSandbox() { 180 bool LinuxSandbox::InitializeSandbox() {
171 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); 181 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
172 return linux_sandbox->InitializeSandboxImpl(); 182 return linux_sandbox->InitializeSandboxImpl();
173 } 183 }
174 184
175 void LinuxSandbox::StopThread(base::Thread* thread) { 185 void LinuxSandbox::StopThread(base::Thread* thread) {
176 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); 186 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
177 linux_sandbox->StopThreadImpl(thread); 187 linux_sandbox->StopThreadImpl(thread);
178 } 188 }
179 189
(...skipping 22 matching lines...) Expand all
202 } 212 }
203 } 213 }
204 214
205 return sandbox_status_flags_; 215 return sandbox_status_flags_;
206 } 216 }
207 217
208 // Threads are counted via /proc/self/task. This is a little hairy because of 218 // Threads are counted via /proc/self/task. This is a little hairy because of
209 // PID namespaces and existing sandboxes, so "self" must really be used instead 219 // PID namespaces and existing sandboxes, so "self" must really be used instead
210 // of using the pid. 220 // of using the pid.
211 bool LinuxSandbox::IsSingleThreaded() const { 221 bool LinuxSandbox::IsSingleThreaded() const {
212 bool is_single_threaded = false;
213 base::ScopedFD proc_self_task(OpenProcTaskFd(proc_fd_)); 222 base::ScopedFD proc_self_task(OpenProcTaskFd(proc_fd_));
214 223
215 // In Debug mode, it's mandatory to be able to count threads to catch bugs.
216 #if !defined(NDEBUG)
217 // Using CHECK here since we want to check all the cases where
218 // !defined(NDEBUG)
219 // gets built.
220 CHECK(proc_self_task.is_valid()) 224 CHECK(proc_self_task.is_valid())
221 << "Could not count threads, the sandbox was not " 225 << "Could not count threads, the sandbox was not "
222 << "pre-initialized properly."; 226 << "pre-initialized properly.";
223 #endif // !defined(NDEBUG)
224 227
225 if (!proc_self_task.is_valid()) { 228 const bool is_single_threaded =
226 // Pretend to be monothreaded if it can't be determined (for instance the 229 sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get());
227 // setuid sandbox is already engaged but no proc_fd_ is available).
228 is_single_threaded = true;
229 } else {
230 is_single_threaded =
231 sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get());
232 }
233 230
234 return is_single_threaded; 231 return is_single_threaded;
235 } 232 }
236 233
237 bool LinuxSandbox::seccomp_bpf_started() const { 234 bool LinuxSandbox::seccomp_bpf_started() const {
238 return seccomp_bpf_started_; 235 return seccomp_bpf_started_;
239 } 236 }
240 237
241 sandbox::SetuidSandboxClient* 238 sandbox::SetuidSandboxClient*
242 LinuxSandbox::setuid_sandbox_client() const { 239 LinuxSandbox::setuid_sandbox_client() const {
243 return setuid_sandbox_client_.get(); 240 return setuid_sandbox_client_.get();
244 } 241 }
245 242
246 // For seccomp-bpf, we use the SandboxSeccompBPF class. 243 // For seccomp-bpf, we use the SandboxSeccompBPF class.
247 bool LinuxSandbox::StartSeccompBPF(const std::string& process_type) { 244 bool LinuxSandbox::StartSeccompBPF(const std::string& process_type) {
248 CHECK(!seccomp_bpf_started_); 245 CHECK(!seccomp_bpf_started_);
249 CHECK(pre_initialized_); 246 CHECK(pre_initialized_);
250 if (seccomp_bpf_supported()) 247 if (seccomp_bpf_supported()) {
251 seccomp_bpf_started_ = SandboxSeccompBPF::StartSandbox(process_type); 248 base::ScopedFD proc_self_task(OpenProcTaskFd(proc_fd_));
249 seccomp_bpf_started_ =
250 SandboxSeccompBPF::StartSandbox(process_type, proc_self_task.Pass());
251 }
252 252
253 if (seccomp_bpf_started_) 253 if (seccomp_bpf_started_) {
254 LogSandboxStarted("seccomp-bpf"); 254 LogSandboxStarted("seccomp-bpf");
255 }
255 256
256 return seccomp_bpf_started_; 257 return seccomp_bpf_started_;
257 } 258 }
258 259
259 bool LinuxSandbox::InitializeSandboxImpl() { 260 bool LinuxSandbox::InitializeSandboxImpl() {
260 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 261 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
261 const std::string process_type = 262 const std::string process_type =
262 command_line->GetSwitchValueASCII(switches::kProcessType); 263 command_line->GetSwitchValueASCII(switches::kProcessType);
263 264
264 // We need to make absolutely sure that our sandbox is "sealed" before 265 // We need to make absolutely sure that our sandbox is "sealed" before
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 407
407 void LinuxSandbox::StopThreadAndEnsureNotCounted(base::Thread* thread) const { 408 void LinuxSandbox::StopThreadAndEnsureNotCounted(base::Thread* thread) const {
408 DCHECK(thread); 409 DCHECK(thread);
409 base::ScopedFD proc_self_task(OpenProcTaskFd(proc_fd_)); 410 base::ScopedFD proc_self_task(OpenProcTaskFd(proc_fd_));
410 PCHECK(proc_self_task.is_valid()); 411 PCHECK(proc_self_task.is_valid());
411 CHECK(sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_self_task.get(), 412 CHECK(sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_self_task.get(),
412 thread)); 413 thread));
413 } 414 }
414 415
415 } // namespace content 416 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698