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