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