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 "base/process/launch.h" | 5 #include "base/process/launch.h" |
6 | 6 |
7 #include <dirent.h> | 7 #include <dirent.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <signal.h> | 10 #include <signal.h> |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 static const char kFDDir[] = "/dev/fd"; | 200 static const char kFDDir[] = "/dev/fd"; |
201 #elif defined(OS_FREEBSD) | 201 #elif defined(OS_FREEBSD) |
202 static const char kFDDir[] = "/dev/fd"; | 202 static const char kFDDir[] = "/dev/fd"; |
203 #elif defined(OS_OPENBSD) | 203 #elif defined(OS_OPENBSD) |
204 static const char kFDDir[] = "/dev/fd"; | 204 static const char kFDDir[] = "/dev/fd"; |
205 #elif defined(OS_ANDROID) | 205 #elif defined(OS_ANDROID) |
206 static const char kFDDir[] = "/proc/self/fd"; | 206 static const char kFDDir[] = "/proc/self/fd"; |
207 #endif | 207 #endif |
208 | 208 |
209 void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) { | 209 void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) { |
210 // DANGER: no calls to malloc are allowed from now on: | 210 // DANGER: no calls to malloc or locks are allowed from now on: |
211 // http://crbug.com/36678 | 211 // http://crbug.com/36678 |
212 | 212 |
213 // Get the maximum number of FDs possible. | 213 // Get the maximum number of FDs possible. |
214 size_t max_fds = GetMaxFds(); | 214 size_t max_fds = GetMaxFds(); |
215 | 215 |
216 DirReaderPosix fd_dir(kFDDir); | 216 DirReaderPosix fd_dir(kFDDir); |
217 if (!fd_dir.IsValid()) { | 217 if (!fd_dir.IsValid()) { |
218 // Fallback case: Try every possible fd. | 218 // Fallback case: Try every possible fd. |
219 for (size_t i = 0; i < max_fds; ++i) { | 219 for (size_t i = 0; i < max_fds; ++i) { |
220 const int fd = static_cast<int>(i); | 220 const int fd = static_cast<int>(i); |
221 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) | 221 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) |
222 continue; | 222 continue; |
223 InjectiveMultimap::const_iterator j; | 223 // Cannot use STL iterators here, since debug iterators use locks. |
224 for (j = saved_mapping.begin(); j != saved_mapping.end(); j++) { | 224 size_t j; |
225 if (fd == j->dest) | 225 for (j = 0; j < saved_mapping.size(); j++) { |
226 if (fd == saved_mapping[j].dest) | |
226 break; | 227 break; |
227 } | 228 } |
228 if (j != saved_mapping.end()) | 229 if (j < saved_mapping.size()) |
229 continue; | 230 continue; |
230 | 231 |
231 // Since we're just trying to close anything we can find, | 232 // Since we're just trying to close anything we can find, |
232 // ignore any error return values of close(). | 233 // ignore any error return values of close(). |
233 close(fd); | 234 close(fd); |
234 } | 235 } |
235 return; | 236 return; |
236 } | 237 } |
237 | 238 |
238 const int dir_fd = fd_dir.fd(); | 239 const int dir_fd = fd_dir.fd(); |
239 | 240 |
240 for ( ; fd_dir.Next(); ) { | 241 for ( ; fd_dir.Next(); ) { |
241 // Skip . and .. entries. | 242 // Skip . and .. entries. |
242 if (fd_dir.name()[0] == '.') | 243 if (fd_dir.name()[0] == '.') |
243 continue; | 244 continue; |
244 | 245 |
245 char *endptr; | 246 char *endptr; |
246 errno = 0; | 247 errno = 0; |
247 const long int fd = strtol(fd_dir.name(), &endptr, 10); | 248 const long int fd = strtol(fd_dir.name(), &endptr, 10); |
248 if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno) | 249 if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno) |
249 continue; | 250 continue; |
250 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) | 251 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) |
251 continue; | 252 continue; |
252 InjectiveMultimap::const_iterator i; | 253 // Cannot use STL iterators here, since debug iterators use locks. |
253 for (i = saved_mapping.begin(); i != saved_mapping.end(); i++) { | 254 size_t i; |
254 if (fd == i->dest) | 255 for (i = 0; i < saved_mapping.size(); i++) { |
256 if (fd == saved_mapping[i].dest) | |
255 break; | 257 break; |
256 } | 258 } |
257 if (i != saved_mapping.end()) | 259 if (i < saved_mapping.size()) |
258 continue; | 260 continue; |
259 if (fd == dir_fd) | 261 if (fd == dir_fd) |
260 continue; | 262 continue; |
261 | 263 |
262 // When running under Valgrind, Valgrind opens several FDs for its | 264 // When running under Valgrind, Valgrind opens several FDs for its |
263 // own use and will complain if we try to close them. All of | 265 // own use and will complain if we try to close them. All of |
264 // these FDs are >= |max_fds|, so we can check against that here | 266 // these FDs are >= |max_fds|, so we can check against that here |
265 // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758 | 267 // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758 |
266 if (fd < static_cast<int>(max_fds)) { | 268 if (fd < static_cast<int>(max_fds)) { |
267 int ret = IGNORE_EINTR(close(fd)); | 269 int ret = IGNORE_EINTR(close(fd)); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
381 | 383 |
382 #if 0 | 384 #if 0 |
383 // When debugging it can be helpful to check that we really aren't making | 385 // When debugging it can be helpful to check that we really aren't making |
384 // any hidden calls to malloc. | 386 // any hidden calls to malloc. |
385 void *malloc_thunk = | 387 void *malloc_thunk = |
386 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); | 388 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); |
387 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); | 389 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); |
388 memset(reinterpret_cast<void*>(malloc), 0xff, 8); | 390 memset(reinterpret_cast<void*>(malloc), 0xff, 8); |
389 #endif // 0 | 391 #endif // 0 |
390 | 392 |
391 // DANGER: no calls to malloc are allowed from now on: | 393 // DANGER: no calls to malloc or locks are allowed from now on: |
392 // http://crbug.com/36678 | 394 // http://crbug.com/36678 |
393 | 395 |
394 #if defined(OS_CHROMEOS) | 396 #if defined(OS_CHROMEOS) |
395 if (options.ctrl_terminal_fd >= 0) { | 397 if (options.ctrl_terminal_fd >= 0) { |
396 // Set process' controlling terminal. | 398 // Set process' controlling terminal. |
397 if (HANDLE_EINTR(setsid()) != -1) { | 399 if (HANDLE_EINTR(setsid()) != -1) { |
398 if (HANDLE_EINTR( | 400 if (HANDLE_EINTR( |
399 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { | 401 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { |
400 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); | 402 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); |
401 } | 403 } |
402 } else { | 404 } else { |
403 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); | 405 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); |
404 } | 406 } |
405 } | 407 } |
406 #endif // defined(OS_CHROMEOS) | 408 #endif // defined(OS_CHROMEOS) |
407 | 409 |
408 if (options.fds_to_remap) { | 410 if (options.fds_to_remap) { |
409 for (FileHandleMappingVector::const_iterator | 411 // Cannot use STL iterators here, since debug iterators use locks. |
410 it = options.fds_to_remap->begin(); | 412 for (size_t i = 0; i < options.fds_to_remap->size(); ++i) { |
411 it != options.fds_to_remap->end(); ++it) { | 413 const FileHandleMappingVector::value_type& value = |
412 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); | 414 (*options.fds_to_remap)[i]; |
413 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); | 415 fd_shuffle1.push_back(InjectionArc(value.first, value.second, false)); |
416 fd_shuffle2.push_back(InjectionArc(value.first, value.second, false)); | |
414 } | 417 } |
415 } | 418 } |
416 | 419 |
417 if (!options.environ.empty()) | 420 if (!options.environ.empty()) |
418 SetEnvironment(new_environ.get()); | 421 SetEnvironment(new_environ.get()); |
419 | 422 |
420 // fd_shuffle1 is mutated by this call because it cannot malloc. | 423 // fd_shuffle1 is mutated by this call because it cannot malloc. |
421 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 424 if (!ShuffleFileDescriptors(&fd_shuffle1)) |
422 _exit(127); | 425 _exit(127); |
423 | 426 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
514 switch (pid = fork()) { | 517 switch (pid = fork()) { |
515 case -1: // error | 518 case -1: // error |
516 close(pipe_fd[0]); | 519 close(pipe_fd[0]); |
517 close(pipe_fd[1]); | 520 close(pipe_fd[1]); |
518 return EXECUTE_FAILURE; | 521 return EXECUTE_FAILURE; |
519 case 0: // child | 522 case 0: // child |
520 { | 523 { |
521 #if defined(OS_MACOSX) | 524 #if defined(OS_MACOSX) |
522 RestoreDefaultExceptionHandler(); | 525 RestoreDefaultExceptionHandler(); |
523 #endif | 526 #endif |
524 // DANGER: no calls to malloc are allowed from now on: | 527 // DANGER: no calls to malloc or locks are allowed from now on: |
525 // http://crbug.com/36678 | 528 // http://crbug.com/36678 |
526 | 529 |
527 // Obscure fork() rule: in the child, if you don't end up doing exec*(), | 530 // Obscure fork() rule: in the child, if you don't end up doing exec*(), |
528 // you call _exit() instead of exit(). This is because _exit() does not | 531 // you call _exit() instead of exit(). This is because _exit() does not |
529 // call any previously-registered (in the parent) exit handlers, which | 532 // call any previously-registered (in the parent) exit handlers, which |
530 // might do things like block waiting for threads that don't even exist | 533 // might do things like block waiting for threads that don't even exist |
531 // in the child. | 534 // in the child. |
532 int dev_null = open("/dev/null", O_WRONLY); | 535 int dev_null = open("/dev/null", O_WRONLY); |
533 if (dev_null < 0) | 536 if (dev_null < 0) |
534 _exit(127); | 537 _exit(127); |
535 | 538 |
536 // Stop type-profiler. | 539 // Stop type-profiler. |
537 // The profiler should be stopped between fork and exec since it inserts | 540 // The profiler should be stopped between fork and exec since it inserts |
538 // locks at new/delete expressions. See http://crbug.com/36678. | 541 // locks at new/delete expressions. See http://crbug.com/36678. |
539 base::type_profiler::Controller::Stop(); | 542 base::type_profiler::Controller::Stop(); |
540 | 543 |
541 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); | 544 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); |
542 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); | 545 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); |
543 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); | 546 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); |
544 // Adding another element here? Remeber to increase the argument to | 547 // Adding another element here? Remeber to increase the argument to |
545 // reserve(), above. | 548 // reserve(), above. |
546 | 549 |
547 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(), | 550 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(), |
Elliot Glaysher
2014/01/07 22:33:14
So maybe I'm wrong here, but isn't this using stl
mattm
2014/01/07 22:43:40
Oh, yeah. I missed this one and I must not have be
| |
548 std::back_inserter(fd_shuffle2)); | 551 std::back_inserter(fd_shuffle2)); |
549 | 552 |
550 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 553 if (!ShuffleFileDescriptors(&fd_shuffle1)) |
551 _exit(127); | 554 _exit(127); |
552 | 555 |
553 CloseSuperfluousFds(fd_shuffle2); | 556 CloseSuperfluousFds(fd_shuffle2); |
554 | 557 |
555 for (size_t i = 0; i < argv.size(); i++) | 558 for (size_t i = 0; i < argv.size(); i++) |
556 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 559 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
557 argv_cstr[argv.size()] = NULL; | 560 argv_cstr[argv.size()] = NULL; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
629 std::string* output, | 632 std::string* output, |
630 int* exit_code) { | 633 int* exit_code) { |
631 // Run |execve()| with the current environment and store "unlimited" data. | 634 // Run |execve()| with the current environment and store "unlimited" data. |
632 GetAppOutputInternalResult result = GetAppOutputInternal( | 635 GetAppOutputInternalResult result = GetAppOutputInternal( |
633 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, | 636 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, |
634 exit_code); | 637 exit_code); |
635 return result == EXECUTE_SUCCESS; | 638 return result == EXECUTE_SUCCESS; |
636 } | 639 } |
637 | 640 |
638 } // namespace base | 641 } // namespace base |
OLD | NEW |