1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "brillo/process.h" 6 7 #include <fcntl.h> 8 #include <signal.h> 9 #include <stdint.h> 10 #include <sys/stat.h> 11 #include <sys/types.h> 12 #include <sys/wait.h> 13 #include <unistd.h> 14 15 #include <map> 16 17 #include <base/files/file_util.h> 18 #include <base/logging.h> 19 #include <base/posix/eintr_wrapper.h> 20 #include <base/process/process_metrics.h> 21 #include <base/strings/string_number_conversions.h> 22 #include <base/strings/string_util.h> 23 #include <base/time/time.h> 24 25 #ifndef __linux__ 26 #define setresuid(_u1, _u2, _u3) setreuid(_u1, _u2) 27 #define setresgid(_g1, _g2, _g3) setregid(_g1, _g2) 28 #endif // !__linux__ 29 30 namespace brillo { 31 32 bool ReturnTrue() { 33 return true; 34 } 35 36 Process::Process() { 37 } 38 39 Process::~Process() { 40 } 41 42 bool Process::ProcessExists(pid_t pid) { 43 return base::DirectoryExists( 44 base::FilePath(base::StringPrintf("/proc/%d", pid))); 45 } 46 47 ProcessImpl::ProcessImpl() 48 : pid_(0), 49 uid_(-1), 50 gid_(-1), 51 pre_exec_(base::Bind(&ReturnTrue)), 52 search_path_(false), 53 inherit_parent_signal_mask_(false), 54 close_unused_file_descriptors_(false) { 55 } 56 57 ProcessImpl::~ProcessImpl() { 58 Reset(0); 59 } 60 61 void ProcessImpl::AddArg(const std::string& arg) { 62 arguments_.push_back(arg); 63 } 64 65 void ProcessImpl::RedirectOutput(const std::string& output_file) { 66 output_file_ = output_file; 67 } 68 69 void ProcessImpl::RedirectUsingPipe(int child_fd, bool is_input) { 70 PipeInfo info; 71 info.is_input_ = is_input; 72 info.is_bound_ = false; 73 pipe_map_[child_fd] = info; 74 } 75 76 void ProcessImpl::BindFd(int parent_fd, int child_fd) { 77 PipeInfo info; 78 info.is_bound_ = true; 79 80 // info.child_fd_ is the 'child half' of the pipe, which gets dup2()ed into 81 // place over child_fd. Since we already have the child we want to dup2() into 82 // place, we can set info.child_fd_ to parent_fd and leave info.parent_fd_ 83 // invalid. 84 info.child_fd_ = parent_fd; 85 info.parent_fd_ = -1; 86 pipe_map_[child_fd] = info; 87 } 88 89 void ProcessImpl::SetCloseUnusedFileDescriptors(bool close_unused_fds) { 90 close_unused_file_descriptors_ = close_unused_fds; 91 } 92 93 void ProcessImpl::SetUid(uid_t uid) { 94 uid_ = uid; 95 } 96 97 void ProcessImpl::SetGid(gid_t gid) { 98 gid_ = gid; 99 } 100 101 void ProcessImpl::SetCapabilities(uint64_t /*capmask*/) { 102 // No-op, since ProcessImpl does not support sandboxing. 103 return; 104 } 105 106 void ProcessImpl::ApplySyscallFilter(const std::string& /*path*/) { 107 // No-op, since ProcessImpl does not support sandboxing. 108 return; 109 } 110 111 void ProcessImpl::EnterNewPidNamespace() { 112 // No-op, since ProcessImpl does not support sandboxing. 113 return; 114 } 115 116 void ProcessImpl::SetInheritParentSignalMask(bool inherit) { 117 inherit_parent_signal_mask_ = inherit; 118 } 119 120 void ProcessImpl::SetPreExecCallback(const PreExecCallback& cb) { 121 pre_exec_ = cb; 122 } 123 124 void ProcessImpl::SetSearchPath(bool search_path) { 125 search_path_ = search_path; 126 } 127 128 int ProcessImpl::GetPipe(int child_fd) { 129 PipeMap::iterator i = pipe_map_.find(child_fd); 130 if (i == pipe_map_.end()) 131 return -1; 132 else 133 return i->second.parent_fd_; 134 } 135 136 bool ProcessImpl::PopulatePipeMap() { 137 // Verify all target fds are already open. With this assumption we 138 // can be sure that the pipe fds created below do not overlap with 139 // any of the target fds which simplifies how we dup2 to them. Note 140 // that multi-threaded code could close i->first between this loop 141 // and the next. 142 for (PipeMap::iterator i = pipe_map_.begin(); i != pipe_map_.end(); ++i) { 143 struct stat stat_buffer; 144 if (fstat(i->first, &stat_buffer) < 0) { 145 int saved_errno = errno; 146 LOG(ERROR) << "Unable to fstat fd " << i->first << ": " << saved_errno; 147 return false; 148 } 149 } 150 151 for (PipeMap::iterator i = pipe_map_.begin(); i != pipe_map_.end(); ++i) { 152 if (i->second.is_bound_) { 153 // already have a parent fd, and the child fd gets dup()ed later. 154 continue; 155 } 156 int pipefds[2]; 157 if (pipe(pipefds) < 0) { 158 int saved_errno = errno; 159 LOG(ERROR) << "pipe call failed with: " << saved_errno; 160 return false; 161 } 162 if (i->second.is_input_) { 163 // pipe is an input from the prospective of the child. 164 i->second.parent_fd_ = pipefds[1]; 165 i->second.child_fd_ = pipefds[0]; 166 } else { 167 i->second.parent_fd_ = pipefds[0]; 168 i->second.child_fd_ = pipefds[1]; 169 } 170 } 171 return true; 172 } 173 174 bool ProcessImpl::IsFileDescriptorInPipeMap(int fd) const { 175 for (const auto& pipe : pipe_map_) { 176 if (fd == pipe.second.parent_fd_ || 177 fd == pipe.second.child_fd_ || 178 fd == pipe.first) { 179 return true; 180 } 181 } 182 return false; 183 } 184 185 void ProcessImpl::CloseUnusedFileDescriptors() { 186 size_t max_fds = base::GetMaxFds(); 187 for (size_t i = 0; i < max_fds; i++) { 188 const int fd = static_cast<int>(i); 189 190 // Ignore STD file descriptors. 191 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) { 192 continue; 193 } 194 195 // Ignore file descriptors used by the PipeMap, they will be handled 196 // by this process later on. 197 if (IsFileDescriptorInPipeMap(fd)) { 198 continue; 199 } 200 201 // Since we're just trying to close anything we can find, 202 // ignore any error return values of close(). 203 IGNORE_EINTR(close(fd)); 204 } 205 } 206 207 bool ProcessImpl::Start() { 208 // If no arguments are provided, fail. 209 if (arguments_.empty()) { 210 return false; 211 } 212 scoped_ptr<char*[]> argv(new char*[arguments_.size() + 1]); 213 214 for (size_t i = 0; i < arguments_.size(); ++i) 215 argv[i] = const_cast<char*>(arguments_[i].c_str()); 216 217 argv[arguments_.size()] = nullptr; 218 219 if (!PopulatePipeMap()) { 220 LOG(ERROR) << "Failing to start because pipe creation failed"; 221 return false; 222 } 223 224 pid_t pid = fork(); 225 int saved_errno = errno; 226 if (pid < 0) { 227 LOG(ERROR) << "Fork failed: " << saved_errno; 228 Reset(0); 229 return false; 230 } 231 232 if (pid == 0) { 233 // Executing inside the child process. 234 // Close unused file descriptors. 235 if (close_unused_file_descriptors_) { 236 CloseUnusedFileDescriptors(); 237 } 238 // Close parent's side of the child pipes. dup2 ours into place and 239 // then close our ends. 240 for (PipeMap::iterator i = pipe_map_.begin(); i != pipe_map_.end(); ++i) { 241 if (i->second.parent_fd_ != -1) 242 IGNORE_EINTR(close(i->second.parent_fd_)); 243 HANDLE_EINTR(dup2(i->second.child_fd_, i->first)); 244 } 245 // Defer the actual close() of the child fd until afterward; this lets the 246 // same child fd be bound to multiple fds using BindFd 247 for (PipeMap::iterator i = pipe_map_.begin(); i != pipe_map_.end(); ++i) { 248 IGNORE_EINTR(close(i->second.child_fd_)); 249 } 250 if (!output_file_.empty()) { 251 int output_handle = HANDLE_EINTR(open( 252 output_file_.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 253 0666)); 254 if (output_handle < 0) { 255 PLOG(ERROR) << "Could not create " << output_file_; 256 // Avoid exit() to avoid atexit handlers from parent. 257 _exit(kErrorExitStatus); 258 } 259 HANDLE_EINTR(dup2(output_handle, STDOUT_FILENO)); 260 HANDLE_EINTR(dup2(output_handle, STDERR_FILENO)); 261 // Only close output_handle if it does not happen to be one of 262 // the two standard file descriptors we are trying to redirect. 263 if (output_handle != STDOUT_FILENO && output_handle != STDERR_FILENO) { 264 IGNORE_EINTR(close(output_handle)); 265 } 266 } 267 if (gid_ != static_cast<gid_t>(-1) && setresgid(gid_, gid_, gid_) < 0) { 268 int saved_errno = errno; 269 LOG(ERROR) << "Unable to set GID to " << gid_ << ": " << saved_errno; 270 _exit(kErrorExitStatus); 271 } 272 if (uid_ != static_cast<uid_t>(-1) && setresuid(uid_, uid_, uid_) < 0) { 273 int saved_errno = errno; 274 LOG(ERROR) << "Unable to set UID to " << uid_ << ": " << saved_errno; 275 _exit(kErrorExitStatus); 276 } 277 if (!pre_exec_.Run()) { 278 LOG(ERROR) << "Pre-exec callback failed"; 279 _exit(kErrorExitStatus); 280 } 281 // Reset signal mask for the child process if not inheriting signal mask 282 // from the parent process. 283 if (!inherit_parent_signal_mask_) { 284 sigset_t signal_mask; 285 CHECK_EQ(0, sigemptyset(&signal_mask)); 286 CHECK_EQ(0, sigprocmask(SIG_SETMASK, &signal_mask, nullptr)); 287 } 288 if (search_path_) { 289 execvp(argv[0], &argv[0]); 290 } else { 291 execv(argv[0], &argv[0]); 292 } 293 PLOG(ERROR) << "Exec of " << argv[0] << " failed:"; 294 _exit(kErrorExitStatus); 295 } else { 296 // Still executing inside the parent process with known child pid. 297 arguments_.clear(); 298 UpdatePid(pid); 299 // Close our copy of child side pipes. 300 for (PipeMap::iterator i = pipe_map_.begin(); i != pipe_map_.end(); ++i) { 301 IGNORE_EINTR(close(i->second.child_fd_)); 302 } 303 } 304 return true; 305 } 306 307 int ProcessImpl::Wait() { 308 int status = 0; 309 if (pid_ == 0) { 310 LOG(ERROR) << "Process not running"; 311 return -1; 312 } 313 if (HANDLE_EINTR(waitpid(pid_, &status, 0)) < 0) { 314 int saved_errno = errno; 315 LOG(ERROR) << "Problem waiting for pid " << pid_ << ": " << saved_errno; 316 return -1; 317 } 318 pid_t old_pid = pid_; 319 // Update the pid to 0 - do not Reset as we do not want to try to 320 // kill the process that has just exited. 321 UpdatePid(0); 322 if (!WIFEXITED(status)) { 323 DCHECK(WIFSIGNALED(status)) << old_pid 324 << " neither exited, nor died on a signal?"; 325 LOG(ERROR) << "Process " << old_pid 326 << " did not exit normally: " << WTERMSIG(status); 327 return -1; 328 } 329 return WEXITSTATUS(status); 330 } 331 332 int ProcessImpl::Run() { 333 if (!Start()) { 334 return -1; 335 } 336 return Wait(); 337 } 338 339 pid_t ProcessImpl::pid() { 340 return pid_; 341 } 342 343 bool ProcessImpl::Kill(int signal, int timeout) { 344 if (pid_ == 0) { 345 // Passing pid == 0 to kill is committing suicide. Check specifically. 346 LOG(ERROR) << "Process not running"; 347 return false; 348 } 349 if (kill(pid_, signal) < 0) { 350 int saved_errno = errno; 351 LOG(ERROR) << "Unable to send signal to " << pid_ << " error " 352 << saved_errno; 353 return false; 354 } 355 base::TimeTicks start_signal = base::TimeTicks::Now(); 356 do { 357 int status = 0; 358 pid_t w = waitpid(pid_, &status, WNOHANG); 359 int saved_errno = errno; 360 if (w < 0) { 361 if (saved_errno == ECHILD) 362 return true; 363 LOG(ERROR) << "Waitpid returned " << w << ", errno " << saved_errno; 364 return false; 365 } 366 if (w > 0) { 367 Reset(0); 368 return true; 369 } 370 usleep(100); 371 } while ((base::TimeTicks::Now() - start_signal).InSecondsF() <= timeout); 372 LOG(INFO) << "process " << pid_ << " did not exit from signal " << signal 373 << " in " << timeout << " seconds"; 374 return false; 375 } 376 377 void ProcessImpl::UpdatePid(pid_t new_pid) { 378 pid_ = new_pid; 379 } 380 381 void ProcessImpl::Reset(pid_t new_pid) { 382 arguments_.clear(); 383 // Close our side of all pipes to this child giving the child to 384 // handle sigpipes and shutdown nicely, though likely it won't 385 // have time. 386 for (PipeMap::iterator i = pipe_map_.begin(); i != pipe_map_.end(); ++i) 387 IGNORE_EINTR(close(i->second.parent_fd_)); 388 pipe_map_.clear(); 389 if (pid_) 390 Kill(SIGKILL, 0); 391 UpdatePid(new_pid); 392 } 393 394 bool ProcessImpl::ResetPidByFile(const std::string& pid_file) { 395 std::string contents; 396 if (!base::ReadFileToString(base::FilePath(pid_file), &contents)) { 397 LOG(ERROR) << "Could not read pid file" << pid_file; 398 return false; 399 } 400 base::TrimWhitespaceASCII(contents, base::TRIM_TRAILING, &contents); 401 int64_t pid_int64 = 0; 402 if (!base::StringToInt64(contents, &pid_int64)) { 403 LOG(ERROR) << "Unexpected pid file contents"; 404 return false; 405 } 406 Reset(pid_int64); 407 return true; 408 } 409 410 pid_t ProcessImpl::Release() { 411 pid_t old_pid = pid_; 412 pid_ = 0; 413 return old_pid; 414 } 415 416 } // namespace brillo 417