LLDB  mainline
ProcessLauncherPosixFork.cpp
Go to the documentation of this file.
1 //===-- ProcessLauncherPosixFork.cpp --------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "lldb/Host/Host.h"
11 #include "lldb/Host/HostProcess.h"
12 #include "lldb/Host/Pipe.h"
14 #include "lldb/Utility/FileSpec.h"
15 #include "lldb/Utility/Log.h"
16 #include "llvm/Support/Errno.h"
17 #include "llvm/Support/FileSystem.h"
18 
19 #include <climits>
20 #include <sys/ptrace.h>
21 #include <sys/wait.h>
22 #include <unistd.h>
23 
24 #include <sstream>
25 #include <csignal>
26 
27 #ifdef __ANDROID__
28 #include <android/api-level.h>
29 #define PT_TRACE_ME PTRACE_TRACEME
30 #endif
31 
32 #if defined(__ANDROID_API__) && __ANDROID_API__ < 15
33 #include <linux/personality.h>
34 #elif defined(__linux__)
35 #include <sys/personality.h>
36 #endif
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 
41 static void FixupEnvironment(Environment &env) {
42 #ifdef __ANDROID__
43  // If there is no PATH variable specified inside the environment then set the
44  // path to /system/bin. It is required because the default path used by
45  // execve() is wrong on android.
46  env.try_emplace("PATH", "/system/bin");
47 #endif
48 }
49 
50 [[noreturn]] static void ExitWithError(int error_fd,
51  const char *operation) {
52  int err = errno;
53  llvm::raw_fd_ostream os(error_fd, true);
54  os << operation << " failed: " << llvm::sys::StrError(err);
55  os.flush();
56  _exit(1);
57 }
58 
59 static void DisableASLRIfRequested(int error_fd, const ProcessLaunchInfo &info) {
60 #if defined(__linux__)
61  if (info.GetFlags().Test(lldb::eLaunchFlagDisableASLR)) {
62  const unsigned long personality_get_current = 0xffffffff;
63  int value = personality(personality_get_current);
64  if (value == -1)
65  ExitWithError(error_fd, "personality get");
66 
67  value = personality(ADDR_NO_RANDOMIZE | value);
68  if (value == -1)
69  ExitWithError(error_fd, "personality set");
70  }
71 #endif
72 }
73 
74 static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd,
75  int flags) {
76  int target_fd = llvm::sys::RetryAfterSignal(-1, ::open,
77  file_spec.GetCString(), flags, 0666);
78 
79  if (target_fd == -1)
80  ExitWithError(error_fd, "DupDescriptor-open");
81 
82  if (target_fd == fd)
83  return;
84 
85  if (::dup2(target_fd, fd) == -1)
86  ExitWithError(error_fd, "DupDescriptor-dup2");
87 
88  ::close(target_fd);
89  return;
90 }
91 
92 [[noreturn]] static void ChildFunc(int error_fd,
93  const ProcessLaunchInfo &info) {
94  if (info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)) {
95  if (setpgid(0, 0) != 0)
96  ExitWithError(error_fd, "setpgid");
97  }
98 
99  for (size_t i = 0; i < info.GetNumFileActions(); ++i) {
100  const FileAction &action = *info.GetFileActionAtIndex(i);
101  switch (action.GetAction()) {
102  case FileAction::eFileActionClose:
103  if (close(action.GetFD()) != 0)
104  ExitWithError(error_fd, "close");
105  break;
106  case FileAction::eFileActionDuplicate:
107  if (dup2(action.GetFD(), action.GetActionArgument()) == -1)
108  ExitWithError(error_fd, "dup2");
109  break;
110  case FileAction::eFileActionOpen:
111  DupDescriptor(error_fd, action.GetFileSpec(), action.GetFD(),
112  action.GetActionArgument());
113  break;
114  case FileAction::eFileActionNone:
115  break;
116  }
117  }
118 
119  const char **argv = info.GetArguments().GetConstArgumentVector();
120 
121  // Change working directory
122  if (info.GetWorkingDirectory() &&
123  0 != ::chdir(info.GetWorkingDirectory().GetCString()))
124  ExitWithError(error_fd, "chdir");
125 
126  DisableASLRIfRequested(error_fd, info);
127  Environment env = info.GetEnvironment();
128  FixupEnvironment(env);
129  Environment::Envp envp = env.getEnvp();
130 
131  // Clear the signal mask to prevent the child from being affected by any
132  // masking done by the parent.
133  sigset_t set;
134  if (sigemptyset(&set) != 0 ||
135  pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0)
136  ExitWithError(error_fd, "pthread_sigmask");
137 
138  if (info.GetFlags().Test(eLaunchFlagDebug)) {
139  // Do not inherit setgid powers.
140  if (setgid(getgid()) != 0)
141  ExitWithError(error_fd, "setgid");
142 
143  // HACK:
144  // Close everything besides stdin, stdout, and stderr that has no file
145  // action to avoid leaking. Only do this when debugging, as elsewhere we
146  // actually rely on passing open descriptors to child processes.
147 
148  const llvm::StringRef proc_fd_path = "/proc/self/fd";
149  std::error_code ec;
150  bool result;
151  ec = llvm::sys::fs::is_directory(proc_fd_path, result);
152  if (result) {
153  std::vector<int> files_to_close;
154  // Directory iterator doesn't ensure any sequence.
155  for (llvm::sys::fs::directory_iterator iter(proc_fd_path, ec), file_end;
156  iter != file_end && !ec; iter.increment(ec)) {
157  int fd = std::stoi(iter->path().substr(proc_fd_path.size() + 1));
158 
159  // Don't close first three entries since they are stdin, stdout and
160  // stderr.
161  if (fd > 2 && !info.GetFileActionForFD(fd) && fd != error_fd)
162  files_to_close.push_back(fd);
163  }
164  for (int file_to_close : files_to_close)
165  close(file_to_close);
166  } else {
167  // Since /proc/self/fd didn't work, trying the slow way instead.
168  int max_fd = sysconf(_SC_OPEN_MAX);
169  for (int fd = 3; fd < max_fd; ++fd)
170  if (!info.GetFileActionForFD(fd) && fd != error_fd)
171  close(fd);
172  }
173 
174  // Start tracing this child that is about to exec.
175  if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1)
176  ExitWithError(error_fd, "ptrace");
177  }
178 
179  // Execute. We should never return...
180  execve(argv[0], const_cast<char *const *>(argv), envp);
181 
182 #if defined(__linux__)
183  if (errno == ETXTBSY) {
184  // On android M and earlier we can get this error because the adb daemon
185  // can hold a write handle on the executable even after it has finished
186  // uploading it. This state lasts only a short time and happens only when
187  // there are many concurrent adb commands being issued, such as when
188  // running the test suite. (The file remains open when someone does an "adb
189  // shell" command in the fork() child before it has had a chance to exec.)
190  // Since this state should clear up quickly, wait a while and then give it
191  // one more go.
192  usleep(50000);
193  execve(argv[0], const_cast<char *const *>(argv), envp);
194  }
195 #endif
196 
197  // ...unless exec fails. In which case we definitely need to end the child
198  // here.
199  ExitWithError(error_fd, "execve");
200 }
201 
203 ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info,
204  Status &error) {
205  char exe_path[PATH_MAX];
206  launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
207 
208  // A pipe used by the child process to report errors.
209  PipePosix pipe;
210  const bool child_processes_inherit = false;
211  error = pipe.CreateNew(child_processes_inherit);
212  if (error.Fail())
213  return HostProcess();
214 
215  ::pid_t pid = ::fork();
216  if (pid == -1) {
217  // Fork failed
218  error.SetErrorStringWithFormatv("Fork failed with error message: {0}",
219  llvm::sys::StrError());
221  }
222  if (pid == 0) {
223  // child process
224  pipe.CloseReadFileDescriptor();
225  ChildFunc(pipe.ReleaseWriteFileDescriptor(), launch_info);
226  }
227 
228  // parent process
229 
230  pipe.CloseWriteFileDescriptor();
231  char buf[1000];
232  int r = read(pipe.GetReadFileDescriptor(), buf, sizeof buf);
233 
234  if (r == 0)
235  return HostProcess(pid); // No error. We're done.
236 
237  error.SetErrorString(buf);
238 
239  llvm::sys::RetryAfterSignal(-1, waitpid, pid, nullptr, 0);
240 
241  return HostProcess();
242 }
lldb_private::ProcessInfo::GetArguments
Args & GetArguments()
Definition: ProcessInfo.h:75
lldb_private::HostProcess
Definition: HostProcess.h:33
LLDB_INVALID_PROCESS_ID
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:93
Host.h
lldb_private::Environment::Envp
Definition: Environment.h:22
ProcessLaunchInfo.h
HostProcess.h
lldb_private::ProcessLaunchInfo::GetFileActionForFD
const FileAction * GetFileActionForFD(int fd) const
Definition: ProcessLaunchInfo.cpp:116
lldb_private::Flags::Test
bool Test(ValueType bit) const
Test a single flag bit.
Definition: Flags.h:96
lldb_private::ProcessLaunchInfo::GetFlags
Flags & GetFlags()
Definition: ProcessLaunchInfo.h:64
lldb_private::FileAction
Definition: FileAction.h:17
lldb_private::FileSpec::GetCString
const char * GetCString(bool denormalize=true) const
Definition: FileSpec.cpp:364
FixupEnvironment
static void FixupEnvironment(Environment &env)
Definition: ProcessLauncherPosixFork.cpp:41
lldb_private::FileSpec
Definition: FileSpec.h:56
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
ChildFunc
static void ChildFunc(int error_fd, const ProcessLaunchInfo &info)
Definition: ProcessLauncherPosixFork.cpp:92
lldb_private::ProcessLaunchInfo
Definition: ProcessLaunchInfo.h:31
Log.h
DisableASLRIfRequested
static void DisableASLRIfRequested(int error_fd, const ProcessLaunchInfo &info)
Definition: ProcessLauncherPosixFork.cpp:59
lldb_private::FileAction::GetFD
int GetFD() const
Definition: FileAction.h:36
lldb_private::ProcessLaunchInfo::GetFileActionAtIndex
const FileAction * GetFileActionAtIndex(size_t idx) const
Definition: ProcessLaunchInfo.cpp:110
lldb_private::Environment::getEnvp
Envp getEnvp() const
Definition: Environment.h:78
Pipe.h
lldb_private::FileAction::GetAction
Action GetAction() const
Definition: FileAction.h:38
lldb_private::ProcessLaunchInfo::GetNumFileActions
size_t GetNumFileActions() const
Definition: ProcessLaunchInfo.h:58
set
set(option_framework FRAMEWORK) endif() if(LLDB_ENABLE_PYTHON) get_target_property(python_bindings_dir swig_wrapper_python BINARY_DIR) set(lldb_python_wrapper $
Definition: API/CMakeLists.txt:9
lldb_private::ProcessLaunchInfo::GetWorkingDirectory
const FileSpec & GetWorkingDirectory() const
Definition: ProcessLaunchInfo.cpp:124
lldb_private::Status
Definition: Status.h:44
lldb_private::ProcessInfo::GetEnvironment
Environment & GetEnvironment()
Definition: ProcessInfo.h:87
lldb_private::Args::GetConstArgumentVector
const char ** GetConstArgumentVector() const
Gets the argument vector.
Definition: Args.cpp:275
lldb::pid_t
uint64_t pid_t
Definition: lldb-types.h:85
lldb_private::FileAction::GetFileSpec
const FileSpec & GetFileSpec() const
Definition: FileAction.cpp:30
lldb_private::Environment
Definition: Environment.h:18
ExitWithError
static void ExitWithError(int error_fd, const char *operation)
Definition: ProcessLauncherPosixFork.cpp:50
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
fork
pid_t fork(void)
Definition: windows/PosixApi.h:121
lldb_private::ProcessInfo::GetExecutableFile
FileSpec & GetExecutableFile()
Definition: ProcessInfo.h:42
FileSpec.h
DupDescriptor
static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd, int flags)
Definition: ProcessLauncherPosixFork.cpp:74
PATH_MAX
#define PATH_MAX
Definition: windows/PosixApi.h:25
lldb_private::FileSpec::GetPath
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:348
lldb_private::FileAction::GetActionArgument
int GetActionArgument() const
Definition: FileAction.h:40
lldb
Definition: SBAddress.h:15
ProcessLauncherPosixFork.h