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 9 #include "lldb/Host/posix/ProcessLauncherPosixFork.h" 10 #include "lldb/Host/Host.h" 11 #include "lldb/Host/HostProcess.h" 12 #include "lldb/Host/Pipe.h" 13 #include "lldb/Host/ProcessLaunchInfo.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 // Begin code running in the child process 42 // NB: This code needs to be async-signal safe, since we're invoking fork from 43 // multithreaded contexts. 44 45 static void write_string(int error_fd, const char *str) { 46 int r = write(error_fd, str, strlen(str)); 47 (void)r; 48 } 49 50 [[noreturn]] static void ExitWithError(int error_fd, 51 const char *operation) { 52 int err = errno; 53 write_string(error_fd, operation); 54 write_string(error_fd, " failed: "); 55 // strerror is not guaranteed to be async-signal safe, but it usually is. 56 write_string(error_fd, strerror(err)); 57 _exit(1); 58 } 59 60 static void DisableASLR(int error_fd) { 61 #if defined(__linux__) 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 #endif 71 } 72 73 static void DupDescriptor(int error_fd, const char *file, int fd, int flags) { 74 int target_fd = llvm::sys::RetryAfterSignal(-1, ::open, file, flags, 0666); 75 76 if (target_fd == -1) 77 ExitWithError(error_fd, "DupDescriptor-open"); 78 79 if (target_fd == fd) 80 return; 81 82 if (::dup2(target_fd, fd) == -1) 83 ExitWithError(error_fd, "DupDescriptor-dup2"); 84 85 ::close(target_fd); 86 } 87 88 namespace { 89 struct ForkFileAction { 90 ForkFileAction(const FileAction &act); 91 92 FileAction::Action action; 93 int fd; 94 std::string path; 95 int arg; 96 }; 97 98 struct ForkLaunchInfo { 99 ForkLaunchInfo(const ProcessLaunchInfo &info); 100 101 bool separate_process_group; 102 bool debug; 103 bool disable_aslr; 104 std::string wd; 105 const char **argv; 106 Environment::Envp envp; 107 std::vector<ForkFileAction> actions; 108 109 bool has_action(int fd) const { 110 for (const ForkFileAction &action : actions) { 111 if (action.fd == fd) 112 return true; 113 } 114 return false; 115 } 116 }; 117 } // namespace 118 119 [[noreturn]] static void ChildFunc(int error_fd, const ForkLaunchInfo &info) { 120 if (info.separate_process_group) { 121 if (setpgid(0, 0) != 0) 122 ExitWithError(error_fd, "setpgid"); 123 } 124 125 for (const ForkFileAction &action : info.actions) { 126 switch (action.action) { 127 case FileAction::eFileActionClose: 128 if (close(action.fd) != 0) 129 ExitWithError(error_fd, "close"); 130 break; 131 case FileAction::eFileActionDuplicate: 132 if (dup2(action.fd, action.arg) == -1) 133 ExitWithError(error_fd, "dup2"); 134 break; 135 case FileAction::eFileActionOpen: 136 DupDescriptor(error_fd, action.path.c_str(), action.fd, action.arg); 137 break; 138 case FileAction::eFileActionNone: 139 break; 140 } 141 } 142 143 // Change working directory 144 if (!info.wd.empty() && 0 != ::chdir(info.wd.c_str())) 145 ExitWithError(error_fd, "chdir"); 146 147 if (info.disable_aslr) 148 DisableASLR(error_fd); 149 150 // Clear the signal mask to prevent the child from being affected by any 151 // masking done by the parent. 152 sigset_t set; 153 if (sigemptyset(&set) != 0 || 154 pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0) 155 ExitWithError(error_fd, "pthread_sigmask"); 156 157 if (info.debug) { 158 // Do not inherit setgid powers. 159 if (setgid(getgid()) != 0) 160 ExitWithError(error_fd, "setgid"); 161 162 // HACK: 163 // Close everything besides stdin, stdout, and stderr that has no file 164 // action to avoid leaking. Only do this when debugging, as elsewhere we 165 // actually rely on passing open descriptors to child processes. 166 // NB: This code is not async-signal safe, but we currently do not launch 167 // processes for debugging from within multithreaded contexts. 168 169 const llvm::StringRef proc_fd_path = "/proc/self/fd"; 170 std::error_code ec; 171 bool result; 172 ec = llvm::sys::fs::is_directory(proc_fd_path, result); 173 if (result) { 174 std::vector<int> files_to_close; 175 // Directory iterator doesn't ensure any sequence. 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)); 179 180 // Don't close first three entries since they are stdin, stdout and 181 // stderr. 182 if (fd > 2 && !info.has_action(fd) && fd != error_fd) 183 files_to_close.push_back(fd); 184 } 185 for (int file_to_close : files_to_close) 186 close(file_to_close); 187 } else { 188 // Since /proc/self/fd didn't work, trying the slow way instead. 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) 192 close(fd); 193 } 194 195 // Start tracing this child that is about to exec. 196 if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1) 197 ExitWithError(error_fd, "ptrace"); 198 } 199 200 // Execute. We should never return... 201 execve(info.argv[0], const_cast<char *const *>(info.argv), info.envp); 202 203 #if defined(__linux__) 204 if (errno == ETXTBSY) { 205 // On android M and earlier we can get this error because the adb daemon 206 // can hold a write handle on the executable even after it has finished 207 // uploading it. This state lasts only a short time and happens only when 208 // there are many concurrent adb commands being issued, such as when 209 // running the test suite. (The file remains open when someone does an "adb 210 // shell" command in the fork() child before it has had a chance to exec.) 211 // Since this state should clear up quickly, wait a while and then give it 212 // one more go. 213 usleep(50000); 214 execve(info.argv[0], const_cast<char *const *>(info.argv), info.envp); 215 } 216 #endif 217 218 // ...unless exec fails. In which case we definitely need to end the child 219 // here. 220 ExitWithError(error_fd, "execve"); 221 } 222 223 // End of code running in the child process. 224 225 ForkFileAction::ForkFileAction(const FileAction &act) 226 : action(act.GetAction()), fd(act.GetFD()), path(act.GetPath().str()), 227 arg(act.GetActionArgument()) {} 228 229 static std::vector<ForkFileAction> 230 MakeForkActions(const ProcessLaunchInfo &info) { 231 std::vector<ForkFileAction> result; 232 for (size_t i = 0; i < info.GetNumFileActions(); ++i) 233 result.emplace_back(*info.GetFileActionAtIndex(i)); 234 return result; 235 } 236 237 static Environment::Envp FixupEnvironment(Environment env) { 238 #ifdef __ANDROID__ 239 // If there is no PATH variable specified inside the environment then set the 240 // path to /system/bin. It is required because the default path used by 241 // execve() is wrong on android. 242 env.try_emplace("PATH", "/system/bin"); 243 #endif 244 return env.getEnvp(); 245 } 246 247 ForkLaunchInfo::ForkLaunchInfo(const ProcessLaunchInfo &info) 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()), 254 envp(FixupEnvironment(info.GetEnvironment())), 255 actions(MakeForkActions(info)) {} 256 257 HostProcess 258 ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info, 259 Status &error) { 260 // A pipe used by the child process to report errors. 261 PipePosix pipe; 262 const bool child_processes_inherit = false; 263 error = pipe.CreateNew(child_processes_inherit); 264 if (error.Fail()) 265 return HostProcess(); 266 267 const ForkLaunchInfo fork_launch_info(launch_info); 268 269 ::pid_t pid = ::fork(); 270 if (pid == -1) { 271 // Fork failed 272 error.SetErrorStringWithFormatv("Fork failed with error message: {0}", 273 llvm::sys::StrError()); 274 return HostProcess(LLDB_INVALID_PROCESS_ID); 275 } 276 if (pid == 0) { 277 // child process 278 pipe.CloseReadFileDescriptor(); 279 ChildFunc(pipe.ReleaseWriteFileDescriptor(), fork_launch_info); 280 } 281 282 // parent process 283 284 pipe.CloseWriteFileDescriptor(); 285 llvm::SmallString<0> buf; 286 size_t pos = 0; 287 ssize_t r = 0; 288 do { 289 pos += r; 290 buf.resize_for_overwrite(pos + 100); 291 r = llvm::sys::RetryAfterSignal(-1, read, pipe.GetReadFileDescriptor(), 292 buf.begin() + pos, buf.size() - pos); 293 } while (r > 0); 294 assert(r != -1); 295 296 buf.resize(pos); 297 if (buf.empty()) 298 return HostProcess(pid); // No error. We're done. 299 300 error.SetErrorString(buf); 301 302 llvm::sys::RetryAfterSignal(-1, waitpid, pid, nullptr, 0); 303 304 return HostProcess(); 305 } 306