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 <sched.h> |
| 11 #include <setjmp.h> |
10 #include <signal.h> | 12 #include <signal.h> |
11 #include <stdlib.h> | 13 #include <stdlib.h> |
12 #include <sys/resource.h> | 14 #include <sys/resource.h> |
| 15 #include <sys/syscall.h> |
13 #include <sys/time.h> | 16 #include <sys/time.h> |
14 #include <sys/types.h> | 17 #include <sys/types.h> |
15 #include <sys/wait.h> | 18 #include <sys/wait.h> |
16 #include <unistd.h> | 19 #include <unistd.h> |
17 | 20 |
18 #include <iterator> | 21 #include <iterator> |
19 #include <limits> | 22 #include <limits> |
20 #include <set> | 23 #include <set> |
21 | 24 |
22 #include "base/allocator/type_profiler_control.h" | 25 #include "base/allocator/type_profiler_control.h" |
23 #include "base/command_line.h" | 26 #include "base/command_line.h" |
24 #include "base/compiler_specific.h" | 27 #include "base/compiler_specific.h" |
25 #include "base/debug/debugger.h" | 28 #include "base/debug/debugger.h" |
26 #include "base/debug/stack_trace.h" | 29 #include "base/debug/stack_trace.h" |
27 #include "base/files/dir_reader_posix.h" | 30 #include "base/files/dir_reader_posix.h" |
28 #include "base/files/file_util.h" | 31 #include "base/files/file_util.h" |
29 #include "base/files/scoped_file.h" | 32 #include "base/files/scoped_file.h" |
30 #include "base/logging.h" | 33 #include "base/logging.h" |
31 #include "base/memory/scoped_ptr.h" | 34 #include "base/memory/scoped_ptr.h" |
32 #include "base/posix/eintr_wrapper.h" | 35 #include "base/posix/eintr_wrapper.h" |
33 #include "base/process/kill.h" | 36 #include "base/process/kill.h" |
34 #include "base/process/process_metrics.h" | 37 #include "base/process/process_metrics.h" |
35 #include "base/strings/stringprintf.h" | 38 #include "base/strings/stringprintf.h" |
36 #include "base/synchronization/waitable_event.h" | 39 #include "base/synchronization/waitable_event.h" |
37 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 40 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
| 41 #include "base/third_party/valgrind/valgrind.h" |
38 #include "base/threading/platform_thread.h" | 42 #include "base/threading/platform_thread.h" |
39 #include "base/threading/thread_restrictions.h" | 43 #include "base/threading/thread_restrictions.h" |
| 44 #include "build/build_config.h" |
40 | 45 |
41 #if defined(OS_LINUX) | 46 #if defined(OS_LINUX) |
42 #include <sys/prctl.h> | 47 #include <sys/prctl.h> |
43 #endif | 48 #endif |
44 | 49 |
45 #if defined(OS_CHROMEOS) | 50 #if defined(OS_CHROMEOS) |
46 #include <sys/ioctl.h> | 51 #include <sys/ioctl.h> |
47 #endif | 52 #endif |
48 | 53 |
49 #if defined(OS_FREEBSD) | 54 #if defined(OS_FREEBSD) |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 // Now ask the kernel again and check that no restorer will leak. | 182 // Now ask the kernel again and check that no restorer will leak. |
178 if (sys_rt_sigaction(signum, NULL, &act) || act.k_sa_restorer) { | 183 if (sys_rt_sigaction(signum, NULL, &act) || act.k_sa_restorer) { |
179 RAW_LOG(FATAL, "Cound not fix sa_restorer."); | 184 RAW_LOG(FATAL, "Cound not fix sa_restorer."); |
180 } | 185 } |
181 #endif // !defined(NDEBUG) | 186 #endif // !defined(NDEBUG) |
182 } | 187 } |
183 } | 188 } |
184 #endif // !defined(OS_LINUX) || | 189 #endif // !defined(OS_LINUX) || |
185 // (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) | 190 // (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) |
186 | 191 |
| 192 #if defined(OS_LINUX) |
| 193 bool IsRunningOnValgrind() { |
| 194 return RUNNING_ON_VALGRIND; |
| 195 } |
| 196 |
| 197 // This function runs on the stack specified on the clone call. It uses longjmp |
| 198 // to switch back to the original stack so the child can return from sys_clone. |
| 199 int CloneHelper(void* arg) { |
| 200 jmp_buf* env_ptr = reinterpret_cast<jmp_buf*>(arg); |
| 201 longjmp(*env_ptr, 1); |
| 202 |
| 203 // Should not be reached. |
| 204 RAW_CHECK(false); |
| 205 return 1; |
| 206 } |
| 207 |
| 208 // This function is noinline to ensure that stack_buf is below the stack pointer |
| 209 // that is saved when setjmp is called below. This is needed because when |
| 210 // compiled with FORTIFY_SOURCE, glibc's longjmp checks that the stack is moved |
| 211 // upwards. See crbug.com/442912 for more details. |
| 212 #if defined(ADDRESS_SANITIZER) |
| 213 // Disable AddressSanitizer instrumentation for this function to make sure |
| 214 // |stack_buf| is allocated on thread stack instead of ASan's fake stack. |
| 215 // Under ASan longjmp() will attempt to clean up the area between the old and |
| 216 // new stack pointers and print a warning that may confuse the user. |
| 217 __attribute__((no_sanitize_address)) |
| 218 #endif |
| 219 NOINLINE pid_t CloneAndLongjmpInChild(unsigned long flags, |
| 220 pid_t* ptid, |
| 221 pid_t* ctid, |
| 222 jmp_buf* env) { |
| 223 // We use the libc clone wrapper instead of making the syscall |
| 224 // directly because making the syscall may fail to update the libc's |
| 225 // internal pid cache. The libc interface unfortunately requires |
| 226 // specifying a new stack, so we use setjmp/longjmp to emulate |
| 227 // fork-like behavior. |
| 228 char stack_buf[PTHREAD_STACK_MIN]; |
| 229 #if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) || \ |
| 230 defined(ARCH_CPU_MIPS64_FAMILY) || defined(ARCH_CPU_MIPS_FAMILY) |
| 231 // The stack grows downward. |
| 232 void* stack = stack_buf + sizeof(stack_buf); |
| 233 #else |
| 234 #error "Unsupported architecture" |
| 235 #endif |
| 236 return clone(&CloneHelper, stack, flags, env, ptid, nullptr, ctid); |
| 237 } |
| 238 #endif // defined(OS_LINUX) |
| 239 |
187 } // anonymous namespace | 240 } // anonymous namespace |
188 | 241 |
189 // Functor for |ScopedDIR| (below). | 242 // Functor for |ScopedDIR| (below). |
190 struct ScopedDIRClose { | 243 struct ScopedDIRClose { |
191 inline void operator()(DIR* x) const { | 244 inline void operator()(DIR* x) const { |
192 if (x) | 245 if (x) |
193 closedir(x); | 246 closedir(x); |
194 } | 247 } |
195 }; | 248 }; |
196 | 249 |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 bool GetAppOutputWithExitCode(const CommandLine& cl, | 717 bool GetAppOutputWithExitCode(const CommandLine& cl, |
665 std::string* output, | 718 std::string* output, |
666 int* exit_code) { | 719 int* exit_code) { |
667 // Run |execve()| with the current environment and store "unlimited" data. | 720 // Run |execve()| with the current environment and store "unlimited" data. |
668 GetAppOutputInternalResult result = GetAppOutputInternal( | 721 GetAppOutputInternalResult result = GetAppOutputInternal( |
669 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, | 722 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, |
670 exit_code); | 723 exit_code); |
671 return result == EXECUTE_SUCCESS; | 724 return result == EXECUTE_SUCCESS; |
672 } | 725 } |
673 | 726 |
| 727 #if defined(OS_LINUX) |
| 728 pid_t ForkWithFlags(unsigned long flags, pid_t* ptid, pid_t* ctid) { |
| 729 const bool clone_tls_used = flags & CLONE_SETTLS; |
| 730 const bool invalid_ctid = |
| 731 (flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && !ctid; |
| 732 const bool invalid_ptid = (flags & CLONE_PARENT_SETTID) && !ptid; |
| 733 |
| 734 // We do not support CLONE_VM. |
| 735 const bool clone_vm_used = flags & CLONE_VM; |
| 736 |
| 737 if (clone_tls_used || invalid_ctid || invalid_ptid || clone_vm_used) { |
| 738 RAW_LOG(FATAL, "Invalid usage of ForkWithFlags"); |
| 739 } |
| 740 |
| 741 // Valgrind's clone implementation does not support specifiying a child_stack |
| 742 // without CLONE_VM, so we cannot use libc's clone wrapper when running under |
| 743 // Valgrind. As a result, the libc pid cache may be incorrect under Valgrind. |
| 744 // See crbug.com/442817 for more details. |
| 745 if (IsRunningOnValgrind()) { |
| 746 // See kernel/fork.c in Linux. There is different ordering of sys_clone |
| 747 // parameters depending on CONFIG_CLONE_BACKWARDS* configuration options. |
| 748 #if defined(ARCH_CPU_X86_64) |
| 749 return syscall(__NR_clone, flags, nullptr, ptid, ctid, nullptr); |
| 750 #elif defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARM_FAMILY) || \ |
| 751 defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_MIPS64_FAMILY) |
| 752 // CONFIG_CLONE_BACKWARDS defined. |
| 753 return syscall(__NR_clone, flags, nullptr, ptid, nullptr, ctid); |
| 754 #else |
| 755 #error "Unsupported architecture" |
| 756 #endif |
| 757 } |
| 758 |
| 759 jmp_buf env; |
| 760 if (setjmp(env) == 0) { |
| 761 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); |
| 762 } |
| 763 |
| 764 return 0; |
| 765 } |
| 766 #endif // defined(OS_LINUX) |
| 767 |
674 } // namespace base | 768 } // namespace base |
OLD | NEW |