| // Copyright 2012 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef CROS_DISKS_SANDBOXED_PROCESS_H_ | |
| #define CROS_DISKS_SANDBOXED_PROCESS_H_ | |
| #include <sys/types.h> | |
| #include <memory> | |
| #include <optional> | |
| #include <string> | |
| #include <vector> | |
| #include <base/containers/span.h> | |
| #include <base/files/file.h> | |
| #include <base/files/file_path.h> | |
| #include <base/functional/callback.h> | |
| #include "cros-disks/process.h" | |
| #include "cros-disks/sandboxed_init.h" | |
| struct minijail; | |
| namespace cros_disks { | |
| class SandboxedProcess : public Process { | |
| public: | |
| SandboxedProcess(); | |
| SandboxedProcess(const SandboxedProcess&) = delete; | |
| SandboxedProcess& operator=(const SandboxedProcess&) = delete; | |
| ~SandboxedProcess() override; | |
| bool KillPidNamespace() override; | |
| // Loads the seccomp filters from the given |file|. The calling process will | |
| // be aborted if |file| does not exist, cannot be read or is malformed. | |
| void SetSeccompPolicy(const base::FilePath& file); | |
| // Puts the process to be sandboxed in a new cgroup namespace. | |
| void NewCgroupNamespace(); | |
| // Puts the process to be sandboxed in a new IPC namespace. | |
| void NewIpcNamespace(); | |
| // Puts the process to be sandboxed in a new mount namespace. | |
| void NewMountNamespace(); | |
| // Puts the process to be sandboxed in an existing mount namespace. | |
| // Can be combined with NewMountNamespace() above: the process will first | |
| // enter the existing namespace and then unshare a new child namespace. | |
| void EnterExistingMountNamespace(const std::string& ns_path); | |
| // Puts the process to be sandboxed in a new network namespace. | |
| void NewNetworkNamespace(); | |
| // Puts the process to be sandboxed in a new PID namespace. | |
| void NewPidNamespace(); | |
| // Assuming the process is sandboxed in a new mount namespace, some essential | |
| // mountpoints like / and /proc are being set up. | |
| bool SetUpMinimalMounts(); | |
| // Maps a file or a folder into process' mount namespace. | |
| bool BindMount(const std::string& from, | |
| const std::string& to, | |
| bool writeable, | |
| bool recursive); | |
| // Mounts source to the specified folder in the new mount namespace. | |
| bool Mount(const std::string& src, | |
| const std::string& to, | |
| const std::string& type, | |
| const char* data); | |
| // Makes the process to call pivot_root for an empty /. | |
| bool EnterPivotRoot(); | |
| // Sets the no_new_privs bit. | |
| void SetNoNewPrivileges(); | |
| // Sets the process capabilities of the process to be sandboxed. | |
| void SetCapabilities(uint64_t capabilities); | |
| // Sets the primary group ID of the process to be sandboxed. | |
| void SetGroupId(gid_t group_id); | |
| // Sets the user ID of the process to be sandboxed. | |
| void SetUserId(uid_t user_id); | |
| // Sets supplementary group IDs of the process to be sandboxed. | |
| void SetSupplementaryGroupIds(base::span<const gid_t> gids); | |
| // Adds the minijail to |cgroup|. | |
| bool AddToCgroup(const std::string& cgroup); | |
| // Preserves the given file descriptor to still be available in the sandboxed | |
| // process. | |
| void PreserveFile(int fd); | |
| // Sets the flag that will simulate progress by delaying the execution of the | |
| // sandboxed program by 10 seconds. | |
| // | |
| // Precondition: NewPidNamespace() was called. | |
| void SimulateProgressForTesting() { | |
| DCHECK(use_pid_namespace_); | |
| simulate_progress_for_testing_ = true; | |
| } | |
| // Should the destruction of this SandboxedProcess trigger the destruction of | |
| // the PID namespace it manages and all the process that are still running in | |
| // it? | |
| void SetKillPidNamespace(const bool kill) { kill_pid_namespace_ = kill; } | |
| protected: | |
| // Process overrides: | |
| pid_t StartImpl(base::ScopedFD in_fd, base::ScopedFD out_fd) override; | |
| int WaitImpl() override; | |
| int WaitNonBlockingImpl() override; | |
| // Minijail object. | |
| minijail* jail_; | |
| // Does this SandboxedProcess use a PID namespace? | |
| bool use_pid_namespace_ = false; | |
| // Whether the destruction of this SandboxedProcess triggers the destruction | |
| // of the PID namespace and all the process that are still running in it. | |
| bool kill_pid_namespace_ = false; | |
| // Should simulate progress and delay the start of the process for testing? | |
| bool simulate_progress_for_testing_ = false; | |
| // Write end of the pipe used to terminate the init process inside the PID | |
| // namespace. This end of the pipe is closed when the SandboxedProcess | |
| // instance is destroyed, generating a SIGIO in the child init process, which | |
| // triggers termination of init and all its nested children. Only used when | |
| // |use_pid_namespace_| is true. | |
| base::ScopedFD termination_fd_; | |
| }; | |
| // Interface for creating preconfigured instances of |SandboxedProcess|. | |
| class SandboxedProcessFactory { | |
| public: | |
| SandboxedProcessFactory() = default; | |
| virtual ~SandboxedProcessFactory() = default; | |
| virtual std::unique_ptr<SandboxedProcess> CreateSandboxedProcess() const = 0; | |
| }; | |
| // Ties executable with the corresponding seccomp policy configuration. | |
| struct SandboxedExecutable { | |
| base::FilePath executable; | |
| base::FilePath seccomp_policy; | |
| }; | |
| // Fake SandboxedProcess for testing. Doesn't launch any actual process. | |
| class FakeSandboxedProcess : public SandboxedProcess { | |
| public: | |
| virtual int OnProcessLaunch(const std::vector<std::string>& argv); | |
| bool GetSimulateProgressForTesting() const { | |
| return simulate_progress_for_testing_; | |
| } | |
| private: | |
| pid_t StartImpl(base::ScopedFD, base::ScopedFD) final; | |
| int WaitImpl() final; | |
| int WaitNonBlockingImpl() final; | |
| std::optional<int> ret_code_; | |
| }; | |
| } // namespace cros_disks | |
| #endif // CROS_DISKS_SANDBOXED_PROCESS_H_ |