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 #ifndef LIBBRILLO_BRILLO_PROCESS_H_ 6 #define LIBBRILLO_BRILLO_PROCESS_H_ 7 8 #include <sys/types.h> 9 10 #include <map> 11 #include <string> 12 #include <vector> 13 14 #include <base/bind.h> 15 #include <base/callback.h> 16 #include <base/files/file_path.h> 17 #include <base/strings/string_util.h> 18 #include <base/strings/stringprintf.h> 19 #include <brillo/brillo_export.h> 20 #include <gtest/gtest_prod.h> 21 22 namespace brillo { 23 // Manages a process. Can create the process, attach to an existing 24 // process by pid or pid file, and kill the process. Upon destruction 25 // any managed process is killed with SIGKILL. Use Release() to 26 // release the process from management. A given system process may 27 // only be managed by one Process at a time. 28 class BRILLO_EXPORT Process { 29 public: 30 Process(); 31 virtual ~Process(); 32 33 // Adds |arg| to the executable command-line to be run. The 34 // executable name itself is the first argument. 35 virtual void AddArg(const std::string& arg) = 0; 36 37 // Adds |option| and |value| as an option with a string value to the 38 // command line to be run. AddStringOption(const std::string & option,const std::string & value)39 inline void AddStringOption(const std::string& option, 40 const std::string& value) { 41 AddArg(option); 42 AddArg(value); 43 } 44 45 // Adds |option| and |value| as an option which takes an integer 46 // value to the command line to be run. AddIntOption(const std::string & option,int value)47 inline void AddIntOption(const std::string& option, int value) { 48 AddArg(option); 49 AddArg(base::StringPrintf("%d", value)); 50 } 51 52 // Redirects to read stdin from |input_file|. |input_file| must not be 53 // a symlink. 54 virtual void RedirectInput(const std::string& input_file) = 0; 55 56 // Redirects stderr and stdout to |output_file|. |output_file| must not be 57 // a symlink. 58 virtual void RedirectOutput(const std::string& output_file) = 0; 59 60 // Indicates we want to redirect |child_fd| in the child process's 61 // file table to a pipe. |child_fd| will be available for reading 62 // from child process's perspective iff |is_input|. 63 virtual void RedirectUsingPipe(int child_fd, bool is_input) = 0; 64 65 // Binds the given file descriptor in the parent to the given file 66 // descriptor in the child. 67 virtual void BindFd(int parent_fd, int child_fd) = 0; 68 69 // Set a flag |close_unused_fds| to indicate if the child process 70 // should close all unused file descriptors inherited from the 71 // parent process. This will not close the file descriptors for 72 // the standard streams (stdin, stdout, and stderr). 73 virtual void SetCloseUnusedFileDescriptors(bool close_unused_fds) = 0; 74 75 // Set the real/effective/saved user ID of the child process. 76 virtual void SetUid(uid_t uid) = 0; 77 78 // Set the real/effective/saved group ID of the child process. 79 virtual void SetGid(gid_t gid) = 0; 80 81 // Set the capabilities assigned to the child process. 82 // NOTE: |capmask| is indeed a mask and should be passed in as the result of 83 // the CAP_TO_MASK(capability) macro, e.g. 84 // my_process.SetCapabilities(CAP_TO_MASK(CAP_SETUID) | 85 // CAP_TO_MASK(CAP_SETGID)); 86 // NOTE: supporting this sandboxing feature is optional (provide no-op 87 // implementation if your Process implementation does not support this). 88 virtual void SetCapabilities(uint64_t capmask) = 0; 89 90 // Apply a syscall filter to the process using the policy file at |path|. 91 // NOTE: supporting this sandboxing feature is optional (provide no-op 92 // implementation if your Process implementation does not support this). 93 virtual void ApplySyscallFilter(const std::string& path) = 0; 94 95 // Enter new PID namespace when this process is run. 96 // NOTE: supporting this sandboxing feature is optional (provide no-op 97 // implementation if your Process implementation does not support this). 98 virtual void EnterNewPidNamespace() = 0; 99 100 // Set a flag |inherit| to indicate if the child process intend to 101 // inherit signal mask from the parent process. When |inherit| is 102 // set to true, the child process will inherit signal mask from the 103 // parent process. This could cause unintended side effect, where all 104 // the signals to the child process might be blocked if they are set 105 // in the parent's signal mask. 106 virtual void SetInheritParentSignalMask(bool inherit) = 0; 107 108 typedef base::Callback<bool(void)> PreExecCallback; 109 110 // Set the pre-exec callback. This is called after all setup is complete but 111 // before we exec() the process. The callback may return false to cause Start 112 // to return false without starting the process. 113 virtual void SetPreExecCallback(const PreExecCallback& cb) = 0; 114 115 // Sets whether starting the process should search the system path or not. 116 // By default the system path will not be searched. 117 virtual void SetSearchPath(bool search_path) = 0; 118 119 // Gets the pipe file descriptor mapped to the process's |child_fd|. 120 virtual int GetPipe(int child_fd) = 0; 121 122 // Starts this process, returning true if successful. 123 virtual bool Start() = 0; 124 125 // Waits for this process to finish. Returns the process's exit 126 // status if it exited normally, or otherwise returns -1. Note 127 // that kErrorExitStatus may be returned if an error occurred 128 // after forking and before execing the child process. 129 virtual int Wait() = 0; 130 131 // Start and wait for this process to finish. Returns same value as 132 // Wait(). 133 virtual int Run() = 0; 134 135 // Returns the pid of this process or else returns 0 if there is no 136 // corresponding process (either because it has not yet been started 137 // or has since exited). 138 virtual pid_t pid() = 0; 139 140 // Sends |signal| to process and wait |timeout| seconds until it 141 // dies. If process is not a child, returns immediately with a 142 // value based on whether kill was successful. If the process is a 143 // child and |timeout| is non-zero, returns true if the process is 144 // able to be reaped within the given |timeout| in seconds. 145 virtual bool Kill(int signal, int timeout) = 0; 146 147 // Resets this Process object to refer to the process with |pid|. 148 // If |pid| is zero, this object no longer refers to a process. 149 virtual void Reset(pid_t new_pid) = 0; 150 151 // Same as Reset but reads the pid from |pid_file|. Returns false 152 // only when the file cannot be read/parsed. 153 virtual bool ResetPidByFile(const std::string& pid_file) = 0; 154 155 // Releases the process so that on destruction, the process is not killed. 156 virtual pid_t Release() = 0; 157 158 // Returns if |pid| is a currently running process. 159 static bool ProcessExists(pid_t pid); 160 161 // When returned from Wait or Run, indicates an error may have occurred 162 // creating the process. 163 enum { kErrorExitStatus = 127 }; 164 }; 165 166 class BRILLO_EXPORT ProcessImpl : public Process { 167 public: 168 ProcessImpl(); 169 virtual ~ProcessImpl(); 170 171 virtual void AddArg(const std::string& arg); 172 virtual void RedirectInput(const std::string& input_file); 173 virtual void RedirectOutput(const std::string& output_file); 174 virtual void RedirectUsingPipe(int child_fd, bool is_input); 175 virtual void BindFd(int parent_fd, int child_fd); 176 virtual void SetCloseUnusedFileDescriptors(bool close_unused_fds); 177 virtual void SetUid(uid_t uid); 178 virtual void SetGid(gid_t gid); 179 virtual void SetCapabilities(uint64_t capmask); 180 virtual void ApplySyscallFilter(const std::string& path); 181 virtual void EnterNewPidNamespace(); 182 virtual void SetInheritParentSignalMask(bool inherit); 183 virtual void SetPreExecCallback(const PreExecCallback& cb); 184 virtual void SetSearchPath(bool search_path); 185 virtual int GetPipe(int child_fd); 186 virtual bool Start(); 187 virtual int Wait(); 188 virtual int Run(); 189 virtual pid_t pid(); 190 virtual bool Kill(int signal, int timeout); 191 virtual void Reset(pid_t pid); 192 virtual bool ResetPidByFile(const std::string& pid_file); 193 virtual pid_t Release(); 194 195 protected: 196 struct PipeInfo { PipeInfoPipeInfo197 PipeInfo() : parent_fd_(-1), child_fd_(-1), is_input_(false) {} 198 // Parent (our) side of the pipe to the child process. 199 int parent_fd_; 200 // Child's side of the pipe to the parent. 201 int child_fd_; 202 // Is this an input or output pipe from child's perspective. 203 bool is_input_; 204 // Is this a bound (pre-existing) file descriptor? 205 bool is_bound_; 206 }; 207 typedef std::map<int, PipeInfo> PipeMap; 208 209 void UpdatePid(pid_t new_pid); 210 bool PopulatePipeMap(); 211 212 private: 213 FRIEND_TEST(ProcessTest, ResetPidByFile); 214 215 bool IsFileDescriptorInPipeMap(int fd) const; 216 void CloseUnusedFileDescriptors(); 217 218 // Pid of currently managed process or 0 if no currently managed 219 // process. pid must not be modified except by calling 220 // UpdatePid(new_pid). 221 pid_t pid_; 222 std::string input_file_; 223 std::string output_file_; 224 std::vector<std::string> arguments_; 225 // Map of child target file descriptors (first) to information about 226 // pipes created (second). 227 PipeMap pipe_map_; 228 uid_t uid_; 229 gid_t gid_; 230 PreExecCallback pre_exec_; 231 bool search_path_; 232 // Flag indicating to inherit signal mask from the parent process. It 233 // is set to false by default, which means by default the child process 234 // will not inherit signal mask from the parent process. 235 bool inherit_parent_signal_mask_; 236 // Flag indicating to close unused file descriptors inherited from the 237 // parent process when starting the child process, which avoids leaking 238 // unnecessary file descriptors to the child process. 239 bool close_unused_file_descriptors_; 240 }; 241 242 } // namespace brillo 243 244 #endif // LIBBRILLO_BRILLO_PROCESS_H_ 245