17#include "llvm/Support/Errno.h"
21#include <sys/ptrace.h>
29#include <sys/personality.h>
40 int r = write(error_fd, str, strlen(str));
44[[noreturn]]
static void ExitWithError(
int error_fd,
const char *operation) {
55 const unsigned long personality_get_current = 0xffffffff;
56 int value = personality(personality_get_current);
60 value = personality(ADDR_NO_RANDOMIZE | value);
66static void DupDescriptor(
int error_fd,
const char *file,
int fd,
int flags) {
75 if (::dup2(target_fd, fd) == -1)
82struct ForkFileAction {
83 ForkFileAction(
const FileAction &act);
91struct ForkLaunchInfo {
92 ForkLaunchInfo(
const ProcessLaunchInfo &info);
94 bool separate_process_group;
98 std::string executable;
100 Environment::Envp envp;
101 std::vector<ForkFileAction> actions;
103 bool has_action(
int fd)
const {
104 for (
const ForkFileAction &action : actions) {
113[[noreturn]]
static void ChildFunc(
int error_fd,
const ForkLaunchInfo &info) {
114 if (info.separate_process_group) {
115 if (setpgid(0, 0) != 0)
119 for (
const ForkFileAction &action : info.actions) {
120 switch (action.action) {
122 if (close(action.fd) != 0)
126 if (action.fd != action.arg) {
127 if (dup2(action.fd, action.arg) == -1)
130 if (fcntl(action.fd, F_SETFD,
131 fcntl(action.fd, F_GETFD) & ~FD_CLOEXEC) == -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)
197 if (ptrace64(PT_TRACE_ME, 0, 0, 0,
nullptr) == -1)
199 if (ptrace(PT_TRACE_ME, 0,
nullptr, 0) == -1)
205 execve(info.executable.c_str(),
const_cast<char *
const *
>(info.argv),
208#if defined(__linux__)
209 if (errno == ETXTBSY) {
219 execve(info.executable.c_str(),
const_cast<char *
const *
>(info.argv),
231ForkFileAction::ForkFileAction(
const FileAction &act)
232 : action(act.GetAction()), fd(act.GetFD()), path(act.GetPath().str()),
233 arg(act.GetActionArgument()) {}
235static std::vector<ForkFileAction>
237 std::vector<ForkFileAction> result;
244 : separate_process_group(
245 info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)),
246 debug(info.GetFlags().Test(eLaunchFlagDebug)),
247 disable_aslr(info.GetFlags().Test(eLaunchFlagDisableASLR)),
248 wd(info.GetWorkingDirectory().GetPath()),
249 executable(info.GetExecutableFile().GetPath()),
250 argv(info.GetArguments().GetConstArgumentVector()),
251 envp(info.GetEnvironment().getEnvp()), actions(
MakeForkActions(info)) {}
262 const ForkLaunchInfo fork_launch_info(launch_info);
268 "Fork failed with error message: {0}", llvm::sys::StrError());
280 llvm::SmallString<0> buf;
285 buf.resize_for_overwrite(pos + 100);
287 buf.begin() + pos, buf.size() - pos);
297 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 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
Status CreateNew() override
int ReleaseWriteFileDescriptor() override
void CloseReadFileDescriptor() override
const FileAction * GetFileActionAtIndex(size_t idx) const
size_t GetNumFileActions() const
HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Status &error) override
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
#define LLDB_INVALID_PROCESS_ID
A class that represents a running process on the host machine.