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