blob: 46ce3e3d224f6bfcdba1a689191371ae113a71c5 [file] [log] [blame]
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +00001//===-- ProcessLauncherLinux.cpp --------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000011#include "lldb/Host/Host.h"
12#include "lldb/Host/HostProcess.h"
13#include "lldb/Host/Pipe.h"
14#include "lldb/Target/ProcessLaunchInfo.h"
Zachary Turner5713a052017-03-22 18:40:07 +000015#include "lldb/Utility/FileSpec.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000016#include "lldb/Utility/Log.h"
Pavel Labath10c41f32017-06-06 14:06:17 +000017#include "llvm/Support/Errno.h"
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000018
19#include <limits.h>
20#include <sys/ptrace.h>
21#include <sys/wait.h>
Pavel Labathb6dbe9a2017-07-18 13:14:01 +000022#include <unistd.h>
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000023
24#include <sstream>
Pavel Labathf40f8fc2017-07-18 14:03:47 +000025#include <csignal>
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000026
27#ifdef __ANDROID__
28#include <android/api-level.h>
Pavel Labath3eb8b1a2017-02-01 16:43:22 +000029#define PT_TRACE_ME PTRACE_TRACEME
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000030#endif
31
Eugene Zemtsovd4abad92017-09-16 02:19:21 +000032#if defined(__ANDROID_API__) && __ANDROID_API__ < 15
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000033#include <linux/personality.h>
34#elif defined(__linux__)
35#include <sys/personality.h>
36#endif
37
38using namespace lldb;
39using namespace lldb_private;
40
Pavel Labath62930e52018-01-10 11:57:31 +000041static void FixupEnvironment(Environment &env) {
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000042#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.
Pavel Labath62930e52018-01-10 11:57:31 +000046 env.try_emplace("PATH", "/system/bin");
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000047#endif
48}
49
50static void LLVM_ATTRIBUTE_NORETURN ExitWithError(int error_fd,
51 const char *operation) {
Pavel Labath6c5c5422017-06-20 08:11:37 +000052 int err = errno;
53 llvm::raw_fd_ostream os(error_fd, true);
54 os << operation << " failed: " << llvm::sys::StrError(err);
55 os.flush();
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000056 _exit(1);
57}
58
59static 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
74static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd,
75 int flags) {
76 int target_fd = ::open(file_spec.GetCString(), flags, 0666);
77
78 if (target_fd == -1)
79 ExitWithError(error_fd, "DupDescriptor-open");
80
81 if (target_fd == fd)
82 return;
83
84 if (::dup2(target_fd, fd) == -1)
85 ExitWithError(error_fd, "DupDescriptor-dup2");
86
87 ::close(target_fd);
88 return;
89}
90
91static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd,
92 const ProcessLaunchInfo &info) {
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000093 if (info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)) {
94 if (setpgid(0, 0) != 0)
95 ExitWithError(error_fd, "setpgid");
96 }
97
98 for (size_t i = 0; i < info.GetNumFileActions(); ++i) {
99 const FileAction &action = *info.GetFileActionAtIndex(i);
100 switch (action.GetAction()) {
101 case FileAction::eFileActionClose:
102 if (close(action.GetFD()) != 0)
103 ExitWithError(error_fd, "close");
104 break;
105 case FileAction::eFileActionDuplicate:
106 if (dup2(action.GetFD(), action.GetActionArgument()) == -1)
107 ExitWithError(error_fd, "dup2");
108 break;
109 case FileAction::eFileActionOpen:
110 DupDescriptor(error_fd, action.GetFileSpec(), action.GetFD(),
111 action.GetActionArgument());
112 break;
113 case FileAction::eFileActionNone:
114 break;
115 }
116 }
117
118 const char **argv = info.GetArguments().GetConstArgumentVector();
119
120 // Change working directory
121 if (info.GetWorkingDirectory() &&
122 0 != ::chdir(info.GetWorkingDirectory().GetCString()))
123 ExitWithError(error_fd, "chdir");
124
125 DisableASLRIfRequested(error_fd, info);
Pavel Labath62930e52018-01-10 11:57:31 +0000126 Environment env = info.GetEnvironment();
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +0000127 FixupEnvironment(env);
Pavel Labath62930e52018-01-10 11:57:31 +0000128 Environment::Envp envp = env.getEnvp();
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +0000129
Adrian Prantl05097242018-04-30 16:49:04 +0000130 // Clear the signal mask to prevent the child from being affected by any
131 // masking done by the parent.
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +0000132 sigset_t set;
133 if (sigemptyset(&set) != 0 ||
134 pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0)
135 ExitWithError(error_fd, "pthread_sigmask");
136
137 if (info.GetFlags().Test(eLaunchFlagDebug)) {
Pavel Labath2eb720f2018-05-23 10:10:36 +0000138 // Do not inherit setgid powers.
139 if (setgid(getgid()) != 0)
140 ExitWithError(error_fd, "setgid");
141
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +0000142 // HACK:
143 // Close everything besides stdin, stdout, and stderr that has no file
144 // action to avoid leaking. Only do this when debugging, as elsewhere we
Adrian Prantl05097242018-04-30 16:49:04 +0000145 // actually rely on passing open descriptors to child processes.
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +0000146 for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd)
147 if (!info.GetFileActionForFD(fd) && fd != error_fd)
148 close(fd);
149
150 // Start tracing this child that is about to exec.
151 if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1)
152 ExitWithError(error_fd, "ptrace");
153 }
154
155 // Execute. We should never return...
Pavel Labath62930e52018-01-10 11:57:31 +0000156 execve(argv[0], const_cast<char *const *>(argv), envp);
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +0000157
158#if defined(__linux__)
159 if (errno == ETXTBSY) {
Adrian Prantl05097242018-04-30 16:49:04 +0000160 // On android M and earlier we can get this error because the adb deamon
161 // can hold a write handle on the executable even after it has finished
162 // uploading it. This state lasts only a short time and happens only when
163 // there are many concurrent adb commands being issued, such as when
164 // running the test suite. (The file remains open when someone does an "adb
165 // shell" command in the fork() child before it has had a chance to exec.)
166 // Since this state should clear up quickly, wait a while and then give it
167 // one more go.
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +0000168 usleep(50000);
Pavel Labath62930e52018-01-10 11:57:31 +0000169 execve(argv[0], const_cast<char *const *>(argv), envp);
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +0000170 }
171#endif
172
173 // ...unless exec fails. In which case we definitely need to end the child
174 // here.
175 ExitWithError(error_fd, "execve");
176}
177
178HostProcess
179ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info,
Zachary Turner97206d52017-05-12 04:51:55 +0000180 Status &error) {
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +0000181 char exe_path[PATH_MAX];
182 launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
183
184 // A pipe used by the child process to report errors.
185 PipePosix pipe;
186 const bool child_processes_inherit = false;
187 error = pipe.CreateNew(child_processes_inherit);
188 if (error.Fail())
189 return HostProcess();
190
191 ::pid_t pid = ::fork();
192 if (pid == -1) {
193 // Fork failed
Pavel Labath10c41f32017-06-06 14:06:17 +0000194 error.SetErrorStringWithFormatv("Fork failed with error message: {0}",
195 llvm::sys::StrError());
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +0000196 return HostProcess(LLDB_INVALID_PROCESS_ID);
197 }
198 if (pid == 0) {
199 // child process
200 pipe.CloseReadFileDescriptor();
201 ChildFunc(pipe.ReleaseWriteFileDescriptor(), launch_info);
202 }
203
204 // parent process
205
206 pipe.CloseWriteFileDescriptor();
207 char buf[1000];
208 int r = read(pipe.GetReadFileDescriptor(), buf, sizeof buf);
209
210 if (r == 0)
211 return HostProcess(pid); // No error. We're done.
212
213 error.SetErrorString(buf);
214
215 waitpid(pid, nullptr, 0);
216
217 return HostProcess();
218}