| 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> | 10 #include <sched.h> |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 | 58 |
| 59 #if defined(OS_MACOSX) | 59 #if defined(OS_MACOSX) |
| 60 #include <crt_externs.h> | 60 #include <crt_externs.h> |
| 61 #include <sys/event.h> | 61 #include <sys/event.h> |
| 62 #else | 62 #else |
| 63 extern char** environ; | 63 extern char** environ; |
| 64 #endif | 64 #endif |
| 65 | 65 |
| 66 namespace base { | 66 namespace base { |
| 67 | 67 |
| 68 #if !defined(OS_NACL_NONSFI) |
| 69 |
| 68 namespace { | 70 namespace { |
| 69 | 71 |
| 70 // Get the process's "environment" (i.e. the thing that setenv/getenv | 72 // Get the process's "environment" (i.e. the thing that setenv/getenv |
| 71 // work with). | 73 // work with). |
| 72 char** GetEnvironment() { | 74 char** GetEnvironment() { |
| 73 #if defined(OS_MACOSX) | 75 #if defined(OS_MACOSX) |
| 74 return *_NSGetEnviron(); | 76 return *_NSGetEnviron(); |
| 75 #else | 77 #else |
| 76 return environ; | 78 return environ; |
| 77 #endif | 79 #endif |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 #if !defined(NDEBUG) | 183 #if !defined(NDEBUG) |
| 182 // Now ask the kernel again and check that no restorer will leak. | 184 // Now ask the kernel again and check that no restorer will leak. |
| 183 if (sys_rt_sigaction(signum, NULL, &act) || act.k_sa_restorer) { | 185 if (sys_rt_sigaction(signum, NULL, &act) || act.k_sa_restorer) { |
| 184 RAW_LOG(FATAL, "Cound not fix sa_restorer."); | 186 RAW_LOG(FATAL, "Cound not fix sa_restorer."); |
| 185 } | 187 } |
| 186 #endif // !defined(NDEBUG) | 188 #endif // !defined(NDEBUG) |
| 187 } | 189 } |
| 188 } | 190 } |
| 189 #endif // !defined(OS_LINUX) || | 191 #endif // !defined(OS_LINUX) || |
| 190 // (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) | 192 // (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) |
| 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 | |
| 240 } // anonymous namespace | 193 } // anonymous namespace |
| 241 | 194 |
| 242 // Functor for |ScopedDIR| (below). | 195 // Functor for |ScopedDIR| (below). |
| 243 struct ScopedDIRClose { | 196 struct ScopedDIRClose { |
| 244 inline void operator()(DIR* x) const { | 197 inline void operator()(DIR* x) const { |
| 245 if (x) | 198 if (x) |
| 246 closedir(x); | 199 closedir(x); |
| 247 } | 200 } |
| 248 }; | 201 }; |
| 249 | 202 |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 bool GetAppOutputWithExitCode(const CommandLine& cl, | 687 bool GetAppOutputWithExitCode(const CommandLine& cl, |
| 735 std::string* output, | 688 std::string* output, |
| 736 int* exit_code) { | 689 int* exit_code) { |
| 737 // Run |execve()| with the current environment and store "unlimited" data. | 690 // Run |execve()| with the current environment and store "unlimited" data. |
| 738 GetAppOutputInternalResult result = GetAppOutputInternal( | 691 GetAppOutputInternalResult result = GetAppOutputInternal( |
| 739 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, | 692 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, |
| 740 exit_code); | 693 exit_code); |
| 741 return result == EXECUTE_SUCCESS; | 694 return result == EXECUTE_SUCCESS; |
| 742 } | 695 } |
| 743 | 696 |
| 744 #if defined(OS_LINUX) | 697 #endif // !defined(OS_NACL_NONSFI) |
| 698 |
| 699 #if defined(OS_LINUX) || defined(OS_NACL_NONSFI) |
| 700 namespace { |
| 701 |
| 702 bool IsRunningOnValgrind() { |
| 703 return RUNNING_ON_VALGRIND; |
| 704 } |
| 705 |
| 706 // This function runs on the stack specified on the clone call. It uses longjmp |
| 707 // to switch back to the original stack so the child can return from sys_clone. |
| 708 int CloneHelper(void* arg) { |
| 709 jmp_buf* env_ptr = reinterpret_cast<jmp_buf*>(arg); |
| 710 longjmp(*env_ptr, 1); |
| 711 |
| 712 // Should not be reached. |
| 713 RAW_CHECK(false); |
| 714 return 1; |
| 715 } |
| 716 |
| 717 // This function is noinline to ensure that stack_buf is below the stack pointer |
| 718 // that is saved when setjmp is called below. This is needed because when |
| 719 // compiled with FORTIFY_SOURCE, glibc's longjmp checks that the stack is moved |
| 720 // upwards. See crbug.com/442912 for more details. |
| 721 #if defined(ADDRESS_SANITIZER) |
| 722 // Disable AddressSanitizer instrumentation for this function to make sure |
| 723 // |stack_buf| is allocated on thread stack instead of ASan's fake stack. |
| 724 // Under ASan longjmp() will attempt to clean up the area between the old and |
| 725 // new stack pointers and print a warning that may confuse the user. |
| 726 __attribute__((no_sanitize_address)) |
| 727 #endif |
| 728 NOINLINE pid_t CloneAndLongjmpInChild(unsigned long flags, |
| 729 pid_t* ptid, |
| 730 pid_t* ctid, |
| 731 jmp_buf* env) { |
| 732 // We use the libc clone wrapper instead of making the syscall |
| 733 // directly because making the syscall may fail to update the libc's |
| 734 // internal pid cache. The libc interface unfortunately requires |
| 735 // specifying a new stack, so we use setjmp/longjmp to emulate |
| 736 // fork-like behavior. |
| 737 char stack_buf[PTHREAD_STACK_MIN]; |
| 738 #if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) || \ |
| 739 defined(ARCH_CPU_MIPS64_FAMILY) || defined(ARCH_CPU_MIPS_FAMILY) |
| 740 // The stack grows downward. |
| 741 void* stack = stack_buf + sizeof(stack_buf); |
| 742 #else |
| 743 #error "Unsupported architecture" |
| 744 #endif |
| 745 return clone(&CloneHelper, stack, flags, env, ptid, nullptr, ctid); |
| 746 } |
| 747 |
| 748 } // anonymous namespace |
| 749 |
| 745 pid_t ForkWithFlags(unsigned long flags, pid_t* ptid, pid_t* ctid) { | 750 pid_t ForkWithFlags(unsigned long flags, pid_t* ptid, pid_t* ctid) { |
| 746 const bool clone_tls_used = flags & CLONE_SETTLS; | 751 const bool clone_tls_used = flags & CLONE_SETTLS; |
| 747 const bool invalid_ctid = | 752 const bool invalid_ctid = |
| 748 (flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && !ctid; | 753 (flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && !ctid; |
| 749 const bool invalid_ptid = (flags & CLONE_PARENT_SETTID) && !ptid; | 754 const bool invalid_ptid = (flags & CLONE_PARENT_SETTID) && !ptid; |
| 750 | 755 |
| 751 // We do not support CLONE_VM. | 756 // We do not support CLONE_VM. |
| 752 const bool clone_vm_used = flags & CLONE_VM; | 757 const bool clone_vm_used = flags & CLONE_VM; |
| 753 | 758 |
| 754 if (clone_tls_used || invalid_ctid || invalid_ptid || clone_vm_used) { | 759 if (clone_tls_used || invalid_ctid || invalid_ptid || clone_vm_used) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 773 #endif | 778 #endif |
| 774 } | 779 } |
| 775 | 780 |
| 776 jmp_buf env; | 781 jmp_buf env; |
| 777 if (setjmp(env) == 0) { | 782 if (setjmp(env) == 0) { |
| 778 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); | 783 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); |
| 779 } | 784 } |
| 780 | 785 |
| 781 return 0; | 786 return 0; |
| 782 } | 787 } |
| 783 #endif // defined(OS_LINUX) | 788 #endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI) |
| 784 | 789 |
| 785 } // namespace base | 790 } // namespace base |
| OLD | NEW |