blob: 4400055d7df99cb255cc521421891d3328c3103a [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"
11#include "lldb/Core/Log.h"
12#include "lldb/Host/FileSpec.h"
13#include "lldb/Host/Host.h"
14#include "lldb/Host/HostProcess.h"
15#include "lldb/Host/Pipe.h"
16#include "lldb/Target/ProcessLaunchInfo.h"
17
18#include <limits.h>
19#include <sys/ptrace.h>
20#include <sys/wait.h>
21
22#include <sstream>
23
24#ifdef __ANDROID__
25#include <android/api-level.h>
Pavel Labath3eb8b1a2017-02-01 16:43:22 +000026#define PT_TRACE_ME PTRACE_TRACEME
Kamil Rytarowski816ae4b2017-02-01 14:30:40 +000027#endif
28
29#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
30#include <linux/personality.h>
31#elif defined(__linux__)
32#include <sys/personality.h>
33#endif
34
35using namespace lldb;
36using namespace lldb_private;
37
38static void FixupEnvironment(Args &env) {
39#ifdef __ANDROID__
40 // If there is no PATH variable specified inside the environment then set the
41 // path to /system/bin. It is required because the default path used by
42 // execve() is wrong on android.
43 static const char *path = "PATH=";
44 for (auto &entry : env.entries()) {
45 if (entry.ref.startswith(path))
46 return;
47 }
48 env.AppendArgument(llvm::StringRef("PATH=/system/bin"));
49#endif
50}
51
52static void LLVM_ATTRIBUTE_NORETURN ExitWithError(int error_fd,
53 const char *operation) {
54 std::ostringstream os;
55 os << operation << " failed: " << strerror(errno);
56 write(error_fd, os.str().data(), os.str().size());
57 close(error_fd);
58 _exit(1);
59}
60
61static void DisableASLRIfRequested(int error_fd, const ProcessLaunchInfo &info) {
62#if defined(__linux__)
63 if (info.GetFlags().Test(lldb::eLaunchFlagDisableASLR)) {
64 const unsigned long personality_get_current = 0xffffffff;
65 int value = personality(personality_get_current);
66 if (value == -1)
67 ExitWithError(error_fd, "personality get");
68
69 value = personality(ADDR_NO_RANDOMIZE | value);
70 if (value == -1)
71 ExitWithError(error_fd, "personality set");
72 }
73#endif
74}
75
76static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd,
77 int flags) {
78 int target_fd = ::open(file_spec.GetCString(), flags, 0666);
79
80 if (target_fd == -1)
81 ExitWithError(error_fd, "DupDescriptor-open");
82
83 if (target_fd == fd)
84 return;
85
86 if (::dup2(target_fd, fd) == -1)
87 ExitWithError(error_fd, "DupDescriptor-dup2");
88
89 ::close(target_fd);
90 return;
91}
92
93static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd,
94 const ProcessLaunchInfo &info) {
95 // First, make sure we disable all logging. If we are logging to stdout, our
96 // logs can be
97 // mistaken for inferior output.
98 Log::DisableAllLogChannels(nullptr);
99
100 // Do not inherit setgid powers.
101 if (setgid(getgid()) != 0)
102 ExitWithError(error_fd, "setgid");
103
104 if (info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)) {
105 if (setpgid(0, 0) != 0)
106 ExitWithError(error_fd, "setpgid");
107 }
108
109 for (size_t i = 0; i < info.GetNumFileActions(); ++i) {
110 const FileAction &action = *info.GetFileActionAtIndex(i);
111 switch (action.GetAction()) {
112 case FileAction::eFileActionClose:
113 if (close(action.GetFD()) != 0)
114 ExitWithError(error_fd, "close");
115 break;
116 case FileAction::eFileActionDuplicate:
117 if (dup2(action.GetFD(), action.GetActionArgument()) == -1)
118 ExitWithError(error_fd, "dup2");
119 break;
120 case FileAction::eFileActionOpen:
121 DupDescriptor(error_fd, action.GetFileSpec(), action.GetFD(),
122 action.GetActionArgument());
123 break;
124 case FileAction::eFileActionNone:
125 break;
126 }
127 }
128
129 const char **argv = info.GetArguments().GetConstArgumentVector();
130
131 // Change working directory
132 if (info.GetWorkingDirectory() &&
133 0 != ::chdir(info.GetWorkingDirectory().GetCString()))
134 ExitWithError(error_fd, "chdir");
135
136 DisableASLRIfRequested(error_fd, info);
137 Args env = info.GetEnvironmentEntries();
138 FixupEnvironment(env);
139 const char **envp = env.GetConstArgumentVector();
140
141 // Clear the signal mask to prevent the child from being affected by
142 // any masking done by the parent.
143 sigset_t set;
144 if (sigemptyset(&set) != 0 ||
145 pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0)
146 ExitWithError(error_fd, "pthread_sigmask");
147
148 if (info.GetFlags().Test(eLaunchFlagDebug)) {
149 // HACK:
150 // Close everything besides stdin, stdout, and stderr that has no file
151 // action to avoid leaking. Only do this when debugging, as elsewhere we
152 // actually rely on
153 // passing open descriptors to child processes.
154 for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd)
155 if (!info.GetFileActionForFD(fd) && fd != error_fd)
156 close(fd);
157
158 // Start tracing this child that is about to exec.
159 if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1)
160 ExitWithError(error_fd, "ptrace");
161 }
162
163 // Execute. We should never return...
164 execve(argv[0], const_cast<char *const *>(argv),
165 const_cast<char *const *>(envp));
166
167#if defined(__linux__)
168 if (errno == ETXTBSY) {
169 // On android M and earlier we can get this error because the adb deamon can
170 // hold a write
171 // handle on the executable even after it has finished uploading it. This
172 // state lasts
173 // only a short time and happens only when there are many concurrent adb
174 // commands being
175 // issued, such as when running the test suite. (The file remains open when
176 // someone does
177 // an "adb shell" command in the fork() child before it has had a chance to
178 // exec.) Since
179 // this state should clear up quickly, wait a while and then give it one
180 // more go.
181 usleep(50000);
182 execve(argv[0], const_cast<char *const *>(argv),
183 const_cast<char *const *>(envp));
184 }
185#endif
186
187 // ...unless exec fails. In which case we definitely need to end the child
188 // here.
189 ExitWithError(error_fd, "execve");
190}
191
192HostProcess
193ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info,
194 Error &error) {
195 char exe_path[PATH_MAX];
196 launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
197
198 // A pipe used by the child process to report errors.
199 PipePosix pipe;
200 const bool child_processes_inherit = false;
201 error = pipe.CreateNew(child_processes_inherit);
202 if (error.Fail())
203 return HostProcess();
204
205 ::pid_t pid = ::fork();
206 if (pid == -1) {
207 // Fork failed
208 error.SetErrorStringWithFormat("Fork failed with error message: %s",
209 strerror(errno));
210 return HostProcess(LLDB_INVALID_PROCESS_ID);
211 }
212 if (pid == 0) {
213 // child process
214 pipe.CloseReadFileDescriptor();
215 ChildFunc(pipe.ReleaseWriteFileDescriptor(), launch_info);
216 }
217
218 // parent process
219
220 pipe.CloseWriteFileDescriptor();
221 char buf[1000];
222 int r = read(pipe.GetReadFileDescriptor(), buf, sizeof buf);
223
224 if (r == 0)
225 return HostProcess(pid); // No error. We're done.
226
227 error.SetErrorString(buf);
228
229 waitpid(pid, nullptr, 0);
230
231 return HostProcess();
232}