xref: /aosp_15_r20/external/libbrillo/brillo/process.h (revision 1a96fba65179ea7d3f56207137718607415c5953)
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