17#include "llvm/Support/Errno.h"
20#include <sys/ptrace.h>
28#include <android/api-level.h>
29#define PT_TRACE_ME PTRACE_TRACEME
32#if defined(__ANDROID_API__) && __ANDROID_API__ < 15
33#include <linux/personality.h>
34#elif defined(__linux__)
35#include <sys/personality.h>
46 int r = write(error_fd, str, strlen(str));
51 const char *operation) {
62 const unsigned long personality_get_current = 0xffffffff;
63 int value = personality(personality_get_current);
67 value = personality(ADDR_NO_RANDOMIZE | value);
73static void DupDescriptor(
int error_fd,
const char *file,
int fd,
int flags) {
82 if (::dup2(target_fd, fd) == -1)
89struct ForkFileAction {
98struct ForkLaunchInfo {
101 bool separate_process_group;
107 std::vector<ForkFileAction> actions;
109 bool has_action(
int fd)
const {
110 for (
const ForkFileAction &action : actions) {
119[[noreturn]]
static void ChildFunc(
int error_fd,
const ForkLaunchInfo &info) {
120 if (info.separate_process_group) {
121 if (setpgid(0, 0) != 0)
125 for (
const ForkFileAction &action : info.actions) {
126 switch (action.action) {
128 if (close(action.fd) != 0)
132 if (dup2(action.fd, action.arg) == -1)
136 DupDescriptor(error_fd, action.path.c_str(), action.fd, action.arg);
144 if (!info.wd.empty() && 0 != ::chdir(info.wd.c_str()))
147 if (info.disable_aslr)
153 if (sigemptyset(&set) != 0 ||
154 pthread_sigmask(SIG_SETMASK, &set,
nullptr) != 0)
159 if (setgid(getgid()) != 0)
169 const llvm::StringRef proc_fd_path =
"/proc/self/fd";
172 ec = llvm::sys::fs::is_directory(proc_fd_path, result);
174 std::vector<int> files_to_close;
176 for (llvm::sys::fs::directory_iterator iter(proc_fd_path, ec), file_end;
177 iter != file_end && !ec; iter.increment(ec)) {
178 int fd = std::stoi(iter->path().substr(proc_fd_path.size() + 1));
182 if (fd > 2 && !info.has_action(fd) && fd != error_fd)
183 files_to_close.push_back(fd);
185 for (
int file_to_close : files_to_close)
186 close(file_to_close);
189 int max_fd = sysconf(_SC_OPEN_MAX);
190 for (
int fd = 3; fd < max_fd; ++fd)
191 if (!info.has_action(fd) && fd != error_fd)
196 if (ptrace(PT_TRACE_ME, 0,
nullptr, 0) == -1)
201 execve(info.argv[0],
const_cast<char *
const *
>(info.argv), info.envp);
203#if defined(__linux__)
204 if (errno == ETXTBSY) {
214 execve(info.argv[0],
const_cast<char *
const *
>(info.argv), info.envp);
225ForkFileAction::ForkFileAction(
const FileAction &act)
226 : action(act.GetAction()), fd(act.GetFD()), path(act.GetPath().str()),
227 arg(act.GetActionArgument()) {}
229static std::vector<ForkFileAction>
231 std::vector<ForkFileAction> result;
242 env.try_emplace(
"PATH",
"/system/bin");
248 : separate_process_group(
249 info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)),
250 debug(info.GetFlags().Test(eLaunchFlagDebug)),
251 disable_aslr(info.GetFlags().Test(eLaunchFlagDisableASLR)),
252 wd(info.GetWorkingDirectory().GetPath()),
253 argv(info.GetArguments().GetConstArgumentVector()),
262 const bool child_processes_inherit =
false;
267 const ForkLaunchInfo fork_launch_info(launch_info);
272 error.SetErrorStringWithFormatv(
"Fork failed with error message: {0}",
273 llvm::sys::StrError());
285 llvm::SmallString<0> buf;
290 buf.resize_for_overwrite(pos + 100);
292 buf.begin() + pos, buf.size() - pos);
300 error.SetErrorString(buf);
302 llvm::sys::RetryAfterSignal(-1, waitpid, pid,
nullptr, 0);
static llvm::raw_ostream & error(Stream &strm)
static void ExitWithError(int error_fd, const char *operation)
static void DisableASLR(int error_fd)
static std::vector< ForkFileAction > MakeForkActions(const ProcessLaunchInfo &info)
static Environment::Envp FixupEnvironment(Environment env)
static void DupDescriptor(int error_fd, const char *file, int fd, int flags)
static void write_string(int error_fd, const char *str)
static void ChildFunc(int error_fd, const ForkLaunchInfo &info)
int Open(const char *path, int flags, int mode=0600)
Wraps ::open in a platform-independent way.
static FileSystem & Instance()
A posix-based implementation of Pipe, a class that abtracts unix style pipes.
int GetReadFileDescriptor() const override
void CloseWriteFileDescriptor() override
int ReleaseWriteFileDescriptor() override
void CloseReadFileDescriptor() override
Status CreateNew(bool child_process_inherit) override
const FileAction * GetFileActionAtIndex(size_t idx) const
size_t GetNumFileActions() const
HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Status &error) override
#define LLDB_INVALID_PROCESS_ID
A class that represents a running process on the host machine.