blob: 1fe21d856a2a7dfd6be17e8c98d4cb40c39d0f39 [file] [log] [blame]
Garrick Evans64a2df32018-12-12 16:53:46 +09001// Copyright 2019 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
Garrick Evans3388a032020-03-24 11:25:55 +09005#ifndef PATCHPANEL_MINIJAILED_PROCESS_RUNNER_H_
6#define PATCHPANEL_MINIJAILED_PROCESS_RUNNER_H_
Garrick Evans64a2df32018-12-12 16:53:46 +09007
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09008#include <memory>
Hugo Benichi33860d72020-07-09 16:34:01 +09009#include <sys/types.h>
10
Garrick Evans64a2df32018-12-12 16:53:46 +090011#include <string>
12#include <vector>
13
14#include <brillo/minijail/minijail.h>
15
Garrick Evans3388a032020-03-24 11:25:55 +090016namespace patchpanel {
Garrick Evans64a2df32018-12-12 16:53:46 +090017
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +090018// Runs the current process with minimal privileges. This function is expected
19// to be used by child processes that need only CAP_NET_RAW and to run as the
Garrick Evans6776b502020-05-01 10:41:56 +090020// patchpaneld user.
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +090021void EnterChildProcessJail();
22
Garrick Evans64a2df32018-12-12 16:53:46 +090023// Enforces the expected processes are run with the correct privileges.
24class MinijailedProcessRunner {
25 public:
Jie Jiangcf5ce9c2020-07-14 17:22:03 +090026 // For mocking waitpid().
27 class SyscallImpl {
28 public:
29 virtual pid_t WaitPID(pid_t pid, int* wstatus, int options = 0);
30 virtual ~SyscallImpl() = default;
31 };
32
Garrick Evans64a2df32018-12-12 16:53:46 +090033 // Ownership of |mj| is not assumed and must be managed by the caller.
34 // If |mj| is null, the default instance will be used.
35 explicit MinijailedProcessRunner(brillo::Minijail* mj = nullptr);
Jie Jiangcf5ce9c2020-07-14 17:22:03 +090036 // Provided for testing only.
37 MinijailedProcessRunner(brillo::Minijail* mj,
38 std::unique_ptr<SyscallImpl> syscall);
Garrick Evans64a2df32018-12-12 16:53:46 +090039 virtual ~MinijailedProcessRunner() = default;
40
Garrick Evans8e8e3472020-01-23 14:03:50 +090041 // Runs brctl.
42 virtual int brctl(const std::string& cmd,
43 const std::vector<std::string>& argv,
44 bool log_failures = true);
Garrick Evans6d227b92019-12-03 16:11:29 +090045
46 // Runs chown to update file ownership.
Garrick Evans8e8e3472020-01-23 14:03:50 +090047 virtual int chown(const std::string& uid,
Garrick Evans6d227b92019-12-03 16:11:29 +090048 const std::string& gid,
Garrick Evans8e8e3472020-01-23 14:03:50 +090049 const std::string& file,
50 bool log_failures = true);
51
Garrick Evans8e8e3472020-01-23 14:03:50 +090052 // Runs ip.
53 virtual int ip(const std::string& obj,
54 const std::string& cmd,
55 const std::vector<std::string>& args,
56 bool log_failures = true);
57 virtual int ip6(const std::string& obj,
58 const std::string& cmd,
59 const std::vector<std::string>& args,
60 bool log_failures = true);
61
Jie Jiangcf5ce9c2020-07-14 17:22:03 +090062 // Runs iptables. If |output| is not nullptr, it will be filled with the
63 // result from stdout of iptables command.
Garrick Evans8e8e3472020-01-23 14:03:50 +090064 virtual int iptables(const std::string& table,
65 const std::vector<std::string>& argv,
Jie Jiangcf5ce9c2020-07-14 17:22:03 +090066 bool log_failures = true,
67 std::string* output = nullptr);
Garrick Evans8e8e3472020-01-23 14:03:50 +090068
69 virtual int ip6tables(const std::string& table,
70 const std::vector<std::string>& argv,
Jie Jiangcf5ce9c2020-07-14 17:22:03 +090071 bool log_failures = true,
72 std::string* output = nullptr);
Garrick Evans8e8e3472020-01-23 14:03:50 +090073
74 // Installs all |modules| via modprobe.
75 virtual int modprobe_all(const std::vector<std::string>& modules,
76 bool log_failures = true);
77
78 // Updates kernel parameter |key| to |value| using sysctl.
79 virtual int sysctl_w(const std::string& key,
80 const std::string& value,
81 bool log_failures = true);
82
Hugo Benichi33860d72020-07-09 16:34:01 +090083 // Attaches a name to the network namespace of the given pid
84 // TODO(hugobenichi) How can patchpanel create a |netns_name| file in
85 // /run/netns without running ip as root ?
86 virtual int ip_netns_attach(const std::string& netns_name,
87 pid_t netns_pid,
88 bool log_failures = true);
89
90 virtual int ip_netns_delete(const std::string& netns_name,
91 bool log_failures = true);
92
Garrick Evans8e8e3472020-01-23 14:03:50 +090093 protected:
94 // Runs a process (argv[0]) with optional arguments (argv[1]...)
95 // in a minijail as an unprivileged user with CAP_NET_ADMIN and
96 // CAP_NET_RAW capabilities.
97 virtual int Run(const std::vector<std::string>& argv,
98 bool log_failures = true);
Garrick Evans6d227b92019-12-03 16:11:29 +090099
Garrick Evans64a2df32018-12-12 16:53:46 +0900100 private:
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900101 int RunSyncDestroy(const std::vector<std::string>& argv,
102 brillo::Minijail* mj,
103 minijail* jail,
104 bool log_failures,
105 int* fd_stdout);
106 int RunSync(const std::vector<std::string>& argv,
107 brillo::Minijail* mj,
108 bool log_failures,
109 int* fd_stdout);
110
Garrick Evans64a2df32018-12-12 16:53:46 +0900111 brillo::Minijail* mj_;
112
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900113 std::unique_ptr<SyscallImpl> syscall_;
114
Garrick Evans64a2df32018-12-12 16:53:46 +0900115 DISALLOW_COPY_AND_ASSIGN(MinijailedProcessRunner);
116};
117
Garrick Evans3388a032020-03-24 11:25:55 +0900118} // namespace patchpanel
Garrick Evans64a2df32018-12-12 16:53:46 +0900119
Garrick Evans3388a032020-03-24 11:25:55 +0900120#endif // PATCHPANEL_MINIJAILED_PROCESS_RUNNER_H_