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 |