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 16 matching lines...) Expand all Loading... |
27 #include "base/posix/eintr_wrapper.h" | 27 #include "base/posix/eintr_wrapper.h" |
28 #include "base/posix/global_descriptors.h" | 28 #include "base/posix/global_descriptors.h" |
29 #include "base/posix/unix_domain_socket_linux.h" | 29 #include "base/posix/unix_domain_socket_linux.h" |
30 #include "base/process/kill.h" | 30 #include "base/process/kill.h" |
31 #include "base/process/process_handle.h" | 31 #include "base/process/process_handle.h" |
32 #include "base/rand_util.h" | 32 #include "base/rand_util.h" |
33 #include "components/nacl/common/nacl_switches.h" | 33 #include "components/nacl/common/nacl_switches.h" |
34 #include "components/nacl/loader/nacl_listener.h" | 34 #include "components/nacl/loader/nacl_listener.h" |
35 #include "components/nacl/loader/nacl_sandbox_linux.h" | 35 #include "components/nacl/loader/nacl_sandbox_linux.h" |
36 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h" | 36 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h" |
| 37 #include "content/public/common/content_descriptors.h" |
37 #include "content/public/common/zygote_fork_delegate_linux.h" | 38 #include "content/public/common/zygote_fork_delegate_linux.h" |
38 #include "crypto/nss_util.h" | 39 #include "crypto/nss_util.h" |
39 #include "ipc/ipc_descriptors.h" | 40 #include "ipc/ipc_descriptors.h" |
40 #include "ipc/ipc_switches.h" | 41 #include "ipc/ipc_switches.h" |
41 #include "sandbox/linux/services/credentials.h" | 42 #include "sandbox/linux/services/credentials.h" |
42 #include "sandbox/linux/services/libc_urandom_override.h" | 43 #include "sandbox/linux/services/libc_urandom_override.h" |
43 #include "sandbox/linux/services/thread_helpers.h" | 44 #include "sandbox/linux/services/thread_helpers.h" |
44 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" | 45 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" |
45 | 46 |
46 namespace { | 47 namespace { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 } | 107 } |
107 } else { | 108 } else { |
108 const bool bpf_sandbox_initialized = InitializeBPFSandbox(); | 109 const bool bpf_sandbox_initialized = InitializeBPFSandbox(); |
109 if (!bpf_sandbox_initialized) { | 110 if (!bpf_sandbox_initialized) { |
110 LOG(ERROR) << "Could not initialize NaCl's second " | 111 LOG(ERROR) << "Could not initialize NaCl's second " |
111 << "layer sandbox (seccomp-bpf) for SFI mode."; | 112 << "layer sandbox (seccomp-bpf) for SFI mode."; |
112 } | 113 } |
113 } | 114 } |
114 } | 115 } |
115 | 116 |
| 117 // Replace |file_descriptor| with the reading end of a closed pipe. |
| 118 void ReplaceFDWithDummy(int file_descriptor) { |
| 119 // Make sure that file_descriptor is an open descriptor. |
| 120 PCHECK(-1 != fcntl(file_descriptor, F_GETFD, 0)); |
| 121 int pipefd[2]; |
| 122 PCHECK(0 == pipe(pipefd)); |
| 123 PCHECK(-1 != dup2(pipefd[0], file_descriptor)); |
| 124 PCHECK(0 == IGNORE_EINTR(close(pipefd[0]))); |
| 125 PCHECK(0 == IGNORE_EINTR(close(pipefd[1]))); |
| 126 } |
| 127 |
116 // The child must mimic the behavior of zygote_main_linux.cc on the child | 128 // The child must mimic the behavior of zygote_main_linux.cc on the child |
117 // side of the fork. See zygote_main_linux.cc:HandleForkRequest from | 129 // side of the fork. See zygote_main_linux.cc:HandleForkRequest from |
118 // if (!child) { | 130 // if (!child) { |
119 void BecomeNaClLoader(const std::vector<int>& child_fds, | 131 void BecomeNaClLoader(const std::vector<int>& child_fds, |
120 const NaClLoaderSystemInfo& system_info, | 132 const NaClLoaderSystemInfo& system_info, |
121 bool uses_nonsfi_mode) { | 133 bool uses_nonsfi_mode) { |
122 VLOG(1) << "NaCl loader: setting up IPC descriptor"; | 134 VLOG(1) << "NaCl loader: setting up IPC descriptor"; |
123 // don't need zygote FD any more | 135 // Close or shutdown IPC channels that we don't need anymore. |
124 if (IGNORE_EINTR(close(kNaClZygoteDescriptor)) != 0) | 136 PCHECK(0 == IGNORE_EINTR(close(kNaClZygoteDescriptor))); |
125 LOG(ERROR) << "close(kNaClZygoteDescriptor) failed."; | 137 // In Non-SFI mode, it's important to close any non-expected IPC channels. |
| 138 if (uses_nonsfi_mode) { |
| 139 // The low-level kSandboxIPCChannel is used by renderers and NaCl for |
| 140 // various operations. See the LinuxSandbox::METHOD_* methods. NaCl uses |
| 141 // LinuxSandbox::METHOD_MAKE_SHARED_MEMORY_SEGMENT in SFI mode, so this |
| 142 // should only be closed in Non-SFI mode. |
| 143 // This file descriptor is insidiously used by a number of APIs. Closing it |
| 144 // could lead to difficult to debug issues. Instead of closing it, replace |
| 145 // it with a dummy. |
| 146 const int sandbox_ipc_channel = |
| 147 base::GlobalDescriptors::kBaseDescriptor + kSandboxIPCChannel; |
| 148 |
| 149 ReplaceFDWithDummy(sandbox_ipc_channel); |
| 150 } |
| 151 |
126 InitializeLayerTwoSandbox(uses_nonsfi_mode); | 152 InitializeLayerTwoSandbox(uses_nonsfi_mode); |
127 base::GlobalDescriptors::GetInstance()->Set( | 153 base::GlobalDescriptors::GetInstance()->Set( |
128 kPrimaryIPCChannel, | 154 kPrimaryIPCChannel, |
129 child_fds[content::ZygoteForkDelegate::kBrowserFDIndex]); | 155 child_fds[content::ZygoteForkDelegate::kBrowserFDIndex]); |
130 | 156 |
131 base::MessageLoopForIO main_message_loop; | 157 base::MessageLoopForIO main_message_loop; |
132 NaClListener listener; | 158 NaClListener listener; |
133 listener.set_uses_nonsfi_mode(uses_nonsfi_mode); | 159 listener.set_uses_nonsfi_mode(uses_nonsfi_mode); |
134 listener.set_prereserved_sandbox_size(system_info.prereserved_sandbox_size); | 160 listener.set_prereserved_sandbox_size(system_info.prereserved_sandbox_size); |
135 listener.set_number_of_cores(system_info.number_of_cores); | 161 listener.set_number_of_cores(system_info.number_of_cores); |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 // Now handle requests from the Zygote. | 489 // Now handle requests from the Zygote. |
464 while (true) { | 490 while (true) { |
465 bool request_handled = HandleZygoteRequest(kNaClZygoteDescriptor, | 491 bool request_handled = HandleZygoteRequest(kNaClZygoteDescriptor, |
466 system_info); | 492 system_info); |
467 // Do not turn this into a CHECK() without thinking about robustness | 493 // Do not turn this into a CHECK() without thinking about robustness |
468 // against malicious IPC requests. | 494 // against malicious IPC requests. |
469 DCHECK(request_handled); | 495 DCHECK(request_handled); |
470 } | 496 } |
471 NOTREACHED(); | 497 NOTREACHED(); |
472 } | 498 } |
OLD | NEW |