xref: /aosp_15_r20/external/cronet/base/process/launch_posix.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/process/launch.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <dirent.h>
8*6777b538SAndroid Build Coastguard Worker #include <errno.h>
9*6777b538SAndroid Build Coastguard Worker #include <fcntl.h>
10*6777b538SAndroid Build Coastguard Worker #include <sched.h>
11*6777b538SAndroid Build Coastguard Worker #include <setjmp.h>
12*6777b538SAndroid Build Coastguard Worker #include <signal.h>
13*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
14*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
15*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
16*6777b538SAndroid Build Coastguard Worker #include <sys/resource.h>
17*6777b538SAndroid Build Coastguard Worker #include <sys/syscall.h>
18*6777b538SAndroid Build Coastguard Worker #include <sys/time.h>
19*6777b538SAndroid Build Coastguard Worker #include <sys/types.h>
20*6777b538SAndroid Build Coastguard Worker #include <sys/wait.h>
21*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker #include <iterator>
24*6777b538SAndroid Build Coastguard Worker #include <limits>
25*6777b538SAndroid Build Coastguard Worker #include <memory>
26*6777b538SAndroid Build Coastguard Worker #include <set>
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
30*6777b538SAndroid Build Coastguard Worker #include "base/debug/debugger.h"
31*6777b538SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h"
32*6777b538SAndroid Build Coastguard Worker #include "base/files/dir_reader_posix.h"
33*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
34*6777b538SAndroid Build Coastguard Worker #include "base/files/scoped_file.h"
35*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
36*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr_exclusion.h"
37*6777b538SAndroid Build Coastguard Worker #include "base/process/environment_internal.h"
38*6777b538SAndroid Build Coastguard Worker #include "base/process/process.h"
39*6777b538SAndroid Build Coastguard Worker #include "base/process/process_metrics.h"
40*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/waitable_event.h"
41*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
42*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread_internal_posix.h"
43*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
44*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
45*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_AIX)
48*6777b538SAndroid Build Coastguard Worker #include <sys/prctl.h>
49*6777b538SAndroid Build Coastguard Worker #endif
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
52*6777b538SAndroid Build Coastguard Worker #include <sys/ioctl.h>
53*6777b538SAndroid Build Coastguard Worker #endif
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_FREEBSD)
56*6777b538SAndroid Build Coastguard Worker #include <sys/event.h>
57*6777b538SAndroid Build Coastguard Worker #include <sys/ucontext.h>
58*6777b538SAndroid Build Coastguard Worker #endif
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC)
61*6777b538SAndroid Build Coastguard Worker #error "macOS should use launch_mac.cc"
62*6777b538SAndroid Build Coastguard Worker #endif
63*6777b538SAndroid Build Coastguard Worker 
64*6777b538SAndroid Build Coastguard Worker extern char** environ;
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker namespace base {
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker namespace {
69*6777b538SAndroid Build Coastguard Worker 
70*6777b538SAndroid Build Coastguard Worker // Get the process's "environment" (i.e. the thing that setenv/getenv
71*6777b538SAndroid Build Coastguard Worker // work with).
GetEnvironment()72*6777b538SAndroid Build Coastguard Worker char** GetEnvironment() {
73*6777b538SAndroid Build Coastguard Worker   return environ;
74*6777b538SAndroid Build Coastguard Worker }
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker // Set the process's "environment" (i.e. the thing that setenv/getenv
77*6777b538SAndroid Build Coastguard Worker // work with).
SetEnvironment(char ** env)78*6777b538SAndroid Build Coastguard Worker void SetEnvironment(char** env) {
79*6777b538SAndroid Build Coastguard Worker   environ = env;
80*6777b538SAndroid Build Coastguard Worker }
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker // Set the calling thread's signal mask to new_sigmask and return
83*6777b538SAndroid Build Coastguard Worker // the previous signal mask.
SetSignalMask(const sigset_t & new_sigmask)84*6777b538SAndroid Build Coastguard Worker sigset_t SetSignalMask(const sigset_t& new_sigmask) {
85*6777b538SAndroid Build Coastguard Worker   sigset_t old_sigmask;
86*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
87*6777b538SAndroid Build Coastguard Worker   // POSIX says pthread_sigmask() must be used in multi-threaded processes,
88*6777b538SAndroid Build Coastguard Worker   // but Android's pthread_sigmask() was broken until 4.1:
89*6777b538SAndroid Build Coastguard Worker   // https://code.google.com/p/android/issues/detail?id=15337
90*6777b538SAndroid Build Coastguard Worker   // http://stackoverflow.com/questions/13777109/pthread-sigmask-on-android-not-working
91*6777b538SAndroid Build Coastguard Worker   RAW_CHECK(sigprocmask(SIG_SETMASK, &new_sigmask, &old_sigmask) == 0);
92*6777b538SAndroid Build Coastguard Worker #else
93*6777b538SAndroid Build Coastguard Worker   RAW_CHECK(pthread_sigmask(SIG_SETMASK, &new_sigmask, &old_sigmask) == 0);
94*6777b538SAndroid Build Coastguard Worker #endif
95*6777b538SAndroid Build Coastguard Worker   return old_sigmask;
96*6777b538SAndroid Build Coastguard Worker }
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker #if (!BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_AIX) && !BUILDFLAG(IS_CHROMEOS)) || \
99*6777b538SAndroid Build Coastguard Worker     (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__))
ResetChildSignalHandlersToDefaults()100*6777b538SAndroid Build Coastguard Worker void ResetChildSignalHandlersToDefaults() {
101*6777b538SAndroid Build Coastguard Worker   // The previous signal handlers are likely to be meaningless in the child's
102*6777b538SAndroid Build Coastguard Worker   // context so we reset them to the defaults for now. http://crbug.com/44953
103*6777b538SAndroid Build Coastguard Worker   // These signal handlers are set up at least in browser_main_posix.cc:
104*6777b538SAndroid Build Coastguard Worker   // BrowserMainPartsPosix::PreEarlyInitialization and stack_trace_posix.cc:
105*6777b538SAndroid Build Coastguard Worker   // EnableInProcessStackDumping.
106*6777b538SAndroid Build Coastguard Worker   signal(SIGHUP, SIG_DFL);
107*6777b538SAndroid Build Coastguard Worker   signal(SIGINT, SIG_DFL);
108*6777b538SAndroid Build Coastguard Worker   signal(SIGILL, SIG_DFL);
109*6777b538SAndroid Build Coastguard Worker   signal(SIGABRT, SIG_DFL);
110*6777b538SAndroid Build Coastguard Worker   signal(SIGFPE, SIG_DFL);
111*6777b538SAndroid Build Coastguard Worker   signal(SIGBUS, SIG_DFL);
112*6777b538SAndroid Build Coastguard Worker   signal(SIGSEGV, SIG_DFL);
113*6777b538SAndroid Build Coastguard Worker   signal(SIGSYS, SIG_DFL);
114*6777b538SAndroid Build Coastguard Worker   signal(SIGTERM, SIG_DFL);
115*6777b538SAndroid Build Coastguard Worker }
116*6777b538SAndroid Build Coastguard Worker 
117*6777b538SAndroid Build Coastguard Worker #else
118*6777b538SAndroid Build Coastguard Worker 
119*6777b538SAndroid Build Coastguard Worker // TODO(jln): remove the Linux special case once kernels are fixed.
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker // Internally the kernel makes sigset_t an array of long large enough to have
122*6777b538SAndroid Build Coastguard Worker // one bit per signal.
123*6777b538SAndroid Build Coastguard Worker typedef uint64_t kernel_sigset_t;
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker // This is what struct sigaction looks like to the kernel at least on X86 and
126*6777b538SAndroid Build Coastguard Worker // ARM. MIPS, for instance, is very different.
127*6777b538SAndroid Build Coastguard Worker // For that reason `k_sa_handler` and `k_sa_restorer` can't be raw_ptr<>.
128*6777b538SAndroid Build Coastguard Worker struct kernel_sigaction {
129*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION void*
130*6777b538SAndroid Build Coastguard Worker       k_sa_handler;  // For this usage it only needs to be a generic pointer.
131*6777b538SAndroid Build Coastguard Worker   unsigned long k_sa_flags;
132*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION void*
133*6777b538SAndroid Build Coastguard Worker       k_sa_restorer;  // For this usage it only needs to be a generic pointer.
134*6777b538SAndroid Build Coastguard Worker   kernel_sigset_t k_sa_mask;
135*6777b538SAndroid Build Coastguard Worker };
136*6777b538SAndroid Build Coastguard Worker 
137*6777b538SAndroid Build Coastguard Worker // glibc's sigaction() will prevent access to sa_restorer, so we need to roll
138*6777b538SAndroid Build Coastguard Worker // our own.
sys_rt_sigaction(int sig,const struct kernel_sigaction * act,struct kernel_sigaction * oact)139*6777b538SAndroid Build Coastguard Worker long sys_rt_sigaction(int sig,
140*6777b538SAndroid Build Coastguard Worker                       const struct kernel_sigaction* act,
141*6777b538SAndroid Build Coastguard Worker                       struct kernel_sigaction* oact) {
142*6777b538SAndroid Build Coastguard Worker   return syscall(SYS_rt_sigaction, sig, act, oact, sizeof(kernel_sigset_t));
143*6777b538SAndroid Build Coastguard Worker }
144*6777b538SAndroid Build Coastguard Worker 
145*6777b538SAndroid Build Coastguard Worker // This function is intended to be used in between fork() and execve() and will
146*6777b538SAndroid Build Coastguard Worker // reset all signal handlers to the default.
147*6777b538SAndroid Build Coastguard Worker // The motivation for going through all of them is that sa_restorer can leak
148*6777b538SAndroid Build Coastguard Worker // from parents and help defeat ASLR on buggy kernels.  We reset it to null.
149*6777b538SAndroid Build Coastguard Worker // See crbug.com/177956.
ResetChildSignalHandlersToDefaults(void)150*6777b538SAndroid Build Coastguard Worker void ResetChildSignalHandlersToDefaults(void) {
151*6777b538SAndroid Build Coastguard Worker   for (int signum = 1; ; ++signum) {
152*6777b538SAndroid Build Coastguard Worker     struct kernel_sigaction act = {nullptr};
153*6777b538SAndroid Build Coastguard Worker     long sigaction_get_ret = sys_rt_sigaction(signum, nullptr, &act);
154*6777b538SAndroid Build Coastguard Worker     if (sigaction_get_ret && errno == EINVAL) {
155*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
156*6777b538SAndroid Build Coastguard Worker       // Linux supports 32 real-time signals from 33 to 64.
157*6777b538SAndroid Build Coastguard Worker       // If the number of signals in the Linux kernel changes, someone should
158*6777b538SAndroid Build Coastguard Worker       // look at this code.
159*6777b538SAndroid Build Coastguard Worker       const int kNumberOfSignals = 64;
160*6777b538SAndroid Build Coastguard Worker       RAW_CHECK(signum == kNumberOfSignals + 1);
161*6777b538SAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
162*6777b538SAndroid Build Coastguard Worker       break;
163*6777b538SAndroid Build Coastguard Worker     }
164*6777b538SAndroid Build Coastguard Worker     // All other failures are fatal.
165*6777b538SAndroid Build Coastguard Worker     if (sigaction_get_ret) {
166*6777b538SAndroid Build Coastguard Worker       RAW_LOG(FATAL, "sigaction (get) failed.");
167*6777b538SAndroid Build Coastguard Worker     }
168*6777b538SAndroid Build Coastguard Worker 
169*6777b538SAndroid Build Coastguard Worker     // The kernel won't allow to re-set SIGKILL or SIGSTOP.
170*6777b538SAndroid Build Coastguard Worker     if (signum != SIGSTOP && signum != SIGKILL) {
171*6777b538SAndroid Build Coastguard Worker       act.k_sa_handler = reinterpret_cast<void*>(SIG_DFL);
172*6777b538SAndroid Build Coastguard Worker       act.k_sa_restorer = nullptr;
173*6777b538SAndroid Build Coastguard Worker       if (sys_rt_sigaction(signum, &act, nullptr)) {
174*6777b538SAndroid Build Coastguard Worker         RAW_LOG(FATAL, "sigaction (set) failed.");
175*6777b538SAndroid Build Coastguard Worker       }
176*6777b538SAndroid Build Coastguard Worker     }
177*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
178*6777b538SAndroid Build Coastguard Worker     // Now ask the kernel again and check that no restorer will leak.
179*6777b538SAndroid Build Coastguard Worker     if (sys_rt_sigaction(signum, nullptr, &act) || act.k_sa_restorer) {
180*6777b538SAndroid Build Coastguard Worker       RAW_LOG(FATAL, "Cound not fix sa_restorer.");
181*6777b538SAndroid Build Coastguard Worker     }
182*6777b538SAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
183*6777b538SAndroid Build Coastguard Worker   }
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker #endif  // !BUILDFLAG(IS_LINUX) ||
186*6777b538SAndroid Build Coastguard Worker         // (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__))
187*6777b538SAndroid Build Coastguard Worker }  // anonymous namespace
188*6777b538SAndroid Build Coastguard Worker 
189*6777b538SAndroid Build Coastguard Worker // Functor for |ScopedDIR| (below).
190*6777b538SAndroid Build Coastguard Worker struct ScopedDIRClose {
operator ()base::ScopedDIRClose191*6777b538SAndroid Build Coastguard Worker   inline void operator()(DIR* x) const {
192*6777b538SAndroid Build Coastguard Worker     if (x)
193*6777b538SAndroid Build Coastguard Worker       closedir(x);
194*6777b538SAndroid Build Coastguard Worker   }
195*6777b538SAndroid Build Coastguard Worker };
196*6777b538SAndroid Build Coastguard Worker 
197*6777b538SAndroid Build Coastguard Worker // Automatically closes |DIR*|s.
198*6777b538SAndroid Build Coastguard Worker typedef std::unique_ptr<DIR, ScopedDIRClose> ScopedDIR;
199*6777b538SAndroid Build Coastguard Worker 
200*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_AIX)
201*6777b538SAndroid Build Coastguard Worker static const char kFDDir[] = "/proc/self/fd";
202*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_SOLARIS)
203*6777b538SAndroid Build Coastguard Worker static const char kFDDir[] = "/dev/fd";
204*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_FREEBSD)
205*6777b538SAndroid Build Coastguard Worker static const char kFDDir[] = "/dev/fd";
206*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_OPENBSD)
207*6777b538SAndroid Build Coastguard Worker static const char kFDDir[] = "/dev/fd";
208*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_ANDROID)
209*6777b538SAndroid Build Coastguard Worker static const char kFDDir[] = "/proc/self/fd";
210*6777b538SAndroid Build Coastguard Worker #endif
211*6777b538SAndroid Build Coastguard Worker 
CloseSuperfluousFds(const base::InjectiveMultimap & saved_mapping)212*6777b538SAndroid Build Coastguard Worker void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
213*6777b538SAndroid Build Coastguard Worker   // DANGER: no calls to malloc or locks are allowed from now on:
214*6777b538SAndroid Build Coastguard Worker   // http://crbug.com/36678
215*6777b538SAndroid Build Coastguard Worker 
216*6777b538SAndroid Build Coastguard Worker   // Get the maximum number of FDs possible.
217*6777b538SAndroid Build Coastguard Worker   size_t max_fds = GetMaxFds();
218*6777b538SAndroid Build Coastguard Worker 
219*6777b538SAndroid Build Coastguard Worker   DirReaderPosix fd_dir(kFDDir);
220*6777b538SAndroid Build Coastguard Worker   if (!fd_dir.IsValid()) {
221*6777b538SAndroid Build Coastguard Worker     // Fallback case: Try every possible fd.
222*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < max_fds; ++i) {
223*6777b538SAndroid Build Coastguard Worker       const int fd = static_cast<int>(i);
224*6777b538SAndroid Build Coastguard Worker       if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
225*6777b538SAndroid Build Coastguard Worker         continue;
226*6777b538SAndroid Build Coastguard Worker       // Cannot use STL iterators here, since debug iterators use locks.
227*6777b538SAndroid Build Coastguard Worker       size_t j;
228*6777b538SAndroid Build Coastguard Worker       for (j = 0; j < saved_mapping.size(); j++) {
229*6777b538SAndroid Build Coastguard Worker         if (fd == saved_mapping[j].dest)
230*6777b538SAndroid Build Coastguard Worker           break;
231*6777b538SAndroid Build Coastguard Worker       }
232*6777b538SAndroid Build Coastguard Worker       if (j < saved_mapping.size())
233*6777b538SAndroid Build Coastguard Worker         continue;
234*6777b538SAndroid Build Coastguard Worker 
235*6777b538SAndroid Build Coastguard Worker       // Since we're just trying to close anything we can find,
236*6777b538SAndroid Build Coastguard Worker       // ignore any error return values of close().
237*6777b538SAndroid Build Coastguard Worker       close(fd);
238*6777b538SAndroid Build Coastguard Worker     }
239*6777b538SAndroid Build Coastguard Worker     return;
240*6777b538SAndroid Build Coastguard Worker   }
241*6777b538SAndroid Build Coastguard Worker 
242*6777b538SAndroid Build Coastguard Worker   const int dir_fd = fd_dir.fd();
243*6777b538SAndroid Build Coastguard Worker 
244*6777b538SAndroid Build Coastguard Worker   for ( ; fd_dir.Next(); ) {
245*6777b538SAndroid Build Coastguard Worker     // Skip . and .. entries.
246*6777b538SAndroid Build Coastguard Worker     if (fd_dir.name()[0] == '.')
247*6777b538SAndroid Build Coastguard Worker       continue;
248*6777b538SAndroid Build Coastguard Worker 
249*6777b538SAndroid Build Coastguard Worker     char *endptr;
250*6777b538SAndroid Build Coastguard Worker     errno = 0;
251*6777b538SAndroid Build Coastguard Worker     const long int fd = strtol(fd_dir.name(), &endptr, 10);
252*6777b538SAndroid Build Coastguard Worker     if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno ||
253*6777b538SAndroid Build Coastguard Worker         !IsValueInRangeForNumericType<int>(fd)) {
254*6777b538SAndroid Build Coastguard Worker       continue;
255*6777b538SAndroid Build Coastguard Worker     }
256*6777b538SAndroid Build Coastguard Worker     if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
257*6777b538SAndroid Build Coastguard Worker       continue;
258*6777b538SAndroid Build Coastguard Worker     // Cannot use STL iterators here, since debug iterators use locks.
259*6777b538SAndroid Build Coastguard Worker     size_t i;
260*6777b538SAndroid Build Coastguard Worker     for (i = 0; i < saved_mapping.size(); i++) {
261*6777b538SAndroid Build Coastguard Worker       if (fd == saved_mapping[i].dest)
262*6777b538SAndroid Build Coastguard Worker         break;
263*6777b538SAndroid Build Coastguard Worker     }
264*6777b538SAndroid Build Coastguard Worker     if (i < saved_mapping.size())
265*6777b538SAndroid Build Coastguard Worker       continue;
266*6777b538SAndroid Build Coastguard Worker     if (fd == dir_fd)
267*6777b538SAndroid Build Coastguard Worker       continue;
268*6777b538SAndroid Build Coastguard Worker 
269*6777b538SAndroid Build Coastguard Worker     int ret = IGNORE_EINTR(close(static_cast<int>(fd)));
270*6777b538SAndroid Build Coastguard Worker     DPCHECK(ret == 0);
271*6777b538SAndroid Build Coastguard Worker   }
272*6777b538SAndroid Build Coastguard Worker }
273*6777b538SAndroid Build Coastguard Worker 
LaunchProcess(const CommandLine & cmdline,const LaunchOptions & options)274*6777b538SAndroid Build Coastguard Worker Process LaunchProcess(const CommandLine& cmdline,
275*6777b538SAndroid Build Coastguard Worker                       const LaunchOptions& options) {
276*6777b538SAndroid Build Coastguard Worker   return LaunchProcess(cmdline.argv(), options);
277*6777b538SAndroid Build Coastguard Worker }
278*6777b538SAndroid Build Coastguard Worker 
LaunchProcess(const std::vector<std::string> & argv,const LaunchOptions & options)279*6777b538SAndroid Build Coastguard Worker Process LaunchProcess(const std::vector<std::string>& argv,
280*6777b538SAndroid Build Coastguard Worker                       const LaunchOptions& options) {
281*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0("base", "LaunchProcess");
282*6777b538SAndroid Build Coastguard Worker 
283*6777b538SAndroid Build Coastguard Worker   InjectiveMultimap fd_shuffle1;
284*6777b538SAndroid Build Coastguard Worker   InjectiveMultimap fd_shuffle2;
285*6777b538SAndroid Build Coastguard Worker   fd_shuffle1.reserve(options.fds_to_remap.size());
286*6777b538SAndroid Build Coastguard Worker   fd_shuffle2.reserve(options.fds_to_remap.size());
287*6777b538SAndroid Build Coastguard Worker 
288*6777b538SAndroid Build Coastguard Worker   std::vector<char*> argv_cstr;
289*6777b538SAndroid Build Coastguard Worker   argv_cstr.reserve(argv.size() + 1);
290*6777b538SAndroid Build Coastguard Worker   for (const auto& arg : argv)
291*6777b538SAndroid Build Coastguard Worker     argv_cstr.push_back(const_cast<char*>(arg.c_str()));
292*6777b538SAndroid Build Coastguard Worker   argv_cstr.push_back(nullptr);
293*6777b538SAndroid Build Coastguard Worker 
294*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<char* []> new_environ;
295*6777b538SAndroid Build Coastguard Worker   char* const empty_environ = nullptr;
296*6777b538SAndroid Build Coastguard Worker   char* const* old_environ = GetEnvironment();
297*6777b538SAndroid Build Coastguard Worker   if (options.clear_environment)
298*6777b538SAndroid Build Coastguard Worker     old_environ = &empty_environ;
299*6777b538SAndroid Build Coastguard Worker   if (!options.environment.empty())
300*6777b538SAndroid Build Coastguard Worker     new_environ = internal::AlterEnvironment(old_environ, options.environment);
301*6777b538SAndroid Build Coastguard Worker 
302*6777b538SAndroid Build Coastguard Worker   sigset_t full_sigset;
303*6777b538SAndroid Build Coastguard Worker   sigfillset(&full_sigset);
304*6777b538SAndroid Build Coastguard Worker   const sigset_t orig_sigmask = SetSignalMask(full_sigset);
305*6777b538SAndroid Build Coastguard Worker 
306*6777b538SAndroid Build Coastguard Worker   const char* current_directory = nullptr;
307*6777b538SAndroid Build Coastguard Worker   if (!options.current_directory.empty()) {
308*6777b538SAndroid Build Coastguard Worker     current_directory = options.current_directory.value().c_str();
309*6777b538SAndroid Build Coastguard Worker   }
310*6777b538SAndroid Build Coastguard Worker 
311*6777b538SAndroid Build Coastguard Worker   pid_t pid;
312*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_AIX)
313*6777b538SAndroid Build Coastguard Worker   if (options.clone_flags) {
314*6777b538SAndroid Build Coastguard Worker     // Signal handling in this function assumes the creation of a new
315*6777b538SAndroid Build Coastguard Worker     // process, so we check that a thread is not being created by mistake
316*6777b538SAndroid Build Coastguard Worker     // and that signal handling follows the process-creation rules.
317*6777b538SAndroid Build Coastguard Worker     RAW_CHECK(
318*6777b538SAndroid Build Coastguard Worker         !(options.clone_flags & (CLONE_SIGHAND | CLONE_THREAD | CLONE_VM)));
319*6777b538SAndroid Build Coastguard Worker 
320*6777b538SAndroid Build Coastguard Worker     // We specify a null ptid and ctid.
321*6777b538SAndroid Build Coastguard Worker     RAW_CHECK(
322*6777b538SAndroid Build Coastguard Worker         !(options.clone_flags &
323*6777b538SAndroid Build Coastguard Worker           (CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT_SETTID)));
324*6777b538SAndroid Build Coastguard Worker 
325*6777b538SAndroid Build Coastguard Worker     // Since we use waitpid, we do not support custom termination signals in the
326*6777b538SAndroid Build Coastguard Worker     // clone flags.
327*6777b538SAndroid Build Coastguard Worker     RAW_CHECK((options.clone_flags & 0xff) == 0);
328*6777b538SAndroid Build Coastguard Worker 
329*6777b538SAndroid Build Coastguard Worker     pid = ForkWithFlags(options.clone_flags | SIGCHLD, nullptr, nullptr);
330*6777b538SAndroid Build Coastguard Worker   } else
331*6777b538SAndroid Build Coastguard Worker #endif
332*6777b538SAndroid Build Coastguard Worker   {
333*6777b538SAndroid Build Coastguard Worker     pid = fork();
334*6777b538SAndroid Build Coastguard Worker   }
335*6777b538SAndroid Build Coastguard Worker 
336*6777b538SAndroid Build Coastguard Worker   // Always restore the original signal mask in the parent.
337*6777b538SAndroid Build Coastguard Worker   if (pid != 0) {
338*6777b538SAndroid Build Coastguard Worker     SetSignalMask(orig_sigmask);
339*6777b538SAndroid Build Coastguard Worker   }
340*6777b538SAndroid Build Coastguard Worker 
341*6777b538SAndroid Build Coastguard Worker   if (pid < 0) {
342*6777b538SAndroid Build Coastguard Worker     DPLOG(ERROR) << "fork";
343*6777b538SAndroid Build Coastguard Worker     return Process();
344*6777b538SAndroid Build Coastguard Worker   }
345*6777b538SAndroid Build Coastguard Worker   if (pid == 0) {
346*6777b538SAndroid Build Coastguard Worker     // Child process
347*6777b538SAndroid Build Coastguard Worker 
348*6777b538SAndroid Build Coastguard Worker     // DANGER: no calls to malloc or locks are allowed from now on:
349*6777b538SAndroid Build Coastguard Worker     // http://crbug.com/36678
350*6777b538SAndroid Build Coastguard Worker 
351*6777b538SAndroid Build Coastguard Worker     // DANGER: fork() rule: in the child, if you don't end up doing exec*(),
352*6777b538SAndroid Build Coastguard Worker     // you call _exit() instead of exit(). This is because _exit() does not
353*6777b538SAndroid Build Coastguard Worker     // call any previously-registered (in the parent) exit handlers, which
354*6777b538SAndroid Build Coastguard Worker     // might do things like block waiting for threads that don't even exist
355*6777b538SAndroid Build Coastguard Worker     // in the child.
356*6777b538SAndroid Build Coastguard Worker 
357*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
358*6777b538SAndroid Build Coastguard Worker     // See comments on the ResetFDOwnership() declaration in
359*6777b538SAndroid Build Coastguard Worker     // base/files/scoped_file.h regarding why this is called early here.
360*6777b538SAndroid Build Coastguard Worker     subtle::ResetFDOwnership();
361*6777b538SAndroid Build Coastguard Worker 
362*6777b538SAndroid Build Coastguard Worker     // The parent process might set FD_CLOEXEC flag on certain file
363*6777b538SAndroid Build Coastguard Worker     // descriptors to prevent them leaking into child processes of the
364*6777b538SAndroid Build Coastguard Worker     // embedder application. Remove the flag from the file descriptors
365*6777b538SAndroid Build Coastguard Worker     // which meant to be inherited by the child process.
366*6777b538SAndroid Build Coastguard Worker     //
367*6777b538SAndroid Build Coastguard Worker     // Cannot use STL iterators here, since debug iterators use locks.
368*6777b538SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(modernize-loop-convert)
369*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < options.fds_to_remove_cloexec.size(); ++i) {
370*6777b538SAndroid Build Coastguard Worker       if (!RemoveCloseOnExec(options.fds_to_remove_cloexec[i])) {
371*6777b538SAndroid Build Coastguard Worker         RAW_LOG(WARNING, "Failed to remove FD_CLOEXEC flag");
372*6777b538SAndroid Build Coastguard Worker       }
373*6777b538SAndroid Build Coastguard Worker     }
374*6777b538SAndroid Build Coastguard Worker #endif
375*6777b538SAndroid Build Coastguard Worker 
376*6777b538SAndroid Build Coastguard Worker     {
377*6777b538SAndroid Build Coastguard Worker       // If a child process uses the readline library, the process block
378*6777b538SAndroid Build Coastguard Worker       // forever. In BSD like OSes including OS X it is safe to assign /dev/null
379*6777b538SAndroid Build Coastguard Worker       // as stdin. See http://crbug.com/56596.
380*6777b538SAndroid Build Coastguard Worker       base::ScopedFD null_fd(HANDLE_EINTR(open("/dev/null", O_RDONLY)));
381*6777b538SAndroid Build Coastguard Worker       if (!null_fd.is_valid()) {
382*6777b538SAndroid Build Coastguard Worker         RAW_LOG(ERROR, "Failed to open /dev/null");
383*6777b538SAndroid Build Coastguard Worker         _exit(127);
384*6777b538SAndroid Build Coastguard Worker       }
385*6777b538SAndroid Build Coastguard Worker 
386*6777b538SAndroid Build Coastguard Worker       int new_fd = HANDLE_EINTR(dup2(null_fd.get(), STDIN_FILENO));
387*6777b538SAndroid Build Coastguard Worker       if (new_fd != STDIN_FILENO) {
388*6777b538SAndroid Build Coastguard Worker         RAW_LOG(ERROR, "Failed to dup /dev/null for stdin");
389*6777b538SAndroid Build Coastguard Worker         _exit(127);
390*6777b538SAndroid Build Coastguard Worker       }
391*6777b538SAndroid Build Coastguard Worker     }
392*6777b538SAndroid Build Coastguard Worker 
393*6777b538SAndroid Build Coastguard Worker     if (options.new_process_group) {
394*6777b538SAndroid Build Coastguard Worker       // Instead of inheriting the process group ID of the parent, the child
395*6777b538SAndroid Build Coastguard Worker       // starts off a new process group with pgid equal to its process ID.
396*6777b538SAndroid Build Coastguard Worker       if (setpgid(0, 0) < 0) {
397*6777b538SAndroid Build Coastguard Worker         RAW_LOG(ERROR, "setpgid failed");
398*6777b538SAndroid Build Coastguard Worker         _exit(127);
399*6777b538SAndroid Build Coastguard Worker       }
400*6777b538SAndroid Build Coastguard Worker     }
401*6777b538SAndroid Build Coastguard Worker 
402*6777b538SAndroid Build Coastguard Worker     if (options.maximize_rlimits) {
403*6777b538SAndroid Build Coastguard Worker       // Some resource limits need to be maximal in this child.
404*6777b538SAndroid Build Coastguard Worker       for (auto resource : *options.maximize_rlimits) {
405*6777b538SAndroid Build Coastguard Worker         struct rlimit limit;
406*6777b538SAndroid Build Coastguard Worker         if (getrlimit(resource, &limit) < 0) {
407*6777b538SAndroid Build Coastguard Worker           RAW_LOG(WARNING, "getrlimit failed");
408*6777b538SAndroid Build Coastguard Worker         } else if (limit.rlim_cur < limit.rlim_max) {
409*6777b538SAndroid Build Coastguard Worker           limit.rlim_cur = limit.rlim_max;
410*6777b538SAndroid Build Coastguard Worker           if (setrlimit(resource, &limit) < 0) {
411*6777b538SAndroid Build Coastguard Worker             RAW_LOG(WARNING, "setrlimit failed");
412*6777b538SAndroid Build Coastguard Worker           }
413*6777b538SAndroid Build Coastguard Worker         }
414*6777b538SAndroid Build Coastguard Worker       }
415*6777b538SAndroid Build Coastguard Worker     }
416*6777b538SAndroid Build Coastguard Worker 
417*6777b538SAndroid Build Coastguard Worker     ResetChildSignalHandlersToDefaults();
418*6777b538SAndroid Build Coastguard Worker     SetSignalMask(orig_sigmask);
419*6777b538SAndroid Build Coastguard Worker 
420*6777b538SAndroid Build Coastguard Worker #if 0
421*6777b538SAndroid Build Coastguard Worker     // When debugging it can be helpful to check that we really aren't making
422*6777b538SAndroid Build Coastguard Worker     // any hidden calls to malloc.
423*6777b538SAndroid Build Coastguard Worker     void *malloc_thunk =
424*6777b538SAndroid Build Coastguard Worker         reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095);
425*6777b538SAndroid Build Coastguard Worker     HANDLE_EINTR(mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC));
426*6777b538SAndroid Build Coastguard Worker     memset(reinterpret_cast<void*>(malloc), 0xff, 8);
427*6777b538SAndroid Build Coastguard Worker #endif  // 0
428*6777b538SAndroid Build Coastguard Worker 
429*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
430*6777b538SAndroid Build Coastguard Worker     if (options.ctrl_terminal_fd >= 0) {
431*6777b538SAndroid Build Coastguard Worker       // Set process' controlling terminal.
432*6777b538SAndroid Build Coastguard Worker       if (HANDLE_EINTR(setsid()) != -1) {
433*6777b538SAndroid Build Coastguard Worker         if (HANDLE_EINTR(
434*6777b538SAndroid Build Coastguard Worker                 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, nullptr)) == -1) {
435*6777b538SAndroid Build Coastguard Worker           RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set");
436*6777b538SAndroid Build Coastguard Worker         }
437*6777b538SAndroid Build Coastguard Worker       } else {
438*6777b538SAndroid Build Coastguard Worker         RAW_LOG(WARNING, "setsid failed, ctrl terminal not set");
439*6777b538SAndroid Build Coastguard Worker       }
440*6777b538SAndroid Build Coastguard Worker     }
441*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_CHROMEOS)
442*6777b538SAndroid Build Coastguard Worker 
443*6777b538SAndroid Build Coastguard Worker     // Cannot use STL iterators here, since debug iterators use locks.
444*6777b538SAndroid Build Coastguard Worker     // NOLINTNEXTLINE(modernize-loop-convert)
445*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < options.fds_to_remap.size(); ++i) {
446*6777b538SAndroid Build Coastguard Worker       const FileHandleMappingVector::value_type& value =
447*6777b538SAndroid Build Coastguard Worker           options.fds_to_remap[i];
448*6777b538SAndroid Build Coastguard Worker       fd_shuffle1.push_back(InjectionArc(value.first, value.second, false));
449*6777b538SAndroid Build Coastguard Worker       fd_shuffle2.push_back(InjectionArc(value.first, value.second, false));
450*6777b538SAndroid Build Coastguard Worker     }
451*6777b538SAndroid Build Coastguard Worker 
452*6777b538SAndroid Build Coastguard Worker     if (!options.environment.empty() || options.clear_environment)
453*6777b538SAndroid Build Coastguard Worker       SetEnvironment(new_environ.get());
454*6777b538SAndroid Build Coastguard Worker 
455*6777b538SAndroid Build Coastguard Worker     // fd_shuffle1 is mutated by this call because it cannot malloc.
456*6777b538SAndroid Build Coastguard Worker     if (!ShuffleFileDescriptors(&fd_shuffle1))
457*6777b538SAndroid Build Coastguard Worker       _exit(127);
458*6777b538SAndroid Build Coastguard Worker 
459*6777b538SAndroid Build Coastguard Worker     CloseSuperfluousFds(fd_shuffle2);
460*6777b538SAndroid Build Coastguard Worker 
461*6777b538SAndroid Build Coastguard Worker     // Set NO_NEW_PRIVS by default. Since NO_NEW_PRIVS only exists in kernel
462*6777b538SAndroid Build Coastguard Worker     // 3.5+, do not check the return value of prctl here.
463*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_AIX)
464*6777b538SAndroid Build Coastguard Worker #ifndef PR_SET_NO_NEW_PRIVS
465*6777b538SAndroid Build Coastguard Worker #define PR_SET_NO_NEW_PRIVS 38
466*6777b538SAndroid Build Coastguard Worker #endif
467*6777b538SAndroid Build Coastguard Worker     if (!options.allow_new_privs) {
468*6777b538SAndroid Build Coastguard Worker       if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) && errno != EINVAL) {
469*6777b538SAndroid Build Coastguard Worker         // Only log if the error is not EINVAL (i.e. not supported).
470*6777b538SAndroid Build Coastguard Worker         RAW_LOG(FATAL, "prctl(PR_SET_NO_NEW_PRIVS) failed");
471*6777b538SAndroid Build Coastguard Worker       }
472*6777b538SAndroid Build Coastguard Worker     }
473*6777b538SAndroid Build Coastguard Worker 
474*6777b538SAndroid Build Coastguard Worker     if (options.kill_on_parent_death) {
475*6777b538SAndroid Build Coastguard Worker       if (prctl(PR_SET_PDEATHSIG, SIGKILL) != 0) {
476*6777b538SAndroid Build Coastguard Worker         RAW_LOG(ERROR, "prctl(PR_SET_PDEATHSIG) failed");
477*6777b538SAndroid Build Coastguard Worker         _exit(127);
478*6777b538SAndroid Build Coastguard Worker       }
479*6777b538SAndroid Build Coastguard Worker     }
480*6777b538SAndroid Build Coastguard Worker #endif
481*6777b538SAndroid Build Coastguard Worker 
482*6777b538SAndroid Build Coastguard Worker     if (current_directory != nullptr) {
483*6777b538SAndroid Build Coastguard Worker       RAW_CHECK(chdir(current_directory) == 0);
484*6777b538SAndroid Build Coastguard Worker     }
485*6777b538SAndroid Build Coastguard Worker 
486*6777b538SAndroid Build Coastguard Worker     if (options.pre_exec_delegate != nullptr) {
487*6777b538SAndroid Build Coastguard Worker       options.pre_exec_delegate->RunAsyncSafe();
488*6777b538SAndroid Build Coastguard Worker     }
489*6777b538SAndroid Build Coastguard Worker 
490*6777b538SAndroid Build Coastguard Worker     const char* executable_path = !options.real_path.empty() ?
491*6777b538SAndroid Build Coastguard Worker         options.real_path.value().c_str() : argv_cstr[0];
492*6777b538SAndroid Build Coastguard Worker 
493*6777b538SAndroid Build Coastguard Worker     execvp(executable_path, argv_cstr.data());
494*6777b538SAndroid Build Coastguard Worker 
495*6777b538SAndroid Build Coastguard Worker     RAW_LOG(ERROR, "LaunchProcess: failed to execvp:");
496*6777b538SAndroid Build Coastguard Worker     RAW_LOG(ERROR, argv_cstr[0]);
497*6777b538SAndroid Build Coastguard Worker     _exit(127);
498*6777b538SAndroid Build Coastguard Worker   } else {
499*6777b538SAndroid Build Coastguard Worker     // Parent process
500*6777b538SAndroid Build Coastguard Worker     if (options.wait) {
501*6777b538SAndroid Build Coastguard Worker       // While this isn't strictly disk IO, waiting for another process to
502*6777b538SAndroid Build Coastguard Worker       // finish is the sort of thing ThreadRestrictions is trying to prevent.
503*6777b538SAndroid Build Coastguard Worker       ScopedBlockingCall scoped_blocking_call(FROM_HERE,
504*6777b538SAndroid Build Coastguard Worker                                               BlockingType::MAY_BLOCK);
505*6777b538SAndroid Build Coastguard Worker       pid_t ret = HANDLE_EINTR(waitpid(pid, nullptr, 0));
506*6777b538SAndroid Build Coastguard Worker       DPCHECK(ret > 0);
507*6777b538SAndroid Build Coastguard Worker     }
508*6777b538SAndroid Build Coastguard Worker   }
509*6777b538SAndroid Build Coastguard Worker 
510*6777b538SAndroid Build Coastguard Worker   return Process(pid);
511*6777b538SAndroid Build Coastguard Worker }
512*6777b538SAndroid Build Coastguard Worker 
RaiseProcessToHighPriority()513*6777b538SAndroid Build Coastguard Worker void RaiseProcessToHighPriority() {
514*6777b538SAndroid Build Coastguard Worker   // On POSIX, we don't actually do anything here.  We could try to nice() or
515*6777b538SAndroid Build Coastguard Worker   // setpriority() or sched_getscheduler, but these all require extra rights.
516*6777b538SAndroid Build Coastguard Worker }
517*6777b538SAndroid Build Coastguard Worker 
518*6777b538SAndroid Build Coastguard Worker // Executes the application specified by |argv| and wait for it to exit. Stores
519*6777b538SAndroid Build Coastguard Worker // the output (stdout) in |output|. If |do_search_path| is set, it searches the
520*6777b538SAndroid Build Coastguard Worker // path for the application; in that case, |envp| must be null, and it will use
521*6777b538SAndroid Build Coastguard Worker // the current environment. If |do_search_path| is false, |argv[0]| should fully
522*6777b538SAndroid Build Coastguard Worker // specify the path of the application, and |envp| will be used as the
523*6777b538SAndroid Build Coastguard Worker // environment. If |include_stderr| is true, includes stderr otherwise redirects
524*6777b538SAndroid Build Coastguard Worker // it to /dev/null.
525*6777b538SAndroid Build Coastguard Worker // The return value of the function indicates success or failure. In the case of
526*6777b538SAndroid Build Coastguard Worker // success, the application exit code will be returned in |*exit_code|, which
527*6777b538SAndroid Build Coastguard Worker // should be checked to determine if the application ran successfully.
GetAppOutputInternal(const std::vector<std::string> & argv,char * const envp[],bool include_stderr,std::string * output,bool do_search_path,int * exit_code)528*6777b538SAndroid Build Coastguard Worker static bool GetAppOutputInternal(
529*6777b538SAndroid Build Coastguard Worker     const std::vector<std::string>& argv,
530*6777b538SAndroid Build Coastguard Worker     char* const envp[],
531*6777b538SAndroid Build Coastguard Worker     bool include_stderr,
532*6777b538SAndroid Build Coastguard Worker     std::string* output,
533*6777b538SAndroid Build Coastguard Worker     bool do_search_path,
534*6777b538SAndroid Build Coastguard Worker     int* exit_code) {
535*6777b538SAndroid Build Coastguard Worker   // exit_code must be supplied so calling function can determine success.
536*6777b538SAndroid Build Coastguard Worker   DCHECK(exit_code);
537*6777b538SAndroid Build Coastguard Worker   *exit_code = EXIT_FAILURE;
538*6777b538SAndroid Build Coastguard Worker 
539*6777b538SAndroid Build Coastguard Worker   // Declare and call reserve() here before calling fork() because the child
540*6777b538SAndroid Build Coastguard Worker   // process cannot allocate memory.
541*6777b538SAndroid Build Coastguard Worker   std::vector<char*> argv_cstr;
542*6777b538SAndroid Build Coastguard Worker   argv_cstr.reserve(argv.size() + 1);
543*6777b538SAndroid Build Coastguard Worker   InjectiveMultimap fd_shuffle1;
544*6777b538SAndroid Build Coastguard Worker   InjectiveMultimap fd_shuffle2;
545*6777b538SAndroid Build Coastguard Worker   fd_shuffle1.reserve(3);
546*6777b538SAndroid Build Coastguard Worker   fd_shuffle2.reserve(3);
547*6777b538SAndroid Build Coastguard Worker 
548*6777b538SAndroid Build Coastguard Worker   // Either |do_search_path| should be false or |envp| should be null, but not
549*6777b538SAndroid Build Coastguard Worker   // both.
550*6777b538SAndroid Build Coastguard Worker   DCHECK(!do_search_path ^ !envp);
551*6777b538SAndroid Build Coastguard Worker 
552*6777b538SAndroid Build Coastguard Worker   int pipe_fd[2];
553*6777b538SAndroid Build Coastguard Worker   if (pipe(pipe_fd) < 0)
554*6777b538SAndroid Build Coastguard Worker     return false;
555*6777b538SAndroid Build Coastguard Worker 
556*6777b538SAndroid Build Coastguard Worker   pid_t pid = fork();
557*6777b538SAndroid Build Coastguard Worker   switch (pid) {
558*6777b538SAndroid Build Coastguard Worker     case -1: {
559*6777b538SAndroid Build Coastguard Worker       // error
560*6777b538SAndroid Build Coastguard Worker       close(pipe_fd[0]);
561*6777b538SAndroid Build Coastguard Worker       close(pipe_fd[1]);
562*6777b538SAndroid Build Coastguard Worker       return false;
563*6777b538SAndroid Build Coastguard Worker     }
564*6777b538SAndroid Build Coastguard Worker     case 0: {
565*6777b538SAndroid Build Coastguard Worker       // child
566*6777b538SAndroid Build Coastguard Worker       //
567*6777b538SAndroid Build Coastguard Worker       // DANGER: no calls to malloc or locks are allowed from now on:
568*6777b538SAndroid Build Coastguard Worker       // http://crbug.com/36678
569*6777b538SAndroid Build Coastguard Worker 
570*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
571*6777b538SAndroid Build Coastguard Worker       // See comments on the ResetFDOwnership() declaration in
572*6777b538SAndroid Build Coastguard Worker       // base/files/scoped_file.h regarding why this is called early here.
573*6777b538SAndroid Build Coastguard Worker       subtle::ResetFDOwnership();
574*6777b538SAndroid Build Coastguard Worker #endif
575*6777b538SAndroid Build Coastguard Worker 
576*6777b538SAndroid Build Coastguard Worker       // Obscure fork() rule: in the child, if you don't end up doing exec*(),
577*6777b538SAndroid Build Coastguard Worker       // you call _exit() instead of exit(). This is because _exit() does not
578*6777b538SAndroid Build Coastguard Worker       // call any previously-registered (in the parent) exit handlers, which
579*6777b538SAndroid Build Coastguard Worker       // might do things like block waiting for threads that don't even exist
580*6777b538SAndroid Build Coastguard Worker       // in the child.
581*6777b538SAndroid Build Coastguard Worker       int dev_null = open("/dev/null", O_WRONLY);
582*6777b538SAndroid Build Coastguard Worker       if (dev_null < 0)
583*6777b538SAndroid Build Coastguard Worker         _exit(127);
584*6777b538SAndroid Build Coastguard Worker 
585*6777b538SAndroid Build Coastguard Worker       fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
586*6777b538SAndroid Build Coastguard Worker       fd_shuffle1.push_back(InjectionArc(include_stderr ? pipe_fd[1] : dev_null,
587*6777b538SAndroid Build Coastguard Worker                                          STDERR_FILENO, true));
588*6777b538SAndroid Build Coastguard Worker       fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
589*6777b538SAndroid Build Coastguard Worker       // Adding another element here? Remeber to increase the argument to
590*6777b538SAndroid Build Coastguard Worker       // reserve(), above.
591*6777b538SAndroid Build Coastguard Worker 
592*6777b538SAndroid Build Coastguard Worker       // Cannot use STL iterators here, since debug iterators use locks.
593*6777b538SAndroid Build Coastguard Worker       // NOLINTNEXTLINE(modernize-loop-convert)
594*6777b538SAndroid Build Coastguard Worker       for (size_t i = 0; i < fd_shuffle1.size(); ++i)
595*6777b538SAndroid Build Coastguard Worker         fd_shuffle2.push_back(fd_shuffle1[i]);
596*6777b538SAndroid Build Coastguard Worker 
597*6777b538SAndroid Build Coastguard Worker       if (!ShuffleFileDescriptors(&fd_shuffle1))
598*6777b538SAndroid Build Coastguard Worker         _exit(127);
599*6777b538SAndroid Build Coastguard Worker 
600*6777b538SAndroid Build Coastguard Worker       CloseSuperfluousFds(fd_shuffle2);
601*6777b538SAndroid Build Coastguard Worker 
602*6777b538SAndroid Build Coastguard Worker       // Cannot use STL iterators here, since debug iterators use locks.
603*6777b538SAndroid Build Coastguard Worker       // NOLINTNEXTLINE(modernize-loop-convert)
604*6777b538SAndroid Build Coastguard Worker       for (size_t i = 0; i < argv.size(); ++i)
605*6777b538SAndroid Build Coastguard Worker         argv_cstr.push_back(const_cast<char*>(argv[i].c_str()));
606*6777b538SAndroid Build Coastguard Worker       argv_cstr.push_back(nullptr);
607*6777b538SAndroid Build Coastguard Worker 
608*6777b538SAndroid Build Coastguard Worker       if (do_search_path)
609*6777b538SAndroid Build Coastguard Worker         execvp(argv_cstr[0], argv_cstr.data());
610*6777b538SAndroid Build Coastguard Worker       else
611*6777b538SAndroid Build Coastguard Worker         execve(argv_cstr[0], argv_cstr.data(), envp);
612*6777b538SAndroid Build Coastguard Worker       _exit(127);
613*6777b538SAndroid Build Coastguard Worker     }
614*6777b538SAndroid Build Coastguard Worker     default: {
615*6777b538SAndroid Build Coastguard Worker       // parent
616*6777b538SAndroid Build Coastguard Worker       //
617*6777b538SAndroid Build Coastguard Worker       // Close our writing end of pipe now. Otherwise later read would not
618*6777b538SAndroid Build Coastguard Worker       // be able to detect end of child's output (in theory we could still
619*6777b538SAndroid Build Coastguard Worker       // write to the pipe).
620*6777b538SAndroid Build Coastguard Worker       close(pipe_fd[1]);
621*6777b538SAndroid Build Coastguard Worker 
622*6777b538SAndroid Build Coastguard Worker       TRACE_EVENT0("base", "GetAppOutput");
623*6777b538SAndroid Build Coastguard Worker 
624*6777b538SAndroid Build Coastguard Worker       output->clear();
625*6777b538SAndroid Build Coastguard Worker 
626*6777b538SAndroid Build Coastguard Worker       while (true) {
627*6777b538SAndroid Build Coastguard Worker         char buffer[256];
628*6777b538SAndroid Build Coastguard Worker         ssize_t bytes_read =
629*6777b538SAndroid Build Coastguard Worker             HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer)));
630*6777b538SAndroid Build Coastguard Worker         if (bytes_read <= 0)
631*6777b538SAndroid Build Coastguard Worker           break;
632*6777b538SAndroid Build Coastguard Worker         output->append(buffer, static_cast<size_t>(bytes_read));
633*6777b538SAndroid Build Coastguard Worker       }
634*6777b538SAndroid Build Coastguard Worker       close(pipe_fd[0]);
635*6777b538SAndroid Build Coastguard Worker 
636*6777b538SAndroid Build Coastguard Worker       // Always wait for exit code (even if we know we'll declare
637*6777b538SAndroid Build Coastguard Worker       // GOT_MAX_OUTPUT).
638*6777b538SAndroid Build Coastguard Worker       Process process(pid);
639*6777b538SAndroid Build Coastguard Worker       // It is okay to allow this process to wait on the launched process as a
640*6777b538SAndroid Build Coastguard Worker       // process launched with GetAppOutput*() shouldn't wait back on the
641*6777b538SAndroid Build Coastguard Worker       // process that launched it.
642*6777b538SAndroid Build Coastguard Worker       internal::GetAppOutputScopedAllowBaseSyncPrimitives allow_wait;
643*6777b538SAndroid Build Coastguard Worker       return process.WaitForExit(exit_code);
644*6777b538SAndroid Build Coastguard Worker     }
645*6777b538SAndroid Build Coastguard Worker   }
646*6777b538SAndroid Build Coastguard Worker }
647*6777b538SAndroid Build Coastguard Worker 
GetAppOutput(const CommandLine & cl,std::string * output)648*6777b538SAndroid Build Coastguard Worker bool GetAppOutput(const CommandLine& cl, std::string* output) {
649*6777b538SAndroid Build Coastguard Worker   return GetAppOutput(cl.argv(), output);
650*6777b538SAndroid Build Coastguard Worker }
651*6777b538SAndroid Build Coastguard Worker 
GetAppOutput(const std::vector<std::string> & argv,std::string * output)652*6777b538SAndroid Build Coastguard Worker bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) {
653*6777b538SAndroid Build Coastguard Worker   // Run |execve()| with the current environment.
654*6777b538SAndroid Build Coastguard Worker   int exit_code;
655*6777b538SAndroid Build Coastguard Worker   bool result =
656*6777b538SAndroid Build Coastguard Worker       GetAppOutputInternal(argv, nullptr, false, output, true, &exit_code);
657*6777b538SAndroid Build Coastguard Worker   return result && exit_code == EXIT_SUCCESS;
658*6777b538SAndroid Build Coastguard Worker }
659*6777b538SAndroid Build Coastguard Worker 
GetAppOutputAndError(const CommandLine & cl,std::string * output)660*6777b538SAndroid Build Coastguard Worker bool GetAppOutputAndError(const CommandLine& cl, std::string* output) {
661*6777b538SAndroid Build Coastguard Worker   // Run |execve()| with the current environment.
662*6777b538SAndroid Build Coastguard Worker   int exit_code;
663*6777b538SAndroid Build Coastguard Worker   bool result =
664*6777b538SAndroid Build Coastguard Worker       GetAppOutputInternal(cl.argv(), nullptr, true, output, true, &exit_code);
665*6777b538SAndroid Build Coastguard Worker   return result && exit_code == EXIT_SUCCESS;
666*6777b538SAndroid Build Coastguard Worker }
667*6777b538SAndroid Build Coastguard Worker 
GetAppOutputAndError(const std::vector<std::string> & argv,std::string * output)668*6777b538SAndroid Build Coastguard Worker bool GetAppOutputAndError(const std::vector<std::string>& argv,
669*6777b538SAndroid Build Coastguard Worker                           std::string* output) {
670*6777b538SAndroid Build Coastguard Worker   int exit_code;
671*6777b538SAndroid Build Coastguard Worker   bool result =
672*6777b538SAndroid Build Coastguard Worker       GetAppOutputInternal(argv, nullptr, true, output, true, &exit_code);
673*6777b538SAndroid Build Coastguard Worker   return result && exit_code == EXIT_SUCCESS;
674*6777b538SAndroid Build Coastguard Worker }
675*6777b538SAndroid Build Coastguard Worker 
GetAppOutputWithExitCode(const CommandLine & cl,std::string * output,int * exit_code)676*6777b538SAndroid Build Coastguard Worker bool GetAppOutputWithExitCode(const CommandLine& cl,
677*6777b538SAndroid Build Coastguard Worker                               std::string* output,
678*6777b538SAndroid Build Coastguard Worker                               int* exit_code) {
679*6777b538SAndroid Build Coastguard Worker   // Run |execve()| with the current environment.
680*6777b538SAndroid Build Coastguard Worker   return GetAppOutputInternal(cl.argv(), nullptr, false, output, true,
681*6777b538SAndroid Build Coastguard Worker                               exit_code);
682*6777b538SAndroid Build Coastguard Worker }
683*6777b538SAndroid Build Coastguard Worker 
684*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_AIX)
685*6777b538SAndroid Build Coastguard Worker namespace {
686*6777b538SAndroid Build Coastguard Worker 
687*6777b538SAndroid Build Coastguard Worker // This function runs on the stack specified on the clone call. It uses longjmp
688*6777b538SAndroid Build Coastguard Worker // to switch back to the original stack so the child can return from sys_clone.
CloneHelper(void * arg)689*6777b538SAndroid Build Coastguard Worker int CloneHelper(void* arg) {
690*6777b538SAndroid Build Coastguard Worker   jmp_buf* env_ptr = reinterpret_cast<jmp_buf*>(arg);
691*6777b538SAndroid Build Coastguard Worker   longjmp(*env_ptr, 1);
692*6777b538SAndroid Build Coastguard Worker 
693*6777b538SAndroid Build Coastguard Worker   // Should not be reached.
694*6777b538SAndroid Build Coastguard Worker   RAW_CHECK(false);
695*6777b538SAndroid Build Coastguard Worker   return 1;
696*6777b538SAndroid Build Coastguard Worker }
697*6777b538SAndroid Build Coastguard Worker 
698*6777b538SAndroid Build Coastguard Worker // This function is noinline to ensure that stack_buf is below the stack pointer
699*6777b538SAndroid Build Coastguard Worker // that is saved when setjmp is called below. This is needed because when
700*6777b538SAndroid Build Coastguard Worker // compiled with FORTIFY_SOURCE, glibc's longjmp checks that the stack is moved
701*6777b538SAndroid Build Coastguard Worker // upwards. See crbug.com/442912 for more details.
702*6777b538SAndroid Build Coastguard Worker #if defined(ADDRESS_SANITIZER)
703*6777b538SAndroid Build Coastguard Worker // Disable AddressSanitizer instrumentation for this function to make sure
704*6777b538SAndroid Build Coastguard Worker // |stack_buf| is allocated on thread stack instead of ASan's fake stack.
705*6777b538SAndroid Build Coastguard Worker // Under ASan longjmp() will attempt to clean up the area between the old and
706*6777b538SAndroid Build Coastguard Worker // new stack pointers and print a warning that may confuse the user.
707*6777b538SAndroid Build Coastguard Worker NOINLINE __attribute__((no_sanitize_address)) pid_t
CloneAndLongjmpInChild(int flags,pid_t * ptid,pid_t * ctid,jmp_buf * env)708*6777b538SAndroid Build Coastguard Worker CloneAndLongjmpInChild(int flags, pid_t* ptid, pid_t* ctid, jmp_buf* env) {
709*6777b538SAndroid Build Coastguard Worker #else
710*6777b538SAndroid Build Coastguard Worker NOINLINE pid_t CloneAndLongjmpInChild(int flags,
711*6777b538SAndroid Build Coastguard Worker                                       pid_t* ptid,
712*6777b538SAndroid Build Coastguard Worker                                       pid_t* ctid,
713*6777b538SAndroid Build Coastguard Worker                                       jmp_buf* env) {
714*6777b538SAndroid Build Coastguard Worker #endif
715*6777b538SAndroid Build Coastguard Worker   // We use the libc clone wrapper instead of making the syscall
716*6777b538SAndroid Build Coastguard Worker   // directly because making the syscall may fail to update the libc's
717*6777b538SAndroid Build Coastguard Worker   // internal pid cache. The libc interface unfortunately requires
718*6777b538SAndroid Build Coastguard Worker   // specifying a new stack, so we use setjmp/longjmp to emulate
719*6777b538SAndroid Build Coastguard Worker   // fork-like behavior.
720*6777b538SAndroid Build Coastguard Worker   alignas(16) char stack_buf[PTHREAD_STACK_MIN];
721*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) ||         \
722*6777b538SAndroid Build Coastguard Worker     defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_S390_FAMILY) ||       \
723*6777b538SAndroid Build Coastguard Worker     defined(ARCH_CPU_PPC64_FAMILY) || defined(ARCH_CPU_LOONGARCH_FAMILY) || \
724*6777b538SAndroid Build Coastguard Worker     defined(ARCH_CPU_RISCV_FAMILY)
725*6777b538SAndroid Build Coastguard Worker   // The stack grows downward.
726*6777b538SAndroid Build Coastguard Worker   void* stack = stack_buf + sizeof(stack_buf);
727*6777b538SAndroid Build Coastguard Worker #else
728*6777b538SAndroid Build Coastguard Worker #error "Unsupported architecture"
729*6777b538SAndroid Build Coastguard Worker #endif
730*6777b538SAndroid Build Coastguard Worker   return clone(&CloneHelper, stack, flags, env, ptid, nullptr, ctid);
731*6777b538SAndroid Build Coastguard Worker }
732*6777b538SAndroid Build Coastguard Worker 
733*6777b538SAndroid Build Coastguard Worker }  // anonymous namespace
734*6777b538SAndroid Build Coastguard Worker 
ForkWithFlags(int flags,pid_t * ptid,pid_t * ctid)735*6777b538SAndroid Build Coastguard Worker pid_t ForkWithFlags(int flags, pid_t* ptid, pid_t* ctid) {
736*6777b538SAndroid Build Coastguard Worker   const bool clone_tls_used = flags & CLONE_SETTLS;
737*6777b538SAndroid Build Coastguard Worker   const bool invalid_ctid =
738*6777b538SAndroid Build Coastguard Worker       (flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && !ctid;
739*6777b538SAndroid Build Coastguard Worker   const bool invalid_ptid = (flags & CLONE_PARENT_SETTID) && !ptid;
740*6777b538SAndroid Build Coastguard Worker 
741*6777b538SAndroid Build Coastguard Worker   // We do not support CLONE_VM.
742*6777b538SAndroid Build Coastguard Worker   const bool clone_vm_used = flags & CLONE_VM;
743*6777b538SAndroid Build Coastguard Worker 
744*6777b538SAndroid Build Coastguard Worker   if (clone_tls_used || invalid_ctid || invalid_ptid || clone_vm_used) {
745*6777b538SAndroid Build Coastguard Worker     RAW_LOG(FATAL, "Invalid usage of ForkWithFlags");
746*6777b538SAndroid Build Coastguard Worker   }
747*6777b538SAndroid Build Coastguard Worker 
748*6777b538SAndroid Build Coastguard Worker   jmp_buf env;
749*6777b538SAndroid Build Coastguard Worker   if (setjmp(env) == 0) {
750*6777b538SAndroid Build Coastguard Worker     return CloneAndLongjmpInChild(flags, ptid, ctid, &env);
751*6777b538SAndroid Build Coastguard Worker   }
752*6777b538SAndroid Build Coastguard Worker 
753*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
754*6777b538SAndroid Build Coastguard Worker   // Since we use clone() directly, it does not call any pthread_aftork()
755*6777b538SAndroid Build Coastguard Worker   // callbacks, we explicitly invalidate tid cache here (normally this call is
756*6777b538SAndroid Build Coastguard Worker   // done as pthread_aftork() callback).  See crbug.com/902514.
757*6777b538SAndroid Build Coastguard Worker   base::internal::InvalidateTidCache();
758*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
759*6777b538SAndroid Build Coastguard Worker 
760*6777b538SAndroid Build Coastguard Worker   return 0;
761*6777b538SAndroid Build Coastguard Worker }
762*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_AIX)
763*6777b538SAndroid Build Coastguard Worker 
764*6777b538SAndroid Build Coastguard Worker }  // namespace base
765