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