xref: /openbsd-src/gnu/llvm/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- ProcessLauncherPosixFork.cpp --------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
10061da546Spatrick #include "lldb/Host/Host.h"
11061da546Spatrick #include "lldb/Host/HostProcess.h"
12061da546Spatrick #include "lldb/Host/Pipe.h"
13061da546Spatrick #include "lldb/Host/ProcessLaunchInfo.h"
14061da546Spatrick #include "lldb/Utility/FileSpec.h"
15061da546Spatrick #include "lldb/Utility/Log.h"
16061da546Spatrick #include "llvm/Support/Errno.h"
17*f6aab3d8Srobert #include "llvm/Support/FileSystem.h"
18061da546Spatrick 
19be691f3bSpatrick #include <climits>
20061da546Spatrick #include <sys/ptrace.h>
21061da546Spatrick #include <sys/wait.h>
22061da546Spatrick #include <unistd.h>
23061da546Spatrick 
24061da546Spatrick #include <sstream>
25061da546Spatrick #include <csignal>
26061da546Spatrick 
27061da546Spatrick #ifdef __ANDROID__
28061da546Spatrick #include <android/api-level.h>
29061da546Spatrick #define PT_TRACE_ME PTRACE_TRACEME
30061da546Spatrick #endif
31061da546Spatrick 
32061da546Spatrick #if defined(__ANDROID_API__) && __ANDROID_API__ < 15
33061da546Spatrick #include <linux/personality.h>
34061da546Spatrick #elif defined(__linux__)
35061da546Spatrick #include <sys/personality.h>
36061da546Spatrick #endif
37061da546Spatrick 
38061da546Spatrick using namespace lldb;
39061da546Spatrick using namespace lldb_private;
40061da546Spatrick 
41*f6aab3d8Srobert // Begin code running in the child process
42*f6aab3d8Srobert // NB: This code needs to be async-signal safe, since we're invoking fork from
43*f6aab3d8Srobert // multithreaded contexts.
44*f6aab3d8Srobert 
write_string(int error_fd,const char * str)45*f6aab3d8Srobert static void write_string(int error_fd, const char *str) {
46*f6aab3d8Srobert   int r = write(error_fd, str, strlen(str));
47*f6aab3d8Srobert   (void)r;
48061da546Spatrick }
49061da546Spatrick 
ExitWithError(int error_fd,const char * operation)50*f6aab3d8Srobert [[noreturn]] static void ExitWithError(int error_fd,
51061da546Spatrick                                        const char *operation) {
52061da546Spatrick   int err = errno;
53*f6aab3d8Srobert   write_string(error_fd, operation);
54*f6aab3d8Srobert   write_string(error_fd, " failed: ");
55*f6aab3d8Srobert   // strerror is not guaranteed to be async-signal safe, but it usually is.
56*f6aab3d8Srobert   write_string(error_fd, strerror(err));
57061da546Spatrick   _exit(1);
58061da546Spatrick }
59061da546Spatrick 
DisableASLR(int error_fd)60*f6aab3d8Srobert static void DisableASLR(int error_fd) {
61061da546Spatrick #if defined(__linux__)
62061da546Spatrick   const unsigned long personality_get_current = 0xffffffff;
63061da546Spatrick   int value = personality(personality_get_current);
64061da546Spatrick   if (value == -1)
65061da546Spatrick     ExitWithError(error_fd, "personality get");
66061da546Spatrick 
67061da546Spatrick   value = personality(ADDR_NO_RANDOMIZE | value);
68061da546Spatrick   if (value == -1)
69061da546Spatrick     ExitWithError(error_fd, "personality set");
70061da546Spatrick #endif
71061da546Spatrick }
72061da546Spatrick 
DupDescriptor(int error_fd,const char * file,int fd,int flags)73*f6aab3d8Srobert static void DupDescriptor(int error_fd, const char *file, int fd, int flags) {
74*f6aab3d8Srobert   int target_fd = llvm::sys::RetryAfterSignal(-1, ::open, file, flags, 0666);
75061da546Spatrick 
76061da546Spatrick   if (target_fd == -1)
77061da546Spatrick     ExitWithError(error_fd, "DupDescriptor-open");
78061da546Spatrick 
79061da546Spatrick   if (target_fd == fd)
80061da546Spatrick     return;
81061da546Spatrick 
82061da546Spatrick   if (::dup2(target_fd, fd) == -1)
83061da546Spatrick     ExitWithError(error_fd, "DupDescriptor-dup2");
84061da546Spatrick 
85061da546Spatrick   ::close(target_fd);
86061da546Spatrick }
87061da546Spatrick 
88*f6aab3d8Srobert namespace {
89*f6aab3d8Srobert struct ForkFileAction {
90*f6aab3d8Srobert   ForkFileAction(const FileAction &act);
91*f6aab3d8Srobert 
92*f6aab3d8Srobert   FileAction::Action action;
93*f6aab3d8Srobert   int fd;
94*f6aab3d8Srobert   std::string path;
95*f6aab3d8Srobert   int arg;
96*f6aab3d8Srobert };
97*f6aab3d8Srobert 
98*f6aab3d8Srobert struct ForkLaunchInfo {
99*f6aab3d8Srobert   ForkLaunchInfo(const ProcessLaunchInfo &info);
100*f6aab3d8Srobert 
101*f6aab3d8Srobert   bool separate_process_group;
102*f6aab3d8Srobert   bool debug;
103*f6aab3d8Srobert   bool disable_aslr;
104*f6aab3d8Srobert   std::string wd;
105*f6aab3d8Srobert   const char **argv;
106*f6aab3d8Srobert   Environment::Envp envp;
107*f6aab3d8Srobert   std::vector<ForkFileAction> actions;
108*f6aab3d8Srobert 
has_action__anon3e0251c90111::ForkLaunchInfo109*f6aab3d8Srobert   bool has_action(int fd) const {
110*f6aab3d8Srobert     for (const ForkFileAction &action : actions) {
111*f6aab3d8Srobert       if (action.fd == fd)
112*f6aab3d8Srobert         return true;
113*f6aab3d8Srobert     }
114*f6aab3d8Srobert     return false;
115*f6aab3d8Srobert   }
116*f6aab3d8Srobert };
117*f6aab3d8Srobert } // namespace
118*f6aab3d8Srobert 
ChildFunc(int error_fd,const ForkLaunchInfo & info)119*f6aab3d8Srobert [[noreturn]] static void ChildFunc(int error_fd, const ForkLaunchInfo &info) {
120*f6aab3d8Srobert   if (info.separate_process_group) {
121061da546Spatrick     if (setpgid(0, 0) != 0)
122061da546Spatrick       ExitWithError(error_fd, "setpgid");
123061da546Spatrick   }
124061da546Spatrick 
125*f6aab3d8Srobert   for (const ForkFileAction &action : info.actions) {
126*f6aab3d8Srobert     switch (action.action) {
127061da546Spatrick     case FileAction::eFileActionClose:
128*f6aab3d8Srobert       if (close(action.fd) != 0)
129061da546Spatrick         ExitWithError(error_fd, "close");
130061da546Spatrick       break;
131061da546Spatrick     case FileAction::eFileActionDuplicate:
132*f6aab3d8Srobert       if (dup2(action.fd, action.arg) == -1)
133061da546Spatrick         ExitWithError(error_fd, "dup2");
134061da546Spatrick       break;
135061da546Spatrick     case FileAction::eFileActionOpen:
136*f6aab3d8Srobert       DupDescriptor(error_fd, action.path.c_str(), action.fd, action.arg);
137061da546Spatrick       break;
138061da546Spatrick     case FileAction::eFileActionNone:
139061da546Spatrick       break;
140061da546Spatrick     }
141061da546Spatrick   }
142061da546Spatrick 
143061da546Spatrick   // Change working directory
144*f6aab3d8Srobert   if (!info.wd.empty() && 0 != ::chdir(info.wd.c_str()))
145061da546Spatrick     ExitWithError(error_fd, "chdir");
146061da546Spatrick 
147*f6aab3d8Srobert   if (info.disable_aslr)
148*f6aab3d8Srobert     DisableASLR(error_fd);
149061da546Spatrick 
150061da546Spatrick   // Clear the signal mask to prevent the child from being affected by any
151061da546Spatrick   // masking done by the parent.
152061da546Spatrick   sigset_t set;
153061da546Spatrick   if (sigemptyset(&set) != 0 ||
154061da546Spatrick       pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0)
155061da546Spatrick     ExitWithError(error_fd, "pthread_sigmask");
156061da546Spatrick 
157*f6aab3d8Srobert   if (info.debug) {
158061da546Spatrick     // Do not inherit setgid powers.
159061da546Spatrick     if (setgid(getgid()) != 0)
160061da546Spatrick       ExitWithError(error_fd, "setgid");
161061da546Spatrick 
162061da546Spatrick     // HACK:
163061da546Spatrick     // Close everything besides stdin, stdout, and stderr that has no file
164061da546Spatrick     // action to avoid leaking. Only do this when debugging, as elsewhere we
165061da546Spatrick     // actually rely on passing open descriptors to child processes.
166*f6aab3d8Srobert     // NB: This code is not async-signal safe, but we currently do not launch
167*f6aab3d8Srobert     // processes for debugging from within multithreaded contexts.
168*f6aab3d8Srobert 
169*f6aab3d8Srobert     const llvm::StringRef proc_fd_path = "/proc/self/fd";
170*f6aab3d8Srobert     std::error_code ec;
171*f6aab3d8Srobert     bool result;
172*f6aab3d8Srobert     ec = llvm::sys::fs::is_directory(proc_fd_path, result);
173*f6aab3d8Srobert     if (result) {
174*f6aab3d8Srobert       std::vector<int> files_to_close;
175*f6aab3d8Srobert       // Directory iterator doesn't ensure any sequence.
176*f6aab3d8Srobert       for (llvm::sys::fs::directory_iterator iter(proc_fd_path, ec), file_end;
177*f6aab3d8Srobert            iter != file_end && !ec; iter.increment(ec)) {
178*f6aab3d8Srobert         int fd = std::stoi(iter->path().substr(proc_fd_path.size() + 1));
179*f6aab3d8Srobert 
180*f6aab3d8Srobert         // Don't close first three entries since they are stdin, stdout and
181*f6aab3d8Srobert         // stderr.
182*f6aab3d8Srobert         if (fd > 2 && !info.has_action(fd) && fd != error_fd)
183*f6aab3d8Srobert           files_to_close.push_back(fd);
184*f6aab3d8Srobert       }
185*f6aab3d8Srobert       for (int file_to_close : files_to_close)
186*f6aab3d8Srobert         close(file_to_close);
187*f6aab3d8Srobert     } else {
188*f6aab3d8Srobert       // Since /proc/self/fd didn't work, trying the slow way instead.
189*f6aab3d8Srobert       int max_fd = sysconf(_SC_OPEN_MAX);
190*f6aab3d8Srobert       for (int fd = 3; fd < max_fd; ++fd)
191*f6aab3d8Srobert         if (!info.has_action(fd) && fd != error_fd)
192061da546Spatrick           close(fd);
193*f6aab3d8Srobert     }
194061da546Spatrick 
195061da546Spatrick     // Start tracing this child that is about to exec.
196061da546Spatrick     if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1)
197061da546Spatrick       ExitWithError(error_fd, "ptrace");
198061da546Spatrick   }
199061da546Spatrick 
200061da546Spatrick   // Execute.  We should never return...
201*f6aab3d8Srobert   execve(info.argv[0], const_cast<char *const *>(info.argv), info.envp);
202061da546Spatrick 
203061da546Spatrick #if defined(__linux__)
204061da546Spatrick   if (errno == ETXTBSY) {
205061da546Spatrick     // On android M and earlier we can get this error because the adb daemon
206061da546Spatrick     // can hold a write handle on the executable even after it has finished
207061da546Spatrick     // uploading it. This state lasts only a short time and happens only when
208061da546Spatrick     // there are many concurrent adb commands being issued, such as when
209061da546Spatrick     // running the test suite. (The file remains open when someone does an "adb
210061da546Spatrick     // shell" command in the fork() child before it has had a chance to exec.)
211061da546Spatrick     // Since this state should clear up quickly, wait a while and then give it
212061da546Spatrick     // one more go.
213061da546Spatrick     usleep(50000);
214*f6aab3d8Srobert     execve(info.argv[0], const_cast<char *const *>(info.argv), info.envp);
215061da546Spatrick   }
216061da546Spatrick #endif
217061da546Spatrick 
218061da546Spatrick   // ...unless exec fails.  In which case we definitely need to end the child
219061da546Spatrick   // here.
220061da546Spatrick   ExitWithError(error_fd, "execve");
221061da546Spatrick }
222061da546Spatrick 
223*f6aab3d8Srobert // End of code running in the child process.
224*f6aab3d8Srobert 
ForkFileAction(const FileAction & act)225*f6aab3d8Srobert ForkFileAction::ForkFileAction(const FileAction &act)
226*f6aab3d8Srobert     : action(act.GetAction()), fd(act.GetFD()), path(act.GetPath().str()),
227*f6aab3d8Srobert       arg(act.GetActionArgument()) {}
228*f6aab3d8Srobert 
229*f6aab3d8Srobert static std::vector<ForkFileAction>
MakeForkActions(const ProcessLaunchInfo & info)230*f6aab3d8Srobert MakeForkActions(const ProcessLaunchInfo &info) {
231*f6aab3d8Srobert   std::vector<ForkFileAction> result;
232*f6aab3d8Srobert   for (size_t i = 0; i < info.GetNumFileActions(); ++i)
233*f6aab3d8Srobert     result.emplace_back(*info.GetFileActionAtIndex(i));
234*f6aab3d8Srobert   return result;
235*f6aab3d8Srobert }
236*f6aab3d8Srobert 
FixupEnvironment(Environment env)237*f6aab3d8Srobert static Environment::Envp FixupEnvironment(Environment env) {
238*f6aab3d8Srobert #ifdef __ANDROID__
239*f6aab3d8Srobert   // If there is no PATH variable specified inside the environment then set the
240*f6aab3d8Srobert   // path to /system/bin. It is required because the default path used by
241*f6aab3d8Srobert   // execve() is wrong on android.
242*f6aab3d8Srobert   env.try_emplace("PATH", "/system/bin");
243*f6aab3d8Srobert #endif
244*f6aab3d8Srobert   return env.getEnvp();
245*f6aab3d8Srobert }
246*f6aab3d8Srobert 
ForkLaunchInfo(const ProcessLaunchInfo & info)247*f6aab3d8Srobert ForkLaunchInfo::ForkLaunchInfo(const ProcessLaunchInfo &info)
248*f6aab3d8Srobert     : separate_process_group(
249*f6aab3d8Srobert           info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)),
250*f6aab3d8Srobert       debug(info.GetFlags().Test(eLaunchFlagDebug)),
251*f6aab3d8Srobert       disable_aslr(info.GetFlags().Test(eLaunchFlagDisableASLR)),
252*f6aab3d8Srobert       wd(info.GetWorkingDirectory().GetPath()),
253*f6aab3d8Srobert       argv(info.GetArguments().GetConstArgumentVector()),
254*f6aab3d8Srobert       envp(FixupEnvironment(info.GetEnvironment())),
255*f6aab3d8Srobert       actions(MakeForkActions(info)) {}
256*f6aab3d8Srobert 
257061da546Spatrick HostProcess
LaunchProcess(const ProcessLaunchInfo & launch_info,Status & error)258061da546Spatrick ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info,
259061da546Spatrick                                         Status &error) {
260061da546Spatrick   // A pipe used by the child process to report errors.
261061da546Spatrick   PipePosix pipe;
262061da546Spatrick   const bool child_processes_inherit = false;
263061da546Spatrick   error = pipe.CreateNew(child_processes_inherit);
264061da546Spatrick   if (error.Fail())
265061da546Spatrick     return HostProcess();
266061da546Spatrick 
267*f6aab3d8Srobert   const ForkLaunchInfo fork_launch_info(launch_info);
268*f6aab3d8Srobert 
269061da546Spatrick   ::pid_t pid = ::fork();
270061da546Spatrick   if (pid == -1) {
271061da546Spatrick     // Fork failed
272061da546Spatrick     error.SetErrorStringWithFormatv("Fork failed with error message: {0}",
273061da546Spatrick                                     llvm::sys::StrError());
274061da546Spatrick     return HostProcess(LLDB_INVALID_PROCESS_ID);
275061da546Spatrick   }
276061da546Spatrick   if (pid == 0) {
277061da546Spatrick     // child process
278061da546Spatrick     pipe.CloseReadFileDescriptor();
279*f6aab3d8Srobert     ChildFunc(pipe.ReleaseWriteFileDescriptor(), fork_launch_info);
280061da546Spatrick   }
281061da546Spatrick 
282061da546Spatrick   // parent process
283061da546Spatrick 
284061da546Spatrick   pipe.CloseWriteFileDescriptor();
285*f6aab3d8Srobert   llvm::SmallString<0> buf;
286*f6aab3d8Srobert   size_t pos = 0;
287*f6aab3d8Srobert   ssize_t r = 0;
288*f6aab3d8Srobert   do {
289*f6aab3d8Srobert     pos += r;
290*f6aab3d8Srobert     buf.resize_for_overwrite(pos + 100);
291*f6aab3d8Srobert     r = llvm::sys::RetryAfterSignal(-1, read, pipe.GetReadFileDescriptor(),
292*f6aab3d8Srobert                                     buf.begin() + pos, buf.size() - pos);
293*f6aab3d8Srobert   } while (r > 0);
294*f6aab3d8Srobert   assert(r != -1);
295061da546Spatrick 
296*f6aab3d8Srobert   buf.resize(pos);
297*f6aab3d8Srobert   if (buf.empty())
298061da546Spatrick     return HostProcess(pid); // No error. We're done.
299061da546Spatrick 
300061da546Spatrick   error.SetErrorString(buf);
301061da546Spatrick 
302061da546Spatrick   llvm::sys::RetryAfterSignal(-1, waitpid, pid, nullptr, 0);
303061da546Spatrick 
304061da546Spatrick   return HostProcess();
305061da546Spatrick }
306