| OLD | NEW |
| 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 "content/zygote/zygote_main.h" | 5 #include "content/zygote/zygote_main.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <pthread.h> | 9 #include <pthread.h> |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 #include <sys/prctl.h> | 48 #include <sys/prctl.h> |
| 49 #include <sys/signal.h> | 49 #include <sys/signal.h> |
| 50 #else | 50 #else |
| 51 #include <signal.h> | 51 #include <signal.h> |
| 52 #endif | 52 #endif |
| 53 | 53 |
| 54 namespace content { | 54 namespace content { |
| 55 | 55 |
| 56 // See http://code.google.com/p/chromium/wiki/LinuxZygote | 56 // See http://code.google.com/p/chromium/wiki/LinuxZygote |
| 57 | 57 |
| 58 // With SELinux we can carve out a precise sandbox, so we don't have to play | |
| 59 // with intercepting libc calls. | |
| 60 #if !defined(CHROMIUM_SELINUX) | |
| 61 | |
| 62 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, | 58 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, |
| 63 char* timezone_out, | 59 char* timezone_out, |
| 64 size_t timezone_out_len) { | 60 size_t timezone_out_len) { |
| 65 Pickle request; | 61 Pickle request; |
| 66 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME); | 62 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME); |
| 67 request.WriteString( | 63 request.WriteString( |
| 68 std::string(reinterpret_cast<char*>(&input), sizeof(input))); | 64 std::string(reinterpret_cast<char*>(&input), sizeof(input))); |
| 69 | 65 |
| 70 uint8_t reply_buf[512]; | 66 uint8_t reply_buf[512]; |
| 71 const ssize_t r = UnixDomainSocket::SendRecvMsg( | 67 const ssize_t r = UnixDomainSocket::SendRecvMsg( |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 if (g_am_zygote_or_renderer) { | 239 if (g_am_zygote_or_renderer) { |
| 244 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0); | 240 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0); |
| 245 return result; | 241 return result; |
| 246 } else { | 242 } else { |
| 247 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard, | 243 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard, |
| 248 InitLibcLocaltimeFunctions)); | 244 InitLibcLocaltimeFunctions)); |
| 249 return g_libc_localtime64_r(timep, result); | 245 return g_libc_localtime64_r(timep, result); |
| 250 } | 246 } |
| 251 } | 247 } |
| 252 | 248 |
| 253 #endif // !CHROMIUM_SELINUX | |
| 254 | |
| 255 // This function triggers the static and lazy construction of objects that need | 249 // This function triggers the static and lazy construction of objects that need |
| 256 // to be created before imposing the sandbox. | 250 // to be created before imposing the sandbox. |
| 257 static void PreSandboxInit() { | 251 static void PreSandboxInit() { |
| 258 base::RandUint64(); | 252 base::RandUint64(); |
| 259 | 253 |
| 260 base::SysInfo::MaxSharedMemorySize(); | 254 base::SysInfo::MaxSharedMemorySize(); |
| 261 | 255 |
| 262 // ICU DateFormat class (used in base/time_format.cc) needs to get the | 256 // ICU DateFormat class (used in base/time_format.cc) needs to get the |
| 263 // Olson timezone ID by accessing the zoneinfo files on disk. After | 257 // Olson timezone ID by accessing the zoneinfo files on disk. After |
| 264 // TimeZone::createDefault is called once here, the timezone ID is | 258 // TimeZone::createDefault is called once here, the timezone ID is |
| (...skipping 15 matching lines...) Expand all Loading... |
| 280 #endif | 274 #endif |
| 281 #if defined(ENABLE_PLUGINS) | 275 #if defined(ENABLE_PLUGINS) |
| 282 // Ensure access to the Pepper plugins before the sandbox is turned on. | 276 // Ensure access to the Pepper plugins before the sandbox is turned on. |
| 283 PepperPluginRegistry::PreloadModules(); | 277 PepperPluginRegistry::PreloadModules(); |
| 284 #endif | 278 #endif |
| 285 #if defined(ENABLE_WEBRTC) | 279 #if defined(ENABLE_WEBRTC) |
| 286 InitializeWebRtcModule(); | 280 InitializeWebRtcModule(); |
| 287 #endif | 281 #endif |
| 288 } | 282 } |
| 289 | 283 |
| 290 #if !defined(CHROMIUM_SELINUX) | |
| 291 // Do nothing here | 284 // Do nothing here |
| 292 static void SIGCHLDHandler(int signal) { | 285 static void SIGCHLDHandler(int signal) { |
| 293 } | 286 } |
| 294 | 287 |
| 295 // The current process will become a process reaper like init. | 288 // The current process will become a process reaper like init. |
| 296 // We fork a child that will continue normally, when it dies, we can safely | 289 // We fork a child that will continue normally, when it dies, we can safely |
| 297 // exit. | 290 // exit. |
| 298 // We need to be careful we close the magic kZygoteIdFd properly in the parent | 291 // We need to be careful we close the magic kZygoteIdFd properly in the parent |
| 299 // before this function returns. | 292 // before this function returns. |
| 300 static bool CreateInitProcessReaper() { | 293 static bool CreateInitProcessReaper() { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { | 419 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { |
| 427 LOG(ERROR) << "Failed to set non-dumpable flag"; | 420 LOG(ERROR) << "Failed to set non-dumpable flag"; |
| 428 return false; | 421 return false; |
| 429 } | 422 } |
| 430 } | 423 } |
| 431 #endif | 424 #endif |
| 432 } | 425 } |
| 433 | 426 |
| 434 return true; | 427 return true; |
| 435 } | 428 } |
| 436 #else // CHROMIUM_SELINUX | |
| 437 | |
| 438 static bool EnterSandbox(sandbox::SetuidSandboxClient* setuid_sandbox, | |
| 439 bool* using_suid_sandbox, bool* has_started_new_init) { | |
| 440 *using_suid_sandbox = false; | |
| 441 *has_started_new_init = false; | |
| 442 | |
| 443 if (!setuid_sandbox) | |
| 444 return false; | |
| 445 | |
| 446 PreSandboxInit(); | |
| 447 SkFontConfigInterface::SetGlobal( | |
| 448 new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor))->unref(); | |
| 449 return true; | |
| 450 } | |
| 451 | |
| 452 #endif // CHROMIUM_SELINUX | |
| 453 | 429 |
| 454 bool ZygoteMain(const MainFunctionParams& params, | 430 bool ZygoteMain(const MainFunctionParams& params, |
| 455 ZygoteForkDelegate* forkdelegate) { | 431 ZygoteForkDelegate* forkdelegate) { |
| 456 #if !defined(CHROMIUM_SELINUX) | |
| 457 g_am_zygote_or_renderer = true; | 432 g_am_zygote_or_renderer = true; |
| 458 sandbox::InitLibcUrandomOverrides(); | 433 sandbox::InitLibcUrandomOverrides(); |
| 459 #endif | |
| 460 | 434 |
| 461 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); | 435 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); |
| 462 // This will pre-initialize the various sandboxes that need it. | 436 // This will pre-initialize the various sandboxes that need it. |
| 463 linux_sandbox->PreinitializeSandbox(); | 437 linux_sandbox->PreinitializeSandbox(); |
| 464 | 438 |
| 465 sandbox::SetuidSandboxClient* setuid_sandbox = | 439 sandbox::SetuidSandboxClient* setuid_sandbox = |
| 466 linux_sandbox->setuid_sandbox_client(); | 440 linux_sandbox->setuid_sandbox_client(); |
| 467 | 441 |
| 468 if (forkdelegate != NULL) { | 442 if (forkdelegate != NULL) { |
| 469 VLOG(1) << "ZygoteMain: initializing fork delegate"; | 443 VLOG(1) << "ZygoteMain: initializing fork delegate"; |
| 470 forkdelegate->Init(Zygote::kMagicSandboxIPCDescriptor); | 444 forkdelegate->Init(Zygote::kMagicSandboxIPCDescriptor); |
| 471 } else { | 445 } else { |
| 472 VLOG(1) << "ZygoteMain: fork delegate is NULL"; | 446 VLOG(1) << "ZygoteMain: fork delegate is NULL"; |
| 473 } | 447 } |
| 474 | 448 |
| 475 // Turn on the SELinux or SUID sandbox. | 449 // Turn on the sandbox. |
| 476 bool using_suid_sandbox = false; | 450 bool using_suid_sandbox = false; |
| 477 bool has_started_new_init = false; | 451 bool has_started_new_init = false; |
| 478 | 452 |
| 479 if (!EnterSandbox(setuid_sandbox, | 453 if (!EnterSandbox(setuid_sandbox, |
| 480 &using_suid_sandbox, | 454 &using_suid_sandbox, |
| 481 &has_started_new_init)) { | 455 &has_started_new_init)) { |
| 482 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " | 456 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " |
| 483 << errno << ")"; | 457 << errno << ")"; |
| 484 return false; | 458 return false; |
| 485 } | 459 } |
| 486 | 460 |
| 487 if (setuid_sandbox->IsInNewPIDNamespace() && !has_started_new_init) { | 461 if (setuid_sandbox->IsInNewPIDNamespace() && !has_started_new_init) { |
| 488 LOG(ERROR) << "The SUID sandbox created a new PID namespace but Zygote " | 462 LOG(ERROR) << "The SUID sandbox created a new PID namespace but Zygote " |
| 489 "is not the init process. Please, make sure the SUID " | 463 "is not the init process. Please, make sure the SUID " |
| 490 "binary is up to date."; | 464 "binary is up to date."; |
| 491 } | 465 } |
| 492 | 466 |
| 493 int sandbox_flags = linux_sandbox->GetStatus(); | 467 int sandbox_flags = linux_sandbox->GetStatus(); |
| 494 | 468 |
| 495 Zygote zygote(sandbox_flags, forkdelegate); | 469 Zygote zygote(sandbox_flags, forkdelegate); |
| 496 // This function call can return multiple times, once per fork(). | 470 // This function call can return multiple times, once per fork(). |
| 497 return zygote.ProcessRequests(); | 471 return zygote.ProcessRequests(); |
| 498 } | 472 } |
| 499 | 473 |
| 500 } // namespace content | 474 } // namespace content |
| OLD | NEW |