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 <stdio.h> 11 #include <sys/socket.h> 12 #include <sys/stat.h> 13 #include <sys/types.h> 14 #include <sys/wait.h> 15 #include <unistd.h> 16 17 #include "base/basictypes.h" 18 #include "base/command_line.h" 19 #include "base/containers/hash_tables.h" 20 #include "base/files/file_path.h" 21 #include "base/linux_util.h" 22 #include "base/memory/scoped_ptr.h" 23 #include "base/native_library.h" 24 #include "base/pickle.h" 25 #include "base/posix/eintr_wrapper.h" 26 #include "base/posix/unix_domain_socket_linux.h" 27 #include "base/rand_util.h" 28 #include "base/sys_info.h" 29 #include "build/build_config.h" 30 #include "content/common/font_config_ipc_linux.h" 31 #include "content/common/pepper_plugin_list.h" 32 #include "content/common/sandbox_linux.h" 33 #include "content/common/zygote_commands_linux.h" 34 #include "content/public/common/content_switches.h" 35 #include "content/public/common/main_function_params.h" 36 #include "content/public/common/pepper_plugin_info.h" 37 #include "content/public/common/sandbox_linux.h" 38 #include "content/public/common/zygote_fork_delegate_linux.h" 39 #include "content/zygote/zygote_linux.h" 40 #include "crypto/nss_util.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/epoll.h> 48 #include <sys/prctl.h> 49 #include <sys/signal.h> 50 #else 51 #include <signal.h> 52 #endif 53 54 #if defined(ENABLE_WEBRTC) 55 #include "third_party/libjingle/overrides/init_webrtc.h" 56 #endif 57 58 namespace content { 59 60 // See http://code.google.com/p/chromium/wiki/LinuxZygote 61 62 static 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 Zygote::kMagicSandboxIPCDescriptor, 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 100 static 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 138 typedef struct tm* (*LocaltimeFunction)(const time_t* timep); 139 typedef struct tm* (*LocaltimeRFunction)(const time_t* timep, 140 struct tm* result); 141 142 static pthread_once_t g_libc_localtime_funcs_guard = PTHREAD_ONCE_INIT; 143 static LocaltimeFunction g_libc_localtime; 144 static LocaltimeFunction g_libc_localtime64; 145 static LocaltimeRFunction g_libc_localtime_r; 146 static LocaltimeRFunction g_libc_localtime64_r; 147 148 static 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"))) 185 struct tm* localtime_override(const time_t* timep) __asm__ ("localtime"); 186 187 __attribute__ ((__visibility__("default"))) 188 struct 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 return g_libc_localtime(timep); 199 } 200 } 201 202 // Use same trick to override localtime64(), localtime_r() and localtime64_r(). 203 __attribute__ ((__visibility__("default"))) 204 struct tm* localtime64_override(const time_t* timep) __asm__ ("localtime64"); 205 206 __attribute__ ((__visibility__("default"))) 207 struct tm* localtime64_override(const time_t* timep) { 208 if (g_am_zygote_or_renderer) { 209 static struct tm time_struct; 210 static char timezone_string[64]; 211 ProxyLocaltimeCallToBrowser(*timep, &time_struct, timezone_string, 212 sizeof(timezone_string)); 213 return &time_struct; 214 } else { 215 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard, 216 InitLibcLocaltimeFunctions)); 217 return g_libc_localtime64(timep); 218 } 219 } 220 221 __attribute__ ((__visibility__("default"))) 222 struct tm* localtime_r_override(const time_t* timep, 223 struct tm* result) __asm__ ("localtime_r"); 224 225 __attribute__ ((__visibility__("default"))) 226 struct tm* localtime_r_override(const time_t* timep, struct tm* result) { 227 if (g_am_zygote_or_renderer) { 228 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0); 229 return result; 230 } else { 231 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard, 232 InitLibcLocaltimeFunctions)); 233 return g_libc_localtime_r(timep, result); 234 } 235 } 236 237 __attribute__ ((__visibility__("default"))) 238 struct tm* localtime64_r_override(const time_t* timep, 239 struct tm* result) __asm__ ("localtime64_r"); 240 241 __attribute__ ((__visibility__("default"))) 242 struct tm* localtime64_r_override(const time_t* timep, struct tm* result) { 243 if (g_am_zygote_or_renderer) { 244 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0); 245 return result; 246 } else { 247 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard, 248 InitLibcLocaltimeFunctions)); 249 return g_libc_localtime64_r(timep, result); 250 } 251 } 252 253 #if defined(ENABLE_PLUGINS) 254 // Loads the (native) libraries but does not initialize them (i.e., does not 255 // call PPP_InitializeModule). This is needed by the zygote on Linux to get 256 // access to the plugins before entering the sandbox. 257 void PreloadPepperPlugins() { 258 std::vector<PepperPluginInfo> plugins; 259 ComputePepperPluginList(&plugins); 260 for (size_t i = 0; i < plugins.size(); ++i) { 261 if (!plugins[i].is_internal && plugins[i].is_sandboxed) { 262 std::string error; 263 base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path, 264 &error); 265 DLOG_IF(WARNING, !library) << "Unable to load plugin " 266 << plugins[i].path.value() << " " 267 << error; 268 (void)library; // Prevent release-mode warning. 269 } 270 } 271 } 272 #endif 273 274 // This function triggers the static and lazy construction of objects that need 275 // to be created before imposing the sandbox. 276 static void PreSandboxInit() { 277 base::RandUint64(); 278 279 base::SysInfo::MaxSharedMemorySize(); 280 281 // ICU DateFormat class (used in base/time_format.cc) needs to get the 282 // Olson timezone ID by accessing the zoneinfo files on disk. After 283 // TimeZone::createDefault is called once here, the timezone ID is 284 // cached and there's no more need to access the file system. 285 scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault()); 286 287 #if defined(USE_NSS) 288 // NSS libraries are loaded before sandbox is activated. This is to allow 289 // successful initialization of NSS which tries to load extra library files. 290 crypto::LoadNSSLibraries(); 291 #elif defined(USE_OPENSSL) 292 // OpenSSL is intentionally not supported in the sandboxed processes, see 293 // http://crbug.com/99163. If that ever changes we'll likely need to init 294 // OpenSSL here (at least, load the library and error strings). 295 #else 296 // It's possible that another hypothetical crypto stack would not require 297 // pre-sandbox init, but more likely this is just a build configuration error. 298 #error Which SSL library are you using? 299 #endif 300 #if defined(ENABLE_PLUGINS) 301 // Ensure access to the Pepper plugins before the sandbox is turned on. 302 PreloadPepperPlugins(); 303 #endif 304 #if defined(ENABLE_WEBRTC) 305 InitializeWebRtcModule(); 306 #endif 307 } 308 309 // Do nothing here 310 static void SIGCHLDHandler(int signal) { 311 } 312 313 // The current process will become a process reaper like init. 314 // We fork a child that will continue normally, when it dies, we can safely 315 // exit. 316 // We need to be careful we close the magic kZygoteIdFd properly in the parent 317 // before this function returns. 318 static bool CreateInitProcessReaper() { 319 int sync_fds[2]; 320 // We want to use send, so we can't use a pipe 321 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sync_fds)) { 322 LOG(ERROR) << "Failed to create socketpair"; 323 return false; 324 } 325 326 // We use normal fork, not the ForkDelegate in this case since we are not a 327 // true Zygote yet. 328 pid_t child_pid = fork(); 329 if (child_pid == -1) { 330 (void) HANDLE_EINTR(close(sync_fds[0])); 331 (void) HANDLE_EINTR(close(sync_fds[1])); 332 return false; 333 } 334 if (child_pid) { 335 // We are the parent, assuming the role of an init process. 336 // The disposition for SIGCHLD cannot be SIG_IGN or wait() will only return 337 // once all of our childs are dead. Since we're init we need to reap childs 338 // as they come. 339 struct sigaction action; 340 memset(&action, 0, sizeof(action)); 341 action.sa_handler = &SIGCHLDHandler; 342 CHECK(sigaction(SIGCHLD, &action, NULL) == 0); 343 344 (void) HANDLE_EINTR(close(sync_fds[0])); 345 shutdown(sync_fds[1], SHUT_RD); 346 // This "magic" socket must only appear in one process. 347 (void) HANDLE_EINTR(close(kZygoteIdFd)); 348 // Tell the child to continue 349 CHECK(HANDLE_EINTR(send(sync_fds[1], "C", 1, MSG_NOSIGNAL)) == 1); 350 (void) HANDLE_EINTR(close(sync_fds[1])); 351 352 for (;;) { 353 // Loop until we have reaped our one natural child 354 siginfo_t reaped_child_info; 355 int wait_ret = 356 HANDLE_EINTR(waitid(P_ALL, 0, &reaped_child_info, WEXITED)); 357 if (wait_ret) 358 _exit(1); 359 if (reaped_child_info.si_pid == child_pid) { 360 int exit_code = 0; 361 // We're done waiting 362 if (reaped_child_info.si_code == CLD_EXITED) { 363 exit_code = reaped_child_info.si_status; 364 } 365 // Exit with the same exit code as our parent. This is most likely 366 // useless. _exit with 0 if we got signaled. 367 _exit(exit_code); 368 } 369 } 370 } else { 371 // The child needs to wait for the parent to close kZygoteIdFd to avoid a 372 // race condition 373 (void) HANDLE_EINTR(close(sync_fds[1])); 374 shutdown(sync_fds[0], SHUT_WR); 375 char should_continue; 376 int read_ret = HANDLE_EINTR(read(sync_fds[0], &should_continue, 1)); 377 (void) HANDLE_EINTR(close(sync_fds[0])); 378 if (read_ret == 1) 379 return true; 380 else 381 return false; 382 } 383 } 384 385 // This will set the *using_suid_sandbox variable to true if the SUID sandbox 386 // is enabled. This does not necessarily exclude other types of sandboxing. 387 static bool EnterSandbox(sandbox::SetuidSandboxClient* setuid_sandbox, 388 bool* using_suid_sandbox, bool* has_started_new_init) { 389 *using_suid_sandbox = false; 390 *has_started_new_init = false; 391 if (!setuid_sandbox) 392 return false; 393 394 PreSandboxInit(); 395 SkFontConfigInterface::SetGlobal( 396 new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor))->unref(); 397 398 if (setuid_sandbox->IsSuidSandboxChild()) { 399 // Use the SUID sandbox. This still allows the seccomp sandbox to 400 // be enabled by the process later. 401 *using_suid_sandbox = true; 402 403 if (!setuid_sandbox->IsSuidSandboxUpToDate()) { 404 LOG(WARNING) << "You are using a wrong version of the setuid binary!\n" 405 "Please read " 406 "https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment." 407 "\n\n"; 408 } 409 410 if (!setuid_sandbox->ChrootMe()) 411 return false; 412 413 if (getpid() == 1) { 414 // The setuid sandbox has created a new PID namespace and we need 415 // to assume the role of init. 416 if (!CreateInitProcessReaper()) { 417 LOG(ERROR) << "Error creating an init process to reap zombies"; 418 return false; 419 } 420 *has_started_new_init = true; 421 } 422 423 #if !defined(OS_OPENBSD) 424 // Previously, we required that the binary be non-readable. This causes the 425 // kernel to mark the process as non-dumpable at startup. The thinking was 426 // that, although we were putting the renderers into a PID namespace (with 427 // the SUID sandbox), they would nonetheless be in the /same/ PID 428 // namespace. So they could ptrace each other unless they were non-dumpable. 429 // 430 // If the binary was readable, then there would be a window between process 431 // startup and the point where we set the non-dumpable flag in which a 432 // compromised renderer could ptrace attach. 433 // 434 // However, now that we have a zygote model, only the (trusted) zygote 435 // exists at this point and we can set the non-dumpable flag which is 436 // inherited by all our renderer children. 437 // 438 // Note: a non-dumpable process can't be debugged. To debug sandbox-related 439 // issues, one can specify --allow-sandbox-debugging to let the process be 440 // dumpable. 441 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 442 if (!command_line.HasSwitch(switches::kAllowSandboxDebugging)) { 443 prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); 444 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { 445 LOG(ERROR) << "Failed to set non-dumpable flag"; 446 return false; 447 } 448 } 449 #endif 450 } 451 452 return true; 453 } 454 455 bool ZygoteMain(const MainFunctionParams& params, 456 ZygoteForkDelegate* forkdelegate) { 457 g_am_zygote_or_renderer = true; 458 sandbox::InitLibcUrandomOverrides(); 459 460 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); 461 // This will pre-initialize the various sandboxes that need it. 462 linux_sandbox->PreinitializeSandbox(); 463 464 sandbox::SetuidSandboxClient* setuid_sandbox = 465 linux_sandbox->setuid_sandbox_client(); 466 467 if (forkdelegate != NULL) { 468 VLOG(1) << "ZygoteMain: initializing fork delegate"; 469 forkdelegate->Init(Zygote::kMagicSandboxIPCDescriptor); 470 } else { 471 VLOG(1) << "ZygoteMain: fork delegate is NULL"; 472 } 473 474 // Turn on the sandbox. 475 bool using_suid_sandbox = false; 476 bool has_started_new_init = false; 477 478 if (!EnterSandbox(setuid_sandbox, 479 &using_suid_sandbox, 480 &has_started_new_init)) { 481 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " 482 << errno << ")"; 483 return false; 484 } 485 486 if (setuid_sandbox->IsInNewPIDNamespace() && !has_started_new_init) { 487 LOG(ERROR) << "The SUID sandbox created a new PID namespace but Zygote " 488 "is not the init process. Please, make sure the SUID " 489 "binary is up to date."; 490 } 491 492 int sandbox_flags = linux_sandbox->GetStatus(); 493 494 Zygote zygote(sandbox_flags, forkdelegate); 495 // This function call can return multiple times, once per fork(). 496 return zygote.ProcessRequests(); 497 } 498 499 } // namespace content 500