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 |