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