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 3 // found in the LICENSE file. 4 5 #include <dirent.h> 6 #include <fcntl.h> 7 #include <sys/resource.h> 8 #include <sys/stat.h> 9 #include <sys/time.h> 10 #include <sys/types.h> 11 #include <unistd.h> 12 13 #include <limits> 14 15 #include "base/bind.h" 16 #include "base/callback_helpers.h" 17 #include "base/command_line.h" 18 #include "base/debug/stack_trace.h" 19 #include "base/files/scoped_file.h" 20 #include "base/logging.h" 21 #include "base/memory/scoped_ptr.h" 22 #include "base/memory/singleton.h" 23 #include "base/posix/eintr_wrapper.h" 24 #include "base/strings/string_number_conversions.h" 25 #include "base/sys_info.h" 26 #include "base/time/time.h" 27 #include "build/build_config.h" 28 #include "content/common/sandbox_linux/sandbox_linux.h" 29 #include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h" 30 #include "content/public/common/content_switches.h" 31 #include "content/public/common/sandbox_linux.h" 32 #include "sandbox/linux/services/credentials.h" 33 #include "sandbox/linux/services/thread_helpers.h" 34 #include "sandbox/linux/services/yama.h" 35 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" 36 37 #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ 38 defined(LEAK_SANITIZER) || defined(UNDEFINED_SANITIZER) 39 #include <sanitizer/common_interface_defs.h> 40 #endif 41 42 using sandbox::Yama; 43 44 namespace { 45 46 struct FDCloser { 47 inline void operator()(int* fd) const { 48 DCHECK(fd); 49 PCHECK(0 == IGNORE_EINTR(close(*fd))); 50 *fd = -1; 51 } 52 }; 53 54 void LogSandboxStarted(const std::string& sandbox_name) { 55 const base::CommandLine& command_line = 56 *base::CommandLine::ForCurrentProcess(); 57 const std::string process_type = 58 command_line.GetSwitchValueASCII(switches::kProcessType); 59 const std::string activated_sandbox = 60 "Activated " + sandbox_name + " sandbox for process type: " + 61 process_type + "."; 62 VLOG(1) << activated_sandbox; 63 } 64 65 #if !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) 66 bool AddResourceLimit(int resource, rlim_t limit) { 67 struct rlimit old_rlimit; 68 if (getrlimit(resource, &old_rlimit)) 69 return false; 70 // Make sure we don't raise the existing limit. 71 const struct rlimit new_rlimit = { 72 std::min(old_rlimit.rlim_cur, limit), 73 std::min(old_rlimit.rlim_max, limit) 74 }; 75 int rc = setrlimit(resource, &new_rlimit); 76 return rc == 0; 77 } 78 #endif 79 80 bool IsRunningTSAN() { 81 #if defined(THREAD_SANITIZER) 82 return true; 83 #else 84 return false; 85 #endif 86 } 87 88 // Try to open /proc/self/task/ with the help of |proc_fd|. |proc_fd| can be 89 // -1. Will return -1 on error and set errno like open(2). 90 int OpenProcTaskFd(int proc_fd) { 91 int proc_self_task = -1; 92 if (proc_fd >= 0) { 93 // If a handle to /proc is available, use it. This allows to bypass file 94 // system restrictions. 95 proc_self_task = openat(proc_fd, "self/task/", O_RDONLY | O_DIRECTORY); 96 } else { 97 // Otherwise, make an attempt to access the file system directly. 98 proc_self_task = open("/proc/self/task/", O_RDONLY | O_DIRECTORY); 99 } 100 return proc_self_task; 101 } 102 103 } // namespace 104 105 namespace content { 106 107 LinuxSandbox::LinuxSandbox() 108 : proc_fd_(-1), 109 seccomp_bpf_started_(false), 110 sandbox_status_flags_(kSandboxLinuxInvalid), 111 pre_initialized_(false), 112 seccomp_bpf_supported_(false), 113 yama_is_enforcing_(false), 114 setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) 115 { 116 if (setuid_sandbox_client_ == NULL) { 117 LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; 118 } 119 #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ 120 defined(LEAK_SANITIZER) || defined(UNDEFINED_SANITIZER) 121 sanitizer_args_ = make_scoped_ptr(new __sanitizer_sandbox_arguments); 122 *sanitizer_args_ = {0}; 123 #endif 124 } 125 126 LinuxSandbox::~LinuxSandbox() { 127 } 128 129 LinuxSandbox* LinuxSandbox::GetInstance() { 130 LinuxSandbox* instance = Singleton<LinuxSandbox>::get(); 131 CHECK(instance); 132 return instance; 133 } 134 135 void LinuxSandbox::PreinitializeSandbox() { 136 CHECK(!pre_initialized_); 137 seccomp_bpf_supported_ = false; 138 #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ 139 defined(LEAK_SANITIZER) || defined(UNDEFINED_SANITIZER) 140 // Sanitizers need to open some resources before the sandbox is enabled. 141 // This should not fork, not launch threads, not open a directory. 142 __sanitizer_sandbox_on_notify(sanitizer_args()); 143 sanitizer_args_.reset(); 144 #endif 145 146 #if !defined(NDEBUG) 147 // The in-process stack dumping needs to open /proc/self/maps and cache 148 // its contents before the sandbox is enabled. It also pre-opens the 149 // object files that are already loaded in the process address space. 150 base::debug::EnableInProcessStackDumpingForSandbox(); 151 152 // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't 153 // produce a sandbox escape in Release mode. 154 proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC); 155 CHECK_GE(proc_fd_, 0); 156 #endif // !defined(NDEBUG) 157 // We "pre-warm" the code that detects supports for seccomp BPF. 158 if (SandboxSeccompBPF::IsSeccompBPFDesired()) { 159 if (!SandboxSeccompBPF::SupportsSandbox()) { 160 VLOG(1) << "Lacking support for seccomp-bpf sandbox."; 161 } else { 162 seccomp_bpf_supported_ = true; 163 } 164 } 165 166 // Yama is a "global", system-level status. We assume it will not regress 167 // after startup. 168 const int yama_status = Yama::GetStatus(); 169 yama_is_enforcing_ = (yama_status & Yama::STATUS_PRESENT) && 170 (yama_status & Yama::STATUS_ENFORCING); 171 pre_initialized_ = true; 172 } 173 174 bool LinuxSandbox::InitializeSandbox() { 175 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); 176 return linux_sandbox->InitializeSandboxImpl(); 177 } 178 179 void LinuxSandbox::StopThread(base::Thread* thread) { 180 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); 181 linux_sandbox->StopThreadImpl(thread); 182 } 183 184 int LinuxSandbox::GetStatus() { 185 CHECK(pre_initialized_); 186 if (kSandboxLinuxInvalid == sandbox_status_flags_) { 187 // Initialize sandbox_status_flags_. 188 sandbox_status_flags_ = 0; 189 if (setuid_sandbox_client_->IsSandboxed()) { 190 sandbox_status_flags_ |= kSandboxLinuxSUID; 191 if (setuid_sandbox_client_->IsInNewPIDNamespace()) 192 sandbox_status_flags_ |= kSandboxLinuxPIDNS; 193 if (setuid_sandbox_client_->IsInNewNETNamespace()) 194 sandbox_status_flags_ |= kSandboxLinuxNetNS; 195 } 196 197 // We report whether the sandbox will be activated when renderers, workers 198 // and PPAPI plugins go through sandbox initialization. 199 if (seccomp_bpf_supported() && 200 SandboxSeccompBPF::ShouldEnableSeccompBPF(switches::kRendererProcess)) { 201 sandbox_status_flags_ |= kSandboxLinuxSeccompBPF; 202 } 203 204 if (yama_is_enforcing_) { 205 sandbox_status_flags_ |= kSandboxLinuxYama; 206 } 207 } 208 209 return sandbox_status_flags_; 210 } 211 212 // Threads are counted via /proc/self/task. This is a little hairy because of 213 // PID namespaces and existing sandboxes, so "self" must really be used instead 214 // of using the pid. 215 bool LinuxSandbox::IsSingleThreaded() const { 216 bool is_single_threaded = false; 217 base::ScopedFD proc_self_task(OpenProcTaskFd(proc_fd_)); 218 219 // In Debug mode, it's mandatory to be able to count threads to catch bugs. 220 #if !defined(NDEBUG) 221 // Using CHECK here since we want to check all the cases where 222 // !defined(NDEBUG) 223 // gets built. 224 CHECK(proc_self_task.is_valid()) 225 << "Could not count threads, the sandbox was not " 226 << "pre-initialized properly."; 227 #endif // !defined(NDEBUG) 228 229 if (!proc_self_task.is_valid()) { 230 // Pretend to be monothreaded if it can't be determined (for instance the 231 // setuid sandbox is already engaged but no proc_fd_ is available). 232 is_single_threaded = true; 233 } else { 234 is_single_threaded = 235 sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get()); 236 } 237 238 return is_single_threaded; 239 } 240 241 bool LinuxSandbox::seccomp_bpf_started() const { 242 return seccomp_bpf_started_; 243 } 244 245 sandbox::SetuidSandboxClient* 246 LinuxSandbox::setuid_sandbox_client() const { 247 return setuid_sandbox_client_.get(); 248 } 249 250 // For seccomp-bpf, we use the SandboxSeccompBPF class. 251 bool LinuxSandbox::StartSeccompBPF(const std::string& process_type) { 252 CHECK(!seccomp_bpf_started_); 253 CHECK(pre_initialized_); 254 if (seccomp_bpf_supported()) 255 seccomp_bpf_started_ = SandboxSeccompBPF::StartSandbox(process_type); 256 257 if (seccomp_bpf_started_) 258 LogSandboxStarted("seccomp-bpf"); 259 260 return seccomp_bpf_started_; 261 } 262 263 bool LinuxSandbox::InitializeSandboxImpl() { 264 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 265 const std::string process_type = 266 command_line->GetSwitchValueASCII(switches::kProcessType); 267 268 // We need to make absolutely sure that our sandbox is "sealed" before 269 // returning. 270 // Unretained() since the current object is a Singleton. 271 base::ScopedClosureRunner sandbox_sealer( 272 base::Bind(&LinuxSandbox::SealSandbox, base::Unretained(this))); 273 // Make sure that this function enables sandboxes as promised by GetStatus(). 274 // Unretained() since the current object is a Singleton. 275 base::ScopedClosureRunner sandbox_promise_keeper( 276 base::Bind(&LinuxSandbox::CheckForBrokenPromises, 277 base::Unretained(this), 278 process_type)); 279 280 // No matter what, it's always an error to call InitializeSandbox() after 281 // threads have been created. 282 if (!IsSingleThreaded()) { 283 std::string error_message = "InitializeSandbox() called with multiple " 284 "threads in process " + process_type; 285 // TSAN starts a helper thread, so we don't start the sandbox and don't 286 // even report an error about it. 287 if (IsRunningTSAN()) 288 return false; 289 290 // The GPU process is allowed to call InitializeSandbox() with threads. 291 bool sandbox_failure_fatal = process_type != switches::kGpuProcess; 292 // This can be disabled with the '--gpu-sandbox-failures-fatal' flag. 293 // Setting the flag with no value or any value different than 'yes' or 'no' 294 // is equal to setting '--gpu-sandbox-failures-fatal=yes'. 295 if (process_type == switches::kGpuProcess && 296 command_line->HasSwitch(switches::kGpuSandboxFailuresFatal)) { 297 const std::string switch_value = 298 command_line->GetSwitchValueASCII(switches::kGpuSandboxFailuresFatal); 299 sandbox_failure_fatal = switch_value != "no"; 300 } 301 302 if (sandbox_failure_fatal) 303 LOG(FATAL) << error_message; 304 305 LOG(ERROR) << error_message; 306 return false; 307 } 308 309 // Only one thread is running, pre-initialize if not already done. 310 if (!pre_initialized_) 311 PreinitializeSandbox(); 312 313 DCHECK(!HasOpenDirectories()) << 314 "InitializeSandbox() called after unexpected directories have been " << 315 "opened. This breaks the security of the setuid sandbox."; 316 317 // Attempt to limit the future size of the address space of the process. 318 LimitAddressSpace(process_type); 319 320 // Try to enable seccomp-bpf. 321 bool seccomp_bpf_started = StartSeccompBPF(process_type); 322 323 return seccomp_bpf_started; 324 } 325 326 void LinuxSandbox::StopThreadImpl(base::Thread* thread) { 327 DCHECK(thread); 328 StopThreadAndEnsureNotCounted(thread); 329 } 330 331 bool LinuxSandbox::seccomp_bpf_supported() const { 332 CHECK(pre_initialized_); 333 return seccomp_bpf_supported_; 334 } 335 336 bool LinuxSandbox::LimitAddressSpace(const std::string& process_type) { 337 (void) process_type; 338 #if !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) 339 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 340 if (command_line->HasSwitch(switches::kNoSandbox)) { 341 return false; 342 } 343 344 // Limit the address space to 4GB. 345 // This is in the hope of making some kernel exploits more complex and less 346 // reliable. It also limits sprays a little on 64-bit. 347 rlim_t address_space_limit = std::numeric_limits<uint32_t>::max(); 348 #if defined(__LP64__) 349 // On 64 bits, V8 and possibly others will reserve massive memory ranges and 350 // rely on on-demand paging for allocation. Unfortunately, even 351 // MADV_DONTNEED ranges count towards RLIMIT_AS so this is not an option. 352 // See crbug.com/169327 for a discussion. 353 // On the GPU process, irrespective of V8, we can exhaust a 4GB address space 354 // under normal usage, see crbug.com/271119 355 // For now, increase limit to 16GB for renderer and worker and gpu processes 356 // to accomodate. 357 if (process_type == switches::kRendererProcess || 358 process_type == switches::kGpuProcess) { 359 address_space_limit = 1L << 34; 360 } 361 #endif // defined(__LP64__) 362 363 // On all platforms, add a limit to the brk() heap that would prevent 364 // allocations that can't be index by an int. 365 const rlim_t kNewDataSegmentMaxSize = std::numeric_limits<int>::max(); 366 367 bool limited_as = AddResourceLimit(RLIMIT_AS, address_space_limit); 368 bool limited_data = AddResourceLimit(RLIMIT_DATA, kNewDataSegmentMaxSize); 369 370 // Cache the resource limit before turning on the sandbox. 371 base::SysInfo::AmountOfVirtualMemory(); 372 373 return limited_as && limited_data; 374 #else 375 base::SysInfo::AmountOfVirtualMemory(); 376 return false; 377 #endif // !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) 378 } 379 380 bool LinuxSandbox::HasOpenDirectories() const { 381 return sandbox::Credentials().HasOpenDirectory(proc_fd_); 382 } 383 384 void LinuxSandbox::SealSandbox() { 385 if (proc_fd_ >= 0) { 386 int ret = IGNORE_EINTR(close(proc_fd_)); 387 CHECK_EQ(0, ret); 388 proc_fd_ = -1; 389 } 390 } 391 392 void LinuxSandbox::CheckForBrokenPromises(const std::string& process_type) { 393 // Make sure that any promise made with GetStatus() wasn't broken. 394 bool promised_seccomp_bpf_would_start = false; 395 if (process_type == switches::kRendererProcess || 396 process_type == switches::kPpapiPluginProcess) { 397 promised_seccomp_bpf_would_start = 398 (sandbox_status_flags_ != kSandboxLinuxInvalid) && 399 (GetStatus() & kSandboxLinuxSeccompBPF); 400 } 401 if (promised_seccomp_bpf_would_start) { 402 CHECK(seccomp_bpf_started_); 403 } 404 } 405 406 void LinuxSandbox::StopThreadAndEnsureNotCounted(base::Thread* thread) const { 407 DCHECK(thread); 408 base::ScopedFD proc_self_task(OpenProcTaskFd(proc_fd_)); 409 PCHECK(proc_self_task.is_valid()); 410 CHECK(sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_self_task.get(), 411 thread)); 412 } 413 414 } // namespace content 415