Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: components/nacl/loader/nacl_helper_linux.cc

Issue 1508213002: Replace ScopedVector<ScopedFD> with std::vector<ScopedFD> (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: danakj feedback Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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>
11 #include <signal.h> 11 #include <signal.h>
12 #include <stdio.h> 12 #include <stdio.h>
13 #include <stdlib.h> 13 #include <stdlib.h>
14 #include <sys/socket.h> 14 #include <sys/socket.h>
15 #include <sys/stat.h> 15 #include <sys/stat.h>
16 #include <sys/types.h> 16 #include <sys/types.h>
17 17
18 #include <string> 18 #include <string>
19 #include <utility>
19 #include <vector> 20 #include <vector>
20 21
21 #include "base/at_exit.h" 22 #include "base/at_exit.h"
22 #include "base/command_line.h" 23 #include "base/command_line.h"
23 #include "base/files/scoped_file.h" 24 #include "base/files/scoped_file.h"
24 #include "base/logging.h" 25 #include "base/logging.h"
25 #include "base/memory/scoped_ptr.h" 26 #include "base/memory/scoped_ptr.h"
26 #include "base/memory/scoped_vector.h"
27 #include "base/message_loop/message_loop.h" 27 #include "base/message_loop/message_loop.h"
28 #include "base/posix/eintr_wrapper.h" 28 #include "base/posix/eintr_wrapper.h"
29 #include "base/posix/global_descriptors.h" 29 #include "base/posix/global_descriptors.h"
30 #include "base/posix/unix_domain_socket_linux.h" 30 #include "base/posix/unix_domain_socket_linux.h"
31 #include "base/process/kill.h" 31 #include "base/process/kill.h"
32 #include "base/process/process_handle.h" 32 #include "base/process/process_handle.h"
33 #include "base/rand_util.h" 33 #include "base/rand_util.h"
34 #include "components/nacl/common/nacl_switches.h" 34 #include "components/nacl/common/nacl_switches.h"
35 #include "components/nacl/loader/sandbox_linux/nacl_sandbox_linux.h" 35 #include "components/nacl/loader/sandbox_linux/nacl_sandbox_linux.h"
36 #include "content/public/common/content_descriptors.h" 36 #include "content/public/common/content_descriptors.h"
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 CHECK(!uses_nonsfi_mode); 125 CHECK(!uses_nonsfi_mode);
126 NaClListener listener; 126 NaClListener listener;
127 listener.set_prereserved_sandbox_size(system_info.prereserved_sandbox_size); 127 listener.set_prereserved_sandbox_size(system_info.prereserved_sandbox_size);
128 listener.set_number_of_cores(system_info.number_of_cores); 128 listener.set_number_of_cores(system_info.number_of_cores);
129 listener.Listen(); 129 listener.Listen();
130 #endif 130 #endif
131 _exit(0); 131 _exit(0);
132 } 132 }
133 133
134 // Start the NaCl loader in a child created by the NaCl loader Zygote. 134 // Start the NaCl loader in a child created by the NaCl loader Zygote.
135 void ChildNaClLoaderInit(ScopedVector<base::ScopedFD> child_fds, 135 void ChildNaClLoaderInit(std::vector<base::ScopedFD> child_fds,
136 const NaClLoaderSystemInfo& system_info, 136 const NaClLoaderSystemInfo& system_info,
137 bool uses_nonsfi_mode, 137 bool uses_nonsfi_mode,
138 nacl::NaClSandbox* nacl_sandbox, 138 nacl::NaClSandbox* nacl_sandbox,
139 const std::string& channel_id) { 139 const std::string& channel_id) {
140 DCHECK(child_fds.size() > 140 DCHECK(child_fds.size() >
141 std::max(content::ZygoteForkDelegate::kPIDOracleFDIndex, 141 std::max(content::ZygoteForkDelegate::kPIDOracleFDIndex,
142 content::ZygoteForkDelegate::kBrowserFDIndex)); 142 content::ZygoteForkDelegate::kBrowserFDIndex));
143 143
144 // Ping the PID oracle socket. 144 // Ping the PID oracle socket.
145 CHECK(content::SendZygoteChildPing( 145 CHECK(content::SendZygoteChildPing(
146 child_fds[content::ZygoteForkDelegate::kPIDOracleFDIndex]->get())); 146 child_fds[content::ZygoteForkDelegate::kPIDOracleFDIndex].get()));
147 147
148 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( 148 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
149 switches::kProcessChannelID, channel_id); 149 switches::kProcessChannelID, channel_id);
150 150
151 // Save the browser socket and close the rest. 151 // Save the browser socket and close the rest.
152 base::ScopedFD browser_fd( 152 base::ScopedFD browser_fd(
153 child_fds[content::ZygoteForkDelegate::kBrowserFDIndex]->Pass()); 153 std::move(child_fds[content::ZygoteForkDelegate::kBrowserFDIndex]));
154 child_fds.clear(); 154 child_fds.clear();
155 155
156 BecomeNaClLoader( 156 BecomeNaClLoader(std::move(browser_fd), system_info, uses_nonsfi_mode,
157 browser_fd.Pass(), system_info, uses_nonsfi_mode, nacl_sandbox); 157 nacl_sandbox);
158 _exit(1); 158 _exit(1);
159 } 159 }
160 160
161 // Handle a fork request from the Zygote. 161 // Handle a fork request from the Zygote.
162 // Some of this code was lifted from 162 // Some of this code was lifted from
163 // content/browser/zygote_main_linux.cc:ForkWithRealPid() 163 // content/browser/zygote_main_linux.cc:ForkWithRealPid()
164 bool HandleForkRequest(ScopedVector<base::ScopedFD> child_fds, 164 bool HandleForkRequest(std::vector<base::ScopedFD> child_fds,
165 const NaClLoaderSystemInfo& system_info, 165 const NaClLoaderSystemInfo& system_info,
166 nacl::NaClSandbox* nacl_sandbox, 166 nacl::NaClSandbox* nacl_sandbox,
167 base::PickleIterator* input_iter, 167 base::PickleIterator* input_iter,
168 base::Pickle* output_pickle) { 168 base::Pickle* output_pickle) {
169 bool uses_nonsfi_mode; 169 bool uses_nonsfi_mode;
170 if (!input_iter->ReadBool(&uses_nonsfi_mode)) { 170 if (!input_iter->ReadBool(&uses_nonsfi_mode)) {
171 LOG(ERROR) << "Could not read uses_nonsfi_mode status"; 171 LOG(ERROR) << "Could not read uses_nonsfi_mode status";
172 return false; 172 return false;
173 } 173 }
174 174
(...skipping 25 matching lines...) Expand all
200 if (child_pid == 0) { 200 if (child_pid == 0) {
201 // Install termiantion signal handlers for nonsfi NaCl. The SFI NaCl runtime 201 // Install termiantion signal handlers for nonsfi NaCl. The SFI NaCl runtime
202 // will install signal handlers for SIGINT, SIGTERM, etc. so we do not need 202 // will install signal handlers for SIGINT, SIGTERM, etc. so we do not need
203 // to install termination signal handlers ourselves (in fact, it will crash 203 // to install termination signal handlers ourselves (in fact, it will crash
204 // if signal handlers for these are present). 204 // if signal handlers for these are present).
205 if (uses_nonsfi_mode && getpid() == 1) { 205 if (uses_nonsfi_mode && getpid() == 1) {
206 // Note that nonsfi NaCl may override some of these signal handlers, which 206 // Note that nonsfi NaCl may override some of these signal handlers, which
207 // is fine. 207 // is fine.
208 sandbox::NamespaceSandbox::InstallDefaultTerminationSignalHandlers(); 208 sandbox::NamespaceSandbox::InstallDefaultTerminationSignalHandlers();
209 } 209 }
210 ChildNaClLoaderInit(child_fds.Pass(), 210 ChildNaClLoaderInit(std::move(child_fds), system_info, uses_nonsfi_mode,
211 system_info, 211 nacl_sandbox, channel_id);
212 uses_nonsfi_mode,
213 nacl_sandbox,
214 channel_id);
215 NOTREACHED(); 212 NOTREACHED();
216 } 213 }
217 214
218 // I am the parent. 215 // I am the parent.
219 // First, close the dummy_fd so the sandbox won't find me when 216 // First, close the dummy_fd so the sandbox won't find me when
220 // looking for the child's pid in /proc. Also close other fds. 217 // looking for the child's pid in /proc. Also close other fds.
221 child_fds.clear(); 218 child_fds.clear();
222 VLOG(1) << "nacl_helper: child_pid is " << child_pid; 219 VLOG(1) << "nacl_helper: child_pid is " << child_pid;
223 220
224 // Now send child_pid (eventually -1 if fork failed) to the Chrome Zygote. 221 // Now send child_pid (eventually -1 if fork failed) to the Chrome Zygote.
(...skipping 29 matching lines...) Expand all
254 output_pickle->WriteInt(exit_code); 251 output_pickle->WriteInt(exit_code);
255 return true; 252 return true;
256 } 253 }
257 254
258 // Honor a command |command_type|. Eventual command parameters are 255 // Honor a command |command_type|. Eventual command parameters are
259 // available in |input_iter| and eventual file descriptors attached to 256 // available in |input_iter| and eventual file descriptors attached to
260 // the command are in |attached_fds|. 257 // the command are in |attached_fds|.
261 // Reply to the command on |reply_fds|. 258 // Reply to the command on |reply_fds|.
262 bool HonorRequestAndReply(int reply_fd, 259 bool HonorRequestAndReply(int reply_fd,
263 int command_type, 260 int command_type,
264 ScopedVector<base::ScopedFD> attached_fds, 261 std::vector<base::ScopedFD> attached_fds,
265 const NaClLoaderSystemInfo& system_info, 262 const NaClLoaderSystemInfo& system_info,
266 nacl::NaClSandbox* nacl_sandbox, 263 nacl::NaClSandbox* nacl_sandbox,
267 base::PickleIterator* input_iter) { 264 base::PickleIterator* input_iter) {
268 base::Pickle write_pickle; 265 base::Pickle write_pickle;
269 bool have_to_reply = false; 266 bool have_to_reply = false;
270 // Commands must write anything to send back to |write_pickle|. 267 // Commands must write anything to send back to |write_pickle|.
271 switch (command_type) { 268 switch (command_type) {
272 case nacl::kNaClForkRequest: 269 case nacl::kNaClForkRequest:
273 have_to_reply = HandleForkRequest(attached_fds.Pass(), 270 have_to_reply =
274 system_info, 271 HandleForkRequest(std::move(attached_fds), system_info, nacl_sandbox,
275 nacl_sandbox, 272 input_iter, &write_pickle);
276 input_iter,
277 &write_pickle);
278 break; 273 break;
279 case nacl::kNaClGetTerminationStatusRequest: 274 case nacl::kNaClGetTerminationStatusRequest:
280 have_to_reply = 275 have_to_reply =
281 HandleGetTerminationStatusRequest(input_iter, &write_pickle); 276 HandleGetTerminationStatusRequest(input_iter, &write_pickle);
282 break; 277 break;
283 default: 278 default:
284 LOG(ERROR) << "Unsupported command from Zygote"; 279 LOG(ERROR) << "Unsupported command from Zygote";
285 return false; 280 return false;
286 } 281 }
287 if (!have_to_reply) 282 if (!have_to_reply)
288 return false; 283 return false;
289 const std::vector<int> empty; // We never send file descriptors back. 284 const std::vector<int> empty; // We never send file descriptors back.
290 if (!base::UnixDomainSocket::SendMsg(reply_fd, write_pickle.data(), 285 if (!base::UnixDomainSocket::SendMsg(reply_fd, write_pickle.data(),
291 write_pickle.size(), empty)) { 286 write_pickle.size(), empty)) {
292 LOG(ERROR) << "*** send() to zygote failed"; 287 LOG(ERROR) << "*** send() to zygote failed";
293 return false; 288 return false;
294 } 289 }
295 return true; 290 return true;
296 } 291 }
297 292
298 // Read a request from the Zygote from |zygote_ipc_fd| and handle it. 293 // Read a request from the Zygote from |zygote_ipc_fd| and handle it.
299 // Die on EOF from |zygote_ipc_fd|. 294 // Die on EOF from |zygote_ipc_fd|.
300 bool HandleZygoteRequest(int zygote_ipc_fd, 295 bool HandleZygoteRequest(int zygote_ipc_fd,
301 const NaClLoaderSystemInfo& system_info, 296 const NaClLoaderSystemInfo& system_info,
302 nacl::NaClSandbox* nacl_sandbox) { 297 nacl::NaClSandbox* nacl_sandbox) {
303 ScopedVector<base::ScopedFD> fds; 298 std::vector<base::ScopedFD> fds;
304 char buf[kNaClMaxIPCMessageLength]; 299 char buf[kNaClMaxIPCMessageLength];
305 const ssize_t msglen = base::UnixDomainSocket::RecvMsg(zygote_ipc_fd, 300 const ssize_t msglen = base::UnixDomainSocket::RecvMsg(zygote_ipc_fd,
306 &buf, sizeof(buf), &fds); 301 &buf, sizeof(buf), &fds);
307 // If the Zygote has started handling requests, we should be sandboxed via 302 // If the Zygote has started handling requests, we should be sandboxed via
308 // the setuid sandbox. 303 // the setuid sandbox.
309 if (!nacl_sandbox->layer_one_enabled()) { 304 if (!nacl_sandbox->layer_one_enabled()) {
310 LOG(ERROR) << "NaCl helper process running without a sandbox!\n" 305 LOG(ERROR) << "NaCl helper process running without a sandbox!\n"
311 << "Most likely you need to configure your SUID sandbox " 306 << "Most likely you need to configure your SUID sandbox "
312 << "correctly"; 307 << "correctly";
313 } 308 }
314 if (msglen == 0 || (msglen == -1 && errno == ECONNRESET)) { 309 if (msglen == 0 || (msglen == -1 && errno == ECONNRESET)) {
315 // EOF from the browser. Goodbye! 310 // EOF from the browser. Goodbye!
316 _exit(0); 311 _exit(0);
317 } 312 }
318 if (msglen < 0) { 313 if (msglen < 0) {
319 PLOG(ERROR) << "nacl_helper: receive from zygote failed"; 314 PLOG(ERROR) << "nacl_helper: receive from zygote failed";
320 return false; 315 return false;
321 } 316 }
322 317
323 base::Pickle read_pickle(buf, msglen); 318 base::Pickle read_pickle(buf, msglen);
324 base::PickleIterator read_iter(read_pickle); 319 base::PickleIterator read_iter(read_pickle);
325 int command_type; 320 int command_type;
326 if (!read_iter.ReadInt(&command_type)) { 321 if (!read_iter.ReadInt(&command_type)) {
327 LOG(ERROR) << "Unable to read command from Zygote"; 322 LOG(ERROR) << "Unable to read command from Zygote";
328 return false; 323 return false;
329 } 324 }
330 return HonorRequestAndReply(zygote_ipc_fd, 325 return HonorRequestAndReply(zygote_ipc_fd, command_type, std::move(fds),
331 command_type, 326 system_info, nacl_sandbox, &read_iter);
332 fds.Pass(),
333 system_info,
334 nacl_sandbox,
335 &read_iter);
336 } 327 }
337 328
338 #if !defined(OS_NACL_NONSFI) 329 #if !defined(OS_NACL_NONSFI)
339 static const char kNaClHelperReservedAtZero[] = "reserved_at_zero"; 330 static const char kNaClHelperReservedAtZero[] = "reserved_at_zero";
340 static const char kNaClHelperRDebug[] = "r_debug"; 331 static const char kNaClHelperRDebug[] = "r_debug";
341 332
342 // Since we were started by nacl_helper_bootstrap rather than in the 333 // Since we were started by nacl_helper_bootstrap rather than in the
343 // usual way, the debugger cannot figure out where our executable 334 // usual way, the debugger cannot figure out where our executable
344 // or the dynamic linker or the shared libraries are in memory, 335 // or the dynamic linker or the shared libraries are in memory,
345 // so it won't find any symbols. But we can fake it out to find us. 336 // so it won't find any symbols. But we can fake it out to find us.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 // Now handle requests from the Zygote. 461 // Now handle requests from the Zygote.
471 while (true) { 462 while (true) {
472 bool request_handled = HandleZygoteRequest( 463 bool request_handled = HandleZygoteRequest(
473 kNaClZygoteDescriptor, system_info, nacl_sandbox.get()); 464 kNaClZygoteDescriptor, system_info, nacl_sandbox.get());
474 // Do not turn this into a CHECK() without thinking about robustness 465 // Do not turn this into a CHECK() without thinking about robustness
475 // against malicious IPC requests. 466 // against malicious IPC requests.
476 DCHECK(request_handled); 467 DCHECK(request_handled);
477 } 468 }
478 NOTREACHED(); 469 NOTREACHED();
479 } 470 }
OLDNEW
« no previous file with comments | « base/posix/unix_domain_socket_linux_unittest.cc ('k') | components/nacl/zygote/nacl_fork_delegate_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698