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 "content/zygote/zygote_main.h" 6 7#include <dlfcn.h> 8#include <fcntl.h> 9#include <pthread.h> 10#include <string.h> 11#include <sys/socket.h> 12#include <sys/types.h> 13#include <unistd.h> 14 15#include "base/basictypes.h" 16#include "base/bind.h" 17#include "base/command_line.h" 18#include "base/compiler_specific.h" 19#include "base/memory/scoped_vector.h" 20#include "base/native_library.h" 21#include "base/pickle.h" 22#include "base/posix/eintr_wrapper.h" 23#include "base/posix/unix_domain_socket_linux.h" 24#include "base/rand_util.h" 25#include "base/strings/string_number_conversions.h" 26#include "base/sys_info.h" 27#include "build/build_config.h" 28#include "content/common/child_process_sandbox_support_impl_linux.h" 29#include "content/common/font_config_ipc_linux.h" 30#include "content/common/pepper_plugin_list.h" 31#include "content/common/sandbox_linux/sandbox_linux.h" 32#include "content/common/zygote_commands_linux.h" 33#include "content/public/common/content_switches.h" 34#include "content/public/common/main_function_params.h" 35#include "content/public/common/pepper_plugin_info.h" 36#include "content/public/common/sandbox_linux.h" 37#include "content/public/common/zygote_fork_delegate_linux.h" 38#include "content/zygote/zygote_linux.h" 39#include "crypto/nss_util.h" 40#include "sandbox/linux/services/init_process_reaper.h" 41#include "sandbox/linux/services/libc_urandom_override.h" 42#include "sandbox/linux/suid/client/setuid_sandbox_client.h" 43#include "third_party/icu/source/i18n/unicode/timezone.h" 44#include "third_party/skia/include/ports/SkFontConfigInterface.h" 45 46#if defined(OS_LINUX) 47#include <sys/prctl.h> 48#endif 49 50#if defined(ENABLE_WEBRTC) 51#include "third_party/libjingle/overrides/init_webrtc.h" 52#endif 53 54#if defined(ADDRESS_SANITIZER) 55#include <sanitizer/asan_interface.h> 56#endif 57 58namespace content { 59 60// See http://code.google.com/p/chromium/wiki/LinuxZygote 61 62static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, 63 char* timezone_out, 64 size_t timezone_out_len) { 65 Pickle request; 66 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME); 67 request.WriteString( 68 std::string(reinterpret_cast<char*>(&input), sizeof(input))); 69 70 uint8_t reply_buf[512]; 71 const ssize_t r = UnixDomainSocket::SendRecvMsg( 72 GetSandboxFD(), reply_buf, sizeof(reply_buf), NULL, 73 request); 74 if (r == -1) { 75 memset(output, 0, sizeof(struct tm)); 76 return; 77 } 78 79 Pickle reply(reinterpret_cast<char*>(reply_buf), r); 80 PickleIterator iter(reply); 81 std::string result, timezone; 82 if (!reply.ReadString(&iter, &result) || 83 !reply.ReadString(&iter, &timezone) || 84 result.size() != sizeof(struct tm)) { 85 memset(output, 0, sizeof(struct tm)); 86 return; 87 } 88 89 memcpy(output, result.data(), sizeof(struct tm)); 90 if (timezone_out_len) { 91 const size_t copy_len = std::min(timezone_out_len - 1, timezone.size()); 92 memcpy(timezone_out, timezone.data(), copy_len); 93 timezone_out[copy_len] = 0; 94 output->tm_zone = timezone_out; 95 } else { 96 output->tm_zone = NULL; 97 } 98} 99 100static bool g_am_zygote_or_renderer = false; 101 102// Sandbox interception of libc calls. 103// 104// Because we are running in a sandbox certain libc calls will fail (localtime 105// being the motivating example - it needs to read /etc/localtime). We need to 106// intercept these calls and proxy them to the browser. However, these calls 107// may come from us or from our libraries. In some cases we can't just change 108// our code. 109// 110// It's for these cases that we have the following setup: 111// 112// We define global functions for those functions which we wish to override. 113// Since we will be first in the dynamic resolution order, the dynamic linker 114// will point callers to our versions of these functions. However, we have the 115// same binary for both the browser and the renderers, which means that our 116// overrides will apply in the browser too. 117// 118// The global |g_am_zygote_or_renderer| is true iff we are in a zygote or 119// renderer process. It's set in ZygoteMain and inherited by the renderers when 120// they fork. (This means that it'll be incorrect for global constructor 121// functions and before ZygoteMain is called - beware). 122// 123// Our replacement functions can check this global and either proxy 124// the call to the browser over the sandbox IPC 125// (http://code.google.com/p/chromium/wiki/LinuxSandboxIPC) or they can use 126// dlsym with RTLD_NEXT to resolve the symbol, ignoring any symbols in the 127// current module. 128// 129// Other avenues: 130// 131// Our first attempt involved some assembly to patch the GOT of the current 132// module. This worked, but was platform specific and doesn't catch the case 133// where a library makes a call rather than current module. 134// 135// We also considered patching the function in place, but this would again by 136// platform specific and the above technique seems to work well enough. 137 138typedef struct tm* (*LocaltimeFunction)(const time_t* timep); 139typedef struct tm* (*LocaltimeRFunction)(const time_t* timep, 140 struct tm* result); 141 142static pthread_once_t g_libc_localtime_funcs_guard = PTHREAD_ONCE_INIT; 143static LocaltimeFunction g_libc_localtime; 144static LocaltimeFunction g_libc_localtime64; 145static LocaltimeRFunction g_libc_localtime_r; 146static LocaltimeRFunction g_libc_localtime64_r; 147 148static void InitLibcLocaltimeFunctions() { 149 g_libc_localtime = reinterpret_cast<LocaltimeFunction>( 150 dlsym(RTLD_NEXT, "localtime")); 151 g_libc_localtime64 = reinterpret_cast<LocaltimeFunction>( 152 dlsym(RTLD_NEXT, "localtime64")); 153 g_libc_localtime_r = reinterpret_cast<LocaltimeRFunction>( 154 dlsym(RTLD_NEXT, "localtime_r")); 155 g_libc_localtime64_r = reinterpret_cast<LocaltimeRFunction>( 156 dlsym(RTLD_NEXT, "localtime64_r")); 157 158 if (!g_libc_localtime || !g_libc_localtime_r) { 159 // http://code.google.com/p/chromium/issues/detail?id=16800 160 // 161 // Nvidia's libGL.so overrides dlsym for an unknown reason and replaces 162 // it with a version which doesn't work. In this case we'll get a NULL 163 // result. There's not a lot we can do at this point, so we just bodge it! 164 LOG(ERROR) << "Your system is broken: dlsym doesn't work! This has been " 165 "reported to be caused by Nvidia's libGL. You should expect" 166 " time related functions to misbehave. " 167 "http://code.google.com/p/chromium/issues/detail?id=16800"; 168 } 169 170 if (!g_libc_localtime) 171 g_libc_localtime = gmtime; 172 if (!g_libc_localtime64) 173 g_libc_localtime64 = g_libc_localtime; 174 if (!g_libc_localtime_r) 175 g_libc_localtime_r = gmtime_r; 176 if (!g_libc_localtime64_r) 177 g_libc_localtime64_r = g_libc_localtime_r; 178} 179 180// Define localtime_override() function with asm name "localtime", so that all 181// references to localtime() will resolve to this function. Notice that we need 182// to set visibility attribute to "default" to export the symbol, as it is set 183// to "hidden" by default in chrome per build/common.gypi. 184__attribute__ ((__visibility__("default"))) 185struct tm* localtime_override(const time_t* timep) __asm__ ("localtime"); 186 187__attribute__ ((__visibility__("default"))) 188struct tm* localtime_override(const time_t* timep) { 189 if (g_am_zygote_or_renderer) { 190 static struct tm time_struct; 191 static char timezone_string[64]; 192 ProxyLocaltimeCallToBrowser(*timep, &time_struct, timezone_string, 193 sizeof(timezone_string)); 194 return &time_struct; 195 } else { 196 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard, 197 InitLibcLocaltimeFunctions)); 198 struct tm* res = g_libc_localtime(timep); 199#if defined(MEMORY_SANITIZER) 200 if (res) __msan_unpoison(res, sizeof(*res)); 201 if (res->tm_zone) __msan_unpoison_string(res->tm_zone); 202#endif 203 return res; 204 } 205} 206 207// Use same trick to override localtime64(), localtime_r() and localtime64_r(). 208__attribute__ ((__visibility__("default"))) 209struct tm* localtime64_override(const time_t* timep) __asm__ ("localtime64"); 210 211__attribute__ ((__visibility__("default"))) 212struct tm* localtime64_override(const time_t* timep) { 213 if (g_am_zygote_or_renderer) { 214 static struct tm time_struct; 215 static char timezone_string[64]; 216 ProxyLocaltimeCallToBrowser(*timep, &time_struct, timezone_string, 217 sizeof(timezone_string)); 218 return &time_struct; 219 } else { 220 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard, 221 InitLibcLocaltimeFunctions)); 222 struct tm* res = g_libc_localtime64(timep); 223#if defined(MEMORY_SANITIZER) 224 if (res) __msan_unpoison(res, sizeof(*res)); 225 if (res->tm_zone) __msan_unpoison_string(res->tm_zone); 226#endif 227 return res; 228 } 229} 230 231__attribute__ ((__visibility__("default"))) 232struct tm* localtime_r_override(const time_t* timep, 233 struct tm* result) __asm__ ("localtime_r"); 234 235__attribute__ ((__visibility__("default"))) 236struct tm* localtime_r_override(const time_t* timep, struct tm* result) { 237 if (g_am_zygote_or_renderer) { 238 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0); 239 return result; 240 } else { 241 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard, 242 InitLibcLocaltimeFunctions)); 243 struct tm* res = g_libc_localtime_r(timep, result); 244#if defined(MEMORY_SANITIZER) 245 if (res) __msan_unpoison(res, sizeof(*res)); 246 if (res->tm_zone) __msan_unpoison_string(res->tm_zone); 247#endif 248 return res; 249 } 250} 251 252__attribute__ ((__visibility__("default"))) 253struct tm* localtime64_r_override(const time_t* timep, 254 struct tm* result) __asm__ ("localtime64_r"); 255 256__attribute__ ((__visibility__("default"))) 257struct tm* localtime64_r_override(const time_t* timep, struct tm* result) { 258 if (g_am_zygote_or_renderer) { 259 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0); 260 return result; 261 } else { 262 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard, 263 InitLibcLocaltimeFunctions)); 264 struct tm* res = g_libc_localtime64_r(timep, result); 265#if defined(MEMORY_SANITIZER) 266 if (res) __msan_unpoison(res, sizeof(*res)); 267 if (res->tm_zone) __msan_unpoison_string(res->tm_zone); 268#endif 269 return res; 270 } 271} 272 273#if defined(ENABLE_PLUGINS) 274// Loads the (native) libraries but does not initialize them (i.e., does not 275// call PPP_InitializeModule). This is needed by the zygote on Linux to get 276// access to the plugins before entering the sandbox. 277void PreloadPepperPlugins() { 278 std::vector<PepperPluginInfo> plugins; 279 ComputePepperPluginList(&plugins); 280 for (size_t i = 0; i < plugins.size(); ++i) { 281 if (!plugins[i].is_internal && plugins[i].is_sandboxed) { 282 base::NativeLibraryLoadError error; 283 base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path, 284 &error); 285 VLOG_IF(1, !library) << "Unable to load plugin " 286 << plugins[i].path.value() << " " 287 << error.ToString(); 288 289 (void)library; // Prevent release-mode warning. 290 } 291 } 292} 293#endif 294 295// This function triggers the static and lazy construction of objects that need 296// to be created before imposing the sandbox. 297static void ZygotePreSandboxInit() { 298 base::RandUint64(); 299 300 base::SysInfo::AmountOfPhysicalMemory(); 301 base::SysInfo::MaxSharedMemorySize(); 302 base::SysInfo::NumberOfProcessors(); 303 304 // ICU DateFormat class (used in base/time_format.cc) needs to get the 305 // Olson timezone ID by accessing the zoneinfo files on disk. After 306 // TimeZone::createDefault is called once here, the timezone ID is 307 // cached and there's no more need to access the file system. 308 scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault()); 309 310#if defined(USE_NSS) 311 // NSS libraries are loaded before sandbox is activated. This is to allow 312 // successful initialization of NSS which tries to load extra library files. 313 crypto::LoadNSSLibraries(); 314#elif defined(USE_OPENSSL) 315 // OpenSSL is intentionally not supported in the sandboxed processes, see 316 // http://crbug.com/99163. If that ever changes we'll likely need to init 317 // OpenSSL here (at least, load the library and error strings). 318#else 319 // It's possible that another hypothetical crypto stack would not require 320 // pre-sandbox init, but more likely this is just a build configuration error. 321 #error Which SSL library are you using? 322#endif 323#if defined(ENABLE_PLUGINS) 324 // Ensure access to the Pepper plugins before the sandbox is turned on. 325 PreloadPepperPlugins(); 326#endif 327#if defined(ENABLE_WEBRTC) 328 InitializeWebRtcModule(); 329#endif 330 SkFontConfigInterface::SetGlobal( 331 new FontConfigIPC(GetSandboxFD()))->unref(); 332} 333 334static bool CreateInitProcessReaper(base::Closure* post_fork_parent_callback) { 335 // The current process becomes init(1), this function returns from a 336 // newly created process. 337 const bool init_created = 338 sandbox::CreateInitProcessReaper(post_fork_parent_callback); 339 if (!init_created) { 340 LOG(ERROR) << "Error creating an init process to reap zombies"; 341 return false; 342 } 343 return true; 344} 345 346// Enter the setuid sandbox. This requires the current process to have been 347// created through the setuid sandbox. 348static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox, 349 base::Closure* post_fork_parent_callback) { 350 DCHECK(setuid_sandbox); 351 DCHECK(setuid_sandbox->IsSuidSandboxChild()); 352 353 // Use the SUID sandbox. This still allows the seccomp sandbox to 354 // be enabled by the process later. 355 356 if (!setuid_sandbox->IsSuidSandboxUpToDate()) { 357 LOG(WARNING) << 358 "You are using a wrong version of the setuid binary!\n" 359 "Please read " 360 "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment." 361 "\n\n"; 362 } 363 364 if (!setuid_sandbox->ChrootMe()) 365 return false; 366 367 if (setuid_sandbox->IsInNewPIDNamespace()) { 368 CHECK_EQ(1, getpid()) 369 << "The SUID sandbox created a new PID namespace but Zygote " 370 "is not the init process. Please, make sure the SUID " 371 "binary is up to date."; 372 } 373 374 if (getpid() == 1) { 375 // The setuid sandbox has created a new PID namespace and we need 376 // to assume the role of init. 377 CHECK(CreateInitProcessReaper(post_fork_parent_callback)); 378 } 379 380#if !defined(OS_OPENBSD) 381 // Previously, we required that the binary be non-readable. This causes the 382 // kernel to mark the process as non-dumpable at startup. The thinking was 383 // that, although we were putting the renderers into a PID namespace (with 384 // the SUID sandbox), they would nonetheless be in the /same/ PID 385 // namespace. So they could ptrace each other unless they were non-dumpable. 386 // 387 // If the binary was readable, then there would be a window between process 388 // startup and the point where we set the non-dumpable flag in which a 389 // compromised renderer could ptrace attach. 390 // 391 // However, now that we have a zygote model, only the (trusted) zygote 392 // exists at this point and we can set the non-dumpable flag which is 393 // inherited by all our renderer children. 394 // 395 // Note: a non-dumpable process can't be debugged. To debug sandbox-related 396 // issues, one can specify --allow-sandbox-debugging to let the process be 397 // dumpable. 398 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 399 if (!command_line.HasSwitch(switches::kAllowSandboxDebugging)) { 400 prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); 401 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { 402 LOG(ERROR) << "Failed to set non-dumpable flag"; 403 return false; 404 } 405 } 406#endif 407 408 return true; 409} 410 411#if defined(ADDRESS_SANITIZER) 412const size_t kSanitizerMaxMessageLength = 1 * 1024 * 1024; 413 414// A helper process which collects code coverage data from the renderers over a 415// socket and dumps it to a file. See http://crbug.com/336212 for discussion. 416static void SanitizerCoverageHelper(int socket_fd, int file_fd) { 417 scoped_ptr<char[]> buffer(new char[kSanitizerMaxMessageLength]); 418 while (true) { 419 ssize_t received_size = HANDLE_EINTR( 420 recv(socket_fd, buffer.get(), kSanitizerMaxMessageLength, 0)); 421 PCHECK(received_size >= 0); 422 if (received_size == 0) 423 // All clients have closed the socket. We should die. 424 _exit(0); 425 PCHECK(file_fd >= 0); 426 ssize_t written_size = 0; 427 while (written_size < received_size) { 428 ssize_t write_res = 429 HANDLE_EINTR(write(file_fd, buffer.get() + written_size, 430 received_size - written_size)); 431 PCHECK(write_res >= 0); 432 written_size += write_res; 433 } 434 PCHECK(0 == HANDLE_EINTR(fsync(file_fd))); 435 } 436} 437 438// fds[0] is the read end, fds[1] is the write end. 439static void CreateSanitizerCoverageSocketPair(int fds[2]) { 440 PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds)); 441 PCHECK(0 == shutdown(fds[0], SHUT_WR)); 442 PCHECK(0 == shutdown(fds[1], SHUT_RD)); 443} 444 445static pid_t ForkSanitizerCoverageHelper(int child_fd, int parent_fd, 446 base::ScopedFD file_fd) { 447 pid_t pid = fork(); 448 PCHECK(pid >= 0); 449 if (pid == 0) { 450 // In the child. 451 PCHECK(0 == IGNORE_EINTR(close(parent_fd))); 452 SanitizerCoverageHelper(child_fd, file_fd.get()); 453 _exit(0); 454 } else { 455 // In the parent. 456 PCHECK(0 == IGNORE_EINTR(close(child_fd))); 457 return pid; 458 } 459} 460 461void CloseFdPair(const int fds[2]) { 462 PCHECK(0 == IGNORE_EINTR(close(fds[0]))); 463 PCHECK(0 == IGNORE_EINTR(close(fds[1]))); 464} 465#endif // defined(ADDRESS_SANITIZER) 466 467// If |is_suid_sandbox_child|, then make sure that the setuid sandbox is 468// engaged. 469static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox, 470 bool is_suid_sandbox_child, 471 base::Closure* post_fork_parent_callback) { 472 DCHECK(linux_sandbox); 473 474 ZygotePreSandboxInit(); 475 476 // Check that the pre-sandbox initialization didn't spawn threads. 477#if !defined(THREAD_SANITIZER) 478 DCHECK(linux_sandbox->IsSingleThreaded()); 479#endif 480 481 sandbox::SetuidSandboxClient* setuid_sandbox = 482 linux_sandbox->setuid_sandbox_client(); 483 484 if (is_suid_sandbox_child) { 485 CHECK(EnterSuidSandbox(setuid_sandbox, post_fork_parent_callback)) 486 << "Failed to enter setuid sandbox"; 487 } 488} 489 490bool ZygoteMain(const MainFunctionParams& params, 491 ScopedVector<ZygoteForkDelegate> fork_delegates) { 492 g_am_zygote_or_renderer = true; 493 sandbox::InitLibcUrandomOverrides(); 494 495 base::Closure *post_fork_parent_callback = NULL; 496 497 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); 498 499#if defined(ADDRESS_SANITIZER) 500 const std::string sancov_file_name = 501 "zygote." + base::Uint64ToString(base::RandUint64()); 502 base::ScopedFD sancov_file_fd( 503 __sanitizer_maybe_open_cov_file(sancov_file_name.c_str())); 504 int sancov_socket_fds[2] = {-1, -1}; 505 CreateSanitizerCoverageSocketPair(sancov_socket_fds); 506 linux_sandbox->sanitizer_args()->coverage_sandboxed = 1; 507 linux_sandbox->sanitizer_args()->coverage_fd = sancov_socket_fds[1]; 508 linux_sandbox->sanitizer_args()->coverage_max_block_size = 509 kSanitizerMaxMessageLength; 510 // Zygote termination will block until the helper process exits, which will 511 // not happen until the write end of the socket is closed everywhere. Make 512 // sure the init process does not hold on to it. 513 base::Closure close_sancov_socket_fds = 514 base::Bind(&CloseFdPair, sancov_socket_fds); 515 post_fork_parent_callback = &close_sancov_socket_fds; 516#endif 517 518 // This will pre-initialize the various sandboxes that need it. 519 linux_sandbox->PreinitializeSandbox(); 520 521 const bool must_enable_setuid_sandbox = 522 linux_sandbox->setuid_sandbox_client()->IsSuidSandboxChild(); 523 if (must_enable_setuid_sandbox) { 524 linux_sandbox->setuid_sandbox_client()->CloseDummyFile(); 525 526 // Let the ZygoteHost know we're booting up. 527 CHECK(UnixDomainSocket::SendMsg(kZygoteSocketPairFd, 528 kZygoteBootMessage, 529 sizeof(kZygoteBootMessage), 530 std::vector<int>())); 531 } 532 533 VLOG(1) << "ZygoteMain: initializing " << fork_delegates.size() 534 << " fork delegates"; 535 for (ScopedVector<ZygoteForkDelegate>::iterator i = fork_delegates.begin(); 536 i != fork_delegates.end(); 537 ++i) { 538 (*i)->Init(GetSandboxFD(), must_enable_setuid_sandbox); 539 } 540 541 // Turn on the first layer of the sandbox if the configuration warrants it. 542 EnterLayerOneSandbox(linux_sandbox, must_enable_setuid_sandbox, 543 post_fork_parent_callback); 544 545 std::vector<pid_t> extra_children; 546 std::vector<int> extra_fds; 547 548#if defined(ADDRESS_SANITIZER) 549 pid_t sancov_helper_pid = ForkSanitizerCoverageHelper( 550 sancov_socket_fds[0], sancov_socket_fds[1], sancov_file_fd.Pass()); 551 // It's important that the zygote reaps the helper before dying. Otherwise, 552 // the destruction of the PID namespace could kill the helper before it 553 // completes its I/O tasks. |sancov_helper_pid| will exit once the last 554 // renderer holding the write end of |sancov_socket_fds| closes it. 555 extra_children.push_back(sancov_helper_pid); 556 // Sanitizer code in the renderers will inherit the write end of the socket 557 // from the zygote. We must keep it open until the very end of the zygote's 558 // lifetime, even though we don't explicitly use it. 559 extra_fds.push_back(sancov_socket_fds[1]); 560#endif 561 562 int sandbox_flags = linux_sandbox->GetStatus(); 563 bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID; 564 CHECK_EQ(must_enable_setuid_sandbox, setuid_sandbox_engaged); 565 566 Zygote zygote(sandbox_flags, fork_delegates.Pass(), extra_children, 567 extra_fds); 568 // This function call can return multiple times, once per fork(). 569 return zygote.ProcessRequests(); 570} 571 572} // namespace content 573