Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 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 CROS_DISKS_SANDBOXED_PROCESS_H_ |
| 6 | #define CROS_DISKS_SANDBOXED_PROCESS_H_ |
| 7 | |
| 8 | #include <sys/types.h> |
| 9 | |
Sergei Datsenko | add282e | 2020-11-16 15:41:24 +1100 | [diff] [blame] | 10 | #include <memory> |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 11 | #include <string> |
Austin Tankiang | 9318502 | 2019-05-20 14:13:20 +1000 | [diff] [blame] | 12 | #include <vector> |
| 13 | |
François Degros | 54abc1d | 2020-02-05 18:43:21 +1100 | [diff] [blame] | 14 | #include <base/containers/span.h> |
Austin Tankiang | 9318502 | 2019-05-20 14:13:20 +1000 | [diff] [blame] | 15 | #include <base/files/file.h> |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 16 | |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 17 | #include "cros-disks/process.h" |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 18 | |
| 19 | struct minijail; |
| 20 | |
| 21 | namespace cros_disks { |
| 22 | |
Ben Chan | 6f391cb | 2012-03-21 17:38:21 -0700 | [diff] [blame] | 23 | class SandboxedProcess : public Process { |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 24 | public: |
| 25 | SandboxedProcess(); |
Qijiang Fan | 6bc59e1 | 2020-11-11 02:51:06 +0900 | [diff] [blame] | 26 | SandboxedProcess(const SandboxedProcess&) = delete; |
| 27 | SandboxedProcess& operator=(const SandboxedProcess&) = delete; |
| 28 | |
Ben Chan | 1c6c194 | 2014-08-12 09:48:29 -0700 | [diff] [blame] | 29 | ~SandboxedProcess() override; |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 30 | |
Ben Chan | 98f8ae0 | 2011-10-04 16:34:34 -0700 | [diff] [blame] | 31 | // Loads the seccomp filters from |policy_file|. The calling process will be |
| 32 | // aborted if |policy_file| does not exist, cannot be read or is malformed. |
| 33 | void LoadSeccompFilterPolicy(const std::string& policy_file); |
| 34 | |
Ben Chan | 0dd4188 | 2017-05-24 00:46:10 -0700 | [diff] [blame] | 35 | // Puts the process to be sandboxed in a new cgroup namespace. |
| 36 | void NewCgroupNamespace(); |
| 37 | |
| 38 | // Puts the process to be sandboxed in a new IPC namespace. |
| 39 | void NewIpcNamespace(); |
| 40 | |
Ben Chan | 44125df | 2017-05-22 11:29:11 -0700 | [diff] [blame] | 41 | // Puts the process to be sandboxed in a new mount namespace. |
| 42 | void NewMountNamespace(); |
| 43 | |
Jorge Lucangeli Obes | 0a388a2 | 2020-04-06 11:43:21 -0400 | [diff] [blame] | 44 | // Puts the process to be sandboxed in an existing mount namespace. |
| 45 | // Can be combined with NewMountNamespace() above: the process will first |
| 46 | // enter the existing namespace and then unshare a new child namespace. |
| 47 | void EnterExistingMountNamespace(const std::string& ns_path); |
| 48 | |
Ben Chan | 0dd4188 | 2017-05-24 00:46:10 -0700 | [diff] [blame] | 49 | // Puts the process to be sandboxed in a new network namespace. |
| 50 | void NewNetworkNamespace(); |
| 51 | |
Sergei Datsenko | 495f5da | 2019-06-06 17:44:23 +1000 | [diff] [blame] | 52 | // Puts the process to be sandboxed in a new PID namespace. |
| 53 | void NewPidNamespace(); |
| 54 | |
Sergei Datsenko | 1cf9f3d | 2019-01-02 14:39:48 +1100 | [diff] [blame] | 55 | // Assuming the process is sandboxed in a new mount namespace, some essential |
| 56 | // mountpoints like / and /proc are being set up. |
| 57 | bool SetUpMinimalMounts(); |
| 58 | |
| 59 | // Maps a file or a folder into process' mount namespace. |
| 60 | bool BindMount(const std::string& from, |
| 61 | const std::string& to, |
Anand K Mistry | 956a550 | 2019-03-06 17:12:59 +1100 | [diff] [blame] | 62 | bool writeable, |
| 63 | bool recursive); |
Sergei Datsenko | 1cf9f3d | 2019-01-02 14:39:48 +1100 | [diff] [blame] | 64 | |
| 65 | // Mounts source to the specified folder in the new mount namespace. |
| 66 | bool Mount(const std::string& src, |
| 67 | const std::string& to, |
| 68 | const std::string& type, |
| 69 | const char* data); |
| 70 | |
| 71 | // Makes the process to call pivot_root for an empty /. |
| 72 | bool EnterPivotRoot(); |
| 73 | |
Ben Chan | 44125df | 2017-05-22 11:29:11 -0700 | [diff] [blame] | 74 | // Skips re-marking existing mounts as private. |
| 75 | void SkipRemountPrivate(); |
| 76 | |
Ben Chan | 0dd4188 | 2017-05-24 00:46:10 -0700 | [diff] [blame] | 77 | // Sets the no_new_privs bit. |
| 78 | void SetNoNewPrivileges(); |
| 79 | |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 80 | // Sets the process capabilities of the process to be sandboxed. |
| 81 | void SetCapabilities(uint64_t capabilities); |
| 82 | |
François Degros | 54abc1d | 2020-02-05 18:43:21 +1100 | [diff] [blame] | 83 | // Sets the primary group ID of the process to be sandboxed. |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 84 | void SetGroupId(gid_t group_id); |
| 85 | |
| 86 | // Sets the user ID of the process to be sandboxed. |
| 87 | void SetUserId(uid_t user_id); |
| 88 | |
François Degros | 54abc1d | 2020-02-05 18:43:21 +1100 | [diff] [blame] | 89 | // Sets supplementary group IDs of the process to be sandboxed. |
| 90 | void SetSupplementaryGroupIds(base::span<const gid_t> gids); |
| 91 | |
Derek Basehore | 1709caf | 2020-07-17 17:06:38 -0700 | [diff] [blame] | 92 | // Adds the minijail to |cgroup|. |
| 93 | bool AddToCgroup(const std::string& cgroup); |
| 94 | |
Austin Tankiang | 9318502 | 2019-05-20 14:13:20 +1000 | [diff] [blame] | 95 | // Close all open fds on fork. |
| 96 | void CloseOpenFds(); |
| 97 | |
| 98 | // Preserves |file| to still be available in the sandboxed process with the |
| 99 | // same file descriptor. Only effective if CloseOpenFds has been called. |
| 100 | bool PreserveFile(const base::File& file); |
| 101 | |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 102 | protected: |
| 103 | // Process overrides: |
François Degros | 1ef6994 | 2019-10-01 15:31:17 +1000 | [diff] [blame] | 104 | pid_t StartImpl(base::ScopedFD in_fd, |
| 105 | base::ScopedFD out_fd, |
| 106 | base::ScopedFD err_fd) override; |
Sergei Datsenko | cd676b7 | 2019-05-10 11:42:05 +1000 | [diff] [blame] | 107 | int WaitImpl() override; |
François Degros | 92bbea4 | 2019-09-13 10:42:52 +1000 | [diff] [blame] | 108 | int WaitNonBlockingImpl() override; |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 109 | |
| 110 | private: |
Ben Chan | 71daeac | 2014-09-08 09:03:36 -0700 | [diff] [blame] | 111 | minijail* jail_; |
Sergei Datsenko | 495f5da | 2019-06-06 17:44:23 +1000 | [diff] [blame] | 112 | bool run_custom_init_ = false; |
| 113 | base::ScopedFD custom_init_control_fd_; |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 114 | }; |
| 115 | |
Sergei Datsenko | add282e | 2020-11-16 15:41:24 +1100 | [diff] [blame] | 116 | // Interface for creating preconfigured instances of |SandboxedProcess|. |
| 117 | class SandboxedProcessFactory { |
| 118 | public: |
| 119 | SandboxedProcessFactory() = default; |
| 120 | virtual ~SandboxedProcessFactory() = default; |
| 121 | virtual std::unique_ptr<SandboxedProcess> CreateSandboxedProcess() const = 0; |
| 122 | }; |
| 123 | |
| 124 | // Ties executable with the corresponding seccomp policy configuration. |
| 125 | struct SandboxedExecutable { |
| 126 | base::FilePath executable; |
| 127 | base::Optional<base::FilePath> seccomp_policy = {}; |
| 128 | }; |
| 129 | |
Sergei Datsenko | f5553d1 | 2020-11-25 07:51:59 +1100 | [diff] [blame] | 130 | // Fake SandboxedProcess for testing. Doesn't launch any actual process. |
| 131 | class FakeSandboxedProcess : public SandboxedProcess { |
| 132 | public: |
| 133 | virtual int OnProcessLaunch(const std::vector<std::string>& argv); |
| 134 | |
| 135 | private: |
| 136 | pid_t StartImpl(base::ScopedFD, base::ScopedFD, base::ScopedFD) final; |
| 137 | int WaitImpl() final; |
| 138 | int WaitNonBlockingImpl() final; |
| 139 | |
| 140 | base::Optional<int> ret_code_; |
| 141 | }; |
| 142 | |
Ben Chan | f68ea49 | 2011-08-23 10:11:08 -0700 | [diff] [blame] | 143 | } // namespace cros_disks |
| 144 | |
| 145 | #endif // CROS_DISKS_SANDBOXED_PROCESS_H_ |