• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
AddStringOption(const std::string & option,const std::string & value)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.
AddIntOption(const std::string & option,int value)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 {
PipeInfoPipeInfo190      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