| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 // A mini-zygote specifically for Native Client. | 5 // A mini-zygote specifically for Native Client. |
| 6 | 6 |
| 7 #include "components/nacl/loader/nacl_helper_linux.h" | 7 #include "components/nacl/loader/nacl_helper_linux.h" |
| 8 | 8 |
| 9 #include <errno.h> | 9 #include <errno.h> |
| 10 #include <fcntl.h> | 10 #include <fcntl.h> |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 PCHECK(0 == IGNORE_EINTR(close(pipefd[1]))); | 68 PCHECK(0 == IGNORE_EINTR(close(pipefd[1]))); |
| 69 } | 69 } |
| 70 | 70 |
| 71 // The child must mimic the behavior of zygote_main_linux.cc on the child | 71 // The child must mimic the behavior of zygote_main_linux.cc on the child |
| 72 // side of the fork. See zygote_main_linux.cc:HandleForkRequest from | 72 // side of the fork. See zygote_main_linux.cc:HandleForkRequest from |
| 73 // if (!child) { | 73 // if (!child) { |
| 74 void BecomeNaClLoader(base::ScopedFD browser_fd, | 74 void BecomeNaClLoader(base::ScopedFD browser_fd, |
| 75 const NaClLoaderSystemInfo& system_info, | 75 const NaClLoaderSystemInfo& system_info, |
| 76 bool uses_nonsfi_mode, | 76 bool uses_nonsfi_mode, |
| 77 nacl::NaClSandbox* nacl_sandbox) { | 77 nacl::NaClSandbox* nacl_sandbox) { |
| 78 #if !defined(OS_NACL_NONSFI) | |
| 79 // Currently sandbox is disabled for nacl_helper_nonsfi. | |
| 80 // TODO(hidehiko): Enable sandbox. | |
| 81 DCHECK(nacl_sandbox); | 78 DCHECK(nacl_sandbox); |
| 82 #endif | |
| 83 VLOG(1) << "NaCl loader: setting up IPC descriptor"; | 79 VLOG(1) << "NaCl loader: setting up IPC descriptor"; |
| 84 // Close or shutdown IPC channels that we don't need anymore. | 80 // Close or shutdown IPC channels that we don't need anymore. |
| 85 PCHECK(0 == IGNORE_EINTR(close(kNaClZygoteDescriptor))); | 81 PCHECK(0 == IGNORE_EINTR(close(kNaClZygoteDescriptor))); |
| 86 // In Non-SFI mode, it's important to close any non-expected IPC channels. | 82 // In Non-SFI mode, it's important to close any non-expected IPC channels. |
| 87 if (uses_nonsfi_mode) { | 83 if (uses_nonsfi_mode) { |
| 88 // The low-level kSandboxIPCChannel is used by renderers and NaCl for | 84 // The low-level kSandboxIPCChannel is used by renderers and NaCl for |
| 89 // various operations. See the LinuxSandbox::METHOD_* methods. NaCl uses | 85 // various operations. See the LinuxSandbox::METHOD_* methods. NaCl uses |
| 90 // LinuxSandbox::METHOD_MAKE_SHARED_MEMORY_SEGMENT in SFI mode, so this | 86 // LinuxSandbox::METHOD_MAKE_SHARED_MEMORY_SEGMENT in SFI mode, so this |
| 91 // should only be closed in Non-SFI mode. | 87 // should only be closed in Non-SFI mode. |
| 92 // This file descriptor is insidiously used by a number of APIs. Closing it | 88 // This file descriptor is insidiously used by a number of APIs. Closing it |
| (...skipping 10 matching lines...) Expand all Loading... |
| 103 #else | 99 #else |
| 104 nacl::nonsfi::InitializeSignalHandler(); | 100 nacl::nonsfi::InitializeSignalHandler(); |
| 105 #endif | 101 #endif |
| 106 } | 102 } |
| 107 | 103 |
| 108 // Always ignore SIGPIPE, for consistency with other Chrome processes and | 104 // Always ignore SIGPIPE, for consistency with other Chrome processes and |
| 109 // because some IPC code, such as sync_socket_posix.cc, requires this. | 105 // because some IPC code, such as sync_socket_posix.cc, requires this. |
| 110 // We do this before seccomp-bpf is initialized. | 106 // We do this before seccomp-bpf is initialized. |
| 111 PCHECK(signal(SIGPIPE, SIG_IGN) != SIG_ERR); | 107 PCHECK(signal(SIGPIPE, SIG_IGN) != SIG_ERR); |
| 112 | 108 |
| 113 #if !defined(OS_NACL_NONSFI) | |
| 114 // Currently sandbox is disabled for nacl_helper_nonsfi. | |
| 115 // TODO(hidehiko): Enable sandbox. | |
| 116 // Finish layer-1 sandbox initialization and initialize the layer-2 sandbox. | 109 // Finish layer-1 sandbox initialization and initialize the layer-2 sandbox. |
| 117 CHECK(!nacl_sandbox->HasOpenDirectory()); | 110 CHECK(!nacl_sandbox->HasOpenDirectory()); |
| 111 #if !defined(OS_NACL_NONSFI) |
| 112 // Currently Layer-two sandbox is not yet supported on nacl_helper_nonsfi. |
| 113 // TODO(hidehiko): Enable the sandbox. |
| 118 nacl_sandbox->InitializeLayerTwoSandbox(uses_nonsfi_mode); | 114 nacl_sandbox->InitializeLayerTwoSandbox(uses_nonsfi_mode); |
| 115 #endif |
| 119 nacl_sandbox->SealLayerOneSandbox(); | 116 nacl_sandbox->SealLayerOneSandbox(); |
| 120 nacl_sandbox->CheckSandboxingStateWithPolicy(); | 117 nacl_sandbox->CheckSandboxingStateWithPolicy(); |
| 121 #endif | |
| 122 | 118 |
| 123 base::GlobalDescriptors::GetInstance()->Set(kPrimaryIPCChannel, | 119 base::GlobalDescriptors::GetInstance()->Set(kPrimaryIPCChannel, |
| 124 browser_fd.release()); | 120 browser_fd.release()); |
| 125 | 121 |
| 126 base::MessageLoopForIO main_message_loop; | 122 base::MessageLoopForIO main_message_loop; |
| 127 #if defined(OS_NACL_NONSFI) | 123 #if defined(OS_NACL_NONSFI) |
| 128 CHECK(uses_nonsfi_mode); | 124 CHECK(uses_nonsfi_mode); |
| 129 nacl::nonsfi::NonSfiListener listener; | 125 nacl::nonsfi::NonSfiListener listener; |
| 130 listener.Listen(); | 126 listener.Listen(); |
| 131 #else | 127 #else |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 | 290 |
| 295 // Read a request from the Zygote from |zygote_ipc_fd| and handle it. | 291 // Read a request from the Zygote from |zygote_ipc_fd| and handle it. |
| 296 // Die on EOF from |zygote_ipc_fd|. | 292 // Die on EOF from |zygote_ipc_fd|. |
| 297 bool HandleZygoteRequest(int zygote_ipc_fd, | 293 bool HandleZygoteRequest(int zygote_ipc_fd, |
| 298 const NaClLoaderSystemInfo& system_info, | 294 const NaClLoaderSystemInfo& system_info, |
| 299 nacl::NaClSandbox* nacl_sandbox) { | 295 nacl::NaClSandbox* nacl_sandbox) { |
| 300 ScopedVector<base::ScopedFD> fds; | 296 ScopedVector<base::ScopedFD> fds; |
| 301 char buf[kNaClMaxIPCMessageLength]; | 297 char buf[kNaClMaxIPCMessageLength]; |
| 302 const ssize_t msglen = UnixDomainSocket::RecvMsg(zygote_ipc_fd, | 298 const ssize_t msglen = UnixDomainSocket::RecvMsg(zygote_ipc_fd, |
| 303 &buf, sizeof(buf), &fds); | 299 &buf, sizeof(buf), &fds); |
| 304 #if !defined(OS_NACL_NONSFI) | |
| 305 // Currently sandbox is disabled for nacl_helper_nonsfi. | |
| 306 // TODO(hidehiko): Enable sandbox. | |
| 307 // If the Zygote has started handling requests, we should be sandboxed via | 300 // If the Zygote has started handling requests, we should be sandboxed via |
| 308 // the setuid sandbox. | 301 // the setuid sandbox. |
| 309 if (!nacl_sandbox->layer_one_enabled()) { | 302 if (!nacl_sandbox->layer_one_enabled()) { |
| 310 LOG(ERROR) << "NaCl helper process running without a sandbox!\n" | 303 LOG(ERROR) << "NaCl helper process running without a sandbox!\n" |
| 311 << "Most likely you need to configure your SUID sandbox " | 304 << "Most likely you need to configure your SUID sandbox " |
| 312 << "correctly"; | 305 << "correctly"; |
| 313 } | 306 } |
| 314 #endif | |
| 315 if (msglen == 0 || (msglen == -1 && errno == ECONNRESET)) { | 307 if (msglen == 0 || (msglen == -1 && errno == ECONNRESET)) { |
| 316 // EOF from the browser. Goodbye! | 308 // EOF from the browser. Goodbye! |
| 317 _exit(0); | 309 _exit(0); |
| 318 } | 310 } |
| 319 if (msglen < 0) { | 311 if (msglen < 0) { |
| 320 PLOG(ERROR) << "nacl_helper: receive from zygote failed"; | 312 PLOG(ERROR) << "nacl_helper: receive from zygote failed"; |
| 321 return false; | 313 return false; |
| 322 } | 314 } |
| 323 | 315 |
| 324 Pickle read_pickle(buf, msglen); | 316 Pickle read_pickle(buf, msglen); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 // These are not used by nacl_helper_nonsfi. | 450 // These are not used by nacl_helper_nonsfi. |
| 459 CheckReservedAtZero(), | 451 CheckReservedAtZero(), |
| 460 sysconf(_SC_NPROCESSORS_ONLN) | 452 sysconf(_SC_NPROCESSORS_ONLN) |
| 461 #endif | 453 #endif |
| 462 }; | 454 }; |
| 463 | 455 |
| 464 #if !defined(OS_NACL_NONSFI) | 456 #if !defined(OS_NACL_NONSFI) |
| 465 CheckRDebug(argv[0]); | 457 CheckRDebug(argv[0]); |
| 466 #endif | 458 #endif |
| 467 | 459 |
| 468 #if defined(OS_NACL_NONSFI) | |
| 469 // Currently sandbox is disabled for nacl_helper_nonsfi. | |
| 470 // TODO(hidehiko): Enable sandbox. | |
| 471 scoped_ptr<nacl::NaClSandbox> nacl_sandbox; | |
| 472 #else | |
| 473 scoped_ptr<nacl::NaClSandbox> nacl_sandbox(new nacl::NaClSandbox); | 460 scoped_ptr<nacl::NaClSandbox> nacl_sandbox(new nacl::NaClSandbox); |
| 474 // Make sure that the early initialization did not start any spurious | 461 // Make sure that the early initialization did not start any spurious |
| 475 // threads. | 462 // threads. |
| 476 #if !defined(THREAD_SANITIZER) | 463 #if !defined(THREAD_SANITIZER) |
| 477 CHECK(nacl_sandbox->IsSingleThreaded()); | 464 CHECK(nacl_sandbox->IsSingleThreaded()); |
| 478 #endif | 465 #endif |
| 479 | 466 |
| 480 const bool is_init_process = 1 == getpid(); | 467 const bool is_init_process = 1 == getpid(); |
| 481 nacl_sandbox->InitializeLayerOneSandbox(); | 468 nacl_sandbox->InitializeLayerOneSandbox(); |
| 482 CHECK_EQ(is_init_process, nacl_sandbox->layer_one_enabled()); | 469 CHECK_EQ(is_init_process, nacl_sandbox->layer_one_enabled()); |
| 483 #endif // defined(OS_NACL_NONSFI) | |
| 484 | 470 |
| 485 const std::vector<int> empty; | 471 const std::vector<int> empty; |
| 486 // Send the zygote a message to let it know we are ready to help | 472 // Send the zygote a message to let it know we are ready to help |
| 487 if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor, | 473 if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor, |
| 488 kNaClHelperStartupAck, | 474 kNaClHelperStartupAck, |
| 489 sizeof(kNaClHelperStartupAck), empty)) { | 475 sizeof(kNaClHelperStartupAck), empty)) { |
| 490 LOG(ERROR) << "*** send() to zygote failed"; | 476 LOG(ERROR) << "*** send() to zygote failed"; |
| 491 } | 477 } |
| 492 | 478 |
| 493 // Now handle requests from the Zygote. | 479 // Now handle requests from the Zygote. |
| 494 while (true) { | 480 while (true) { |
| 495 bool request_handled = HandleZygoteRequest( | 481 bool request_handled = HandleZygoteRequest( |
| 496 kNaClZygoteDescriptor, system_info, nacl_sandbox.get()); | 482 kNaClZygoteDescriptor, system_info, nacl_sandbox.get()); |
| 497 // Do not turn this into a CHECK() without thinking about robustness | 483 // Do not turn this into a CHECK() without thinking about robustness |
| 498 // against malicious IPC requests. | 484 // against malicious IPC requests. |
| 499 DCHECK(request_handled); | 485 DCHECK(request_handled); |
| 500 } | 486 } |
| 501 NOTREACHED(); | 487 NOTREACHED(); |
| 502 } | 488 } |
| OLD | NEW |