blob: 000188336b77450e5108b3e6c525483917e1b5aa [file] [log] [blame]
Ben Chan7e6fea02013-01-17 15:21:01 -08001// Copyright (c) 2013 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 CROS_DISKS_FUSE_MOUNTER_H_
6#define CROS_DISKS_FUSE_MOUNTER_H_
7
Anand K Mistry41a23962019-02-05 11:57:03 +11008#include <sys/types.h>
9
Sergei Datsenko6907a132019-04-01 11:26:56 +110010#include <memory>
Ben Chan7e6fea02013-01-17 15:21:01 -080011#include <string>
Sergei Datsenko1cf9f3d2019-01-02 14:39:48 +110012#include <vector>
Ben Chan7e6fea02013-01-17 15:21:01 -080013
Anand K Mistry41a23962019-02-05 11:57:03 +110014#include <base/files/file.h>
Jorge Lucangeli Obes0a388a22020-04-06 11:43:21 -040015#include <base/files/file_path.h>
François Degros54abc1d2020-02-05 18:43:21 +110016#include <base/strings/string_piece.h>
Anand K Mistry41a23962019-02-05 11:57:03 +110017
François Degrosaec21fb2020-03-06 15:23:43 +110018#include "cros-disks/metrics.h"
Ben Chan7e6fea02013-01-17 15:21:01 -080019#include "cros-disks/mounter.h"
Sergei Datsenkoadd282e2020-11-16 15:41:24 +110020#include "cros-disks/sandboxed_process.h"
21#include "cros-disks/user.h"
Ben Chan7e6fea02013-01-17 15:21:01 -080022
Sergei Datsenkoa910bba2019-06-18 13:31:59 +100023namespace brillo {
24class ProcessReaper;
25} // namespace brillo
26
Ben Chan7e6fea02013-01-17 15:21:01 -080027namespace cros_disks {
28
29class Platform;
François Degros5c6d9cb2020-07-16 13:44:44 +100030class Process;
Sergei Datsenko6907a132019-04-01 11:26:56 +110031class SandboxedProcess;
Ben Chan7e6fea02013-01-17 15:21:01 -080032
Sergei Datsenkoadd282e2020-11-16 15:41:24 +110033// Class for creating instances of SandboxedProcess with appropriate
34// configuration.
35class FUSESandboxedProcessFactory : public SandboxedProcessFactory {
36 public:
37 FUSESandboxedProcessFactory(
38 const Platform* platform,
39 SandboxedExecutable executable,
40 OwnerUser run_as,
41 bool has_network_access = false,
42 std::vector<gid_t> supplementary_groups = {},
43 base::Optional<base::FilePath> mount_namespace = {});
44 ~FUSESandboxedProcessFactory() override;
45
46 // Returns pre-configured sandbox with the most essential set up. Additional
47 // per-instance configuration should be done by the caller if needed.
48 std::unique_ptr<SandboxedProcess> CreateSandboxedProcess() const override;
49
50 const base::FilePath& executable() const { return executable_; }
51 const OwnerUser& run_as() const { return run_as_; }
52
53 private:
54 friend class FUSESandboxedProcessFactoryTest;
55
56 bool ConfigureSandbox(SandboxedProcess* sandbox) const;
57
58 const Platform* const platform_;
59
60 // Path to the FUSE daemon executable.
61 const base::FilePath executable_;
62
63 // Path to the seccomp policy configuration.
64 const base::Optional<base::FilePath> seccomp_policy_;
65
66 // UID/GID to run the FUSE daemon as.
67 const OwnerUser run_as_;
68
69 // Whether to leave network accessible from the sandbox.
70 const bool has_network_access_;
71
72 // Additional groups to associate with the FUSE daemon process.
73 const std::vector<gid_t> supplementary_groups_;
74
75 // Path identifying the mount namespace to use.
76 const base::Optional<base::FilePath> mount_namespace_;
77};
78
Sergei Datsenko199f4f42020-10-08 10:47:12 +110079// Uprivileged mounting of any FUSE filesystem. Filesystem-specific set up
80// and sandboxing is to be done in a subclass.
81class FUSEMounter : public Mounter {
82 public:
Sergei Datsenko1d2cbf82020-12-08 21:54:42 +110083 struct Config {
84 bool nosymfollow = true;
85 bool read_only = false;
86 };
87
Sergei Datsenko199f4f42020-10-08 10:47:12 +110088 FUSEMounter(const Platform* platform,
89 brillo::ProcessReaper* process_reaper,
90 std::string filesystem_type,
Sergei Datsenko1d2cbf82020-12-08 21:54:42 +110091 Config config);
Qijiang Fan6bc59e12020-11-11 02:51:06 +090092 FUSEMounter(const FUSEMounter&) = delete;
93 FUSEMounter& operator=(const FUSEMounter&) = delete;
Sergei Datsenko199f4f42020-10-08 10:47:12 +110094 ~FUSEMounter() override;
95
96 const Platform* platform() const { return platform_; }
97 brillo::ProcessReaper* process_reaper() const { return process_reaper_; }
Sergei Datsenkof5553d12020-11-25 07:51:59 +110098 const std::string& filesystem_type() const { return filesystem_type_; }
Sergei Datsenko199f4f42020-10-08 10:47:12 +110099
100 // Mounter overrides:
101 std::unique_ptr<MountPoint> Mount(const std::string& source,
102 const base::FilePath& target_path,
103 std::vector<std::string> params,
104 MountErrorType* error) const final;
105
106 protected:
Sergei Datsenko88035aa2020-11-15 00:24:01 +1100107 // Translates mount app's return codes into errors. The base
108 // implementation just assumes any non-zero return code to be a
109 // MOUNT_ERROR_MOUNT_PROGRAM_FAILED, but subclasses can implement more
110 // elaborate mappings.
111 virtual MountErrorType InterpretReturnCode(int return_code) const;
112
113 // Performs necessary set up and makes a SandboxedProcess ready to be
114 // launched to serve a mount. The returned instance will have one more
115 // last argument added to indicate the FUSE mount path according to
116 // fusermount's conventions, so implementation doesn't have to do this,
117 // |target_path| is purely informational.
118 virtual std::unique_ptr<SandboxedProcess> PrepareSandbox(
119 const std::string& source,
120 const base::FilePath& target_path,
121 std::vector<std::string> params,
122 MountErrorType* error) const = 0;
123
124 private:
Sergei Datsenko199f4f42020-10-08 10:47:12 +1100125 // Performs necessary set up and launches FUSE daemon that communicates to
126 // FUSE kernel layer via the |fuse_file|. Returns PID of the daemon process.
Sergei Datsenko88035aa2020-11-15 00:24:01 +1100127 pid_t StartDaemon(const base::File& fuse_file,
128 const std::string& source,
129 const base::FilePath& target_path,
130 std::vector<std::string> params,
131 MountErrorType* error) const;
Sergei Datsenko199f4f42020-10-08 10:47:12 +1100132
133 private:
134 const Platform* const platform_;
135 brillo::ProcessReaper* const process_reaper_;
136 const std::string filesystem_type_;
Sergei Datsenko1d2cbf82020-12-08 21:54:42 +1100137 const Config config_;
Sergei Datsenko199f4f42020-10-08 10:47:12 +1100138};
139
Sergei Datsenkof5553d12020-11-25 07:51:59 +1100140// A convenience class to tie FUSE mounter with a sandbox configuration.
141class FUSEMounterHelper : public FUSEMounter {
142 public:
143 FUSEMounterHelper(const Platform* platform,
144 brillo::ProcessReaper* process_reaper,
145 std::string filesystem_type,
146 bool nosymfollow,
147 const SandboxedProcessFactory* sandbox_factory);
148 FUSEMounterHelper(const FUSEMounterHelper&) = delete;
149 FUSEMounterHelper& operator=(const FUSEMounterHelper&) = delete;
150 ~FUSEMounterHelper() override;
151
152 protected:
153 const SandboxedProcessFactory* sandbox_factory() const {
154 return sandbox_factory_;
155 }
156
157 // FUSEMounter overrides:
158 std::unique_ptr<SandboxedProcess> PrepareSandbox(
159 const std::string& source,
160 const base::FilePath& target_path,
161 std::vector<std::string> params,
162 MountErrorType* error) const final;
163
164 virtual MountErrorType ConfigureSandbox(const std::string& source,
165 const base::FilePath& target_path,
166 std::vector<std::string> params,
167 SandboxedProcess* sandbox) const = 0;
168
169 private:
170 const SandboxedProcessFactory* const sandbox_factory_;
171};
172
Ben Chan7e6fea02013-01-17 15:21:01 -0800173} // namespace cros_disks
174
175#endif // CROS_DISKS_FUSE_MOUNTER_H_