1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_permission_translation")]
6*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
7*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_permission_translation")]
8*bb4ee6a4SAndroid Build Coastguard Worker use std::str::FromStr;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
10*bb4ee6a4SAndroid Build Coastguard Worker
11*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_permission_translation")]
12*bb4ee6a4SAndroid Build Coastguard Worker use libc;
13*bb4ee6a4SAndroid Build Coastguard Worker #[allow(unused_imports)]
14*bb4ee6a4SAndroid Build Coastguard Worker use serde::de::Error;
15*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
16*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserializer;
17*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
18*bb4ee6a4SAndroid Build Coastguard Worker use serde_keyvalue::FromKeyValues;
19*bb4ee6a4SAndroid Build Coastguard Worker
20*bb4ee6a4SAndroid Build Coastguard Worker /// The caching policy that the file system should report to the FUSE client. By default the FUSE
21*bb4ee6a4SAndroid Build Coastguard Worker /// protocol uses close-to-open consistency. This means that any cached contents of the file are
22*bb4ee6a4SAndroid Build Coastguard Worker /// invalidated the next time that file is opened.
23*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize, FromKeyValues)]
24*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename_all = "kebab-case")]
25*bb4ee6a4SAndroid Build Coastguard Worker pub enum CachePolicy {
26*bb4ee6a4SAndroid Build Coastguard Worker /// The client should never cache file data and all I/O should be directly forwarded to the
27*bb4ee6a4SAndroid Build Coastguard Worker /// server. This policy must be selected when file contents may change without the knowledge of
28*bb4ee6a4SAndroid Build Coastguard Worker /// the FUSE client (i.e., the file system does not have exclusive access to the directory).
29*bb4ee6a4SAndroid Build Coastguard Worker Never,
30*bb4ee6a4SAndroid Build Coastguard Worker
31*bb4ee6a4SAndroid Build Coastguard Worker /// The client is free to choose when and how to cache file data. This is the default policy
32*bb4ee6a4SAndroid Build Coastguard Worker /// and uses close-to-open consistency as described in the enum documentation.
33*bb4ee6a4SAndroid Build Coastguard Worker #[default]
34*bb4ee6a4SAndroid Build Coastguard Worker Auto,
35*bb4ee6a4SAndroid Build Coastguard Worker
36*bb4ee6a4SAndroid Build Coastguard Worker /// The client should always cache file data. This means that the FUSE client will not
37*bb4ee6a4SAndroid Build Coastguard Worker /// invalidate any cached data that was returned by the file system the last time the file was
38*bb4ee6a4SAndroid Build Coastguard Worker /// opened. This policy should only be selected when the file system has exclusive access to
39*bb4ee6a4SAndroid Build Coastguard Worker /// the directory.
40*bb4ee6a4SAndroid Build Coastguard Worker Always,
41*bb4ee6a4SAndroid Build Coastguard Worker }
42*bb4ee6a4SAndroid Build Coastguard Worker
config_default_timeout() -> Duration43*bb4ee6a4SAndroid Build Coastguard Worker const fn config_default_timeout() -> Duration {
44*bb4ee6a4SAndroid Build Coastguard Worker Duration::from_secs(5)
45*bb4ee6a4SAndroid Build Coastguard Worker }
46*bb4ee6a4SAndroid Build Coastguard Worker
config_default_negative_timeout() -> Duration47*bb4ee6a4SAndroid Build Coastguard Worker const fn config_default_negative_timeout() -> Duration {
48*bb4ee6a4SAndroid Build Coastguard Worker Duration::ZERO
49*bb4ee6a4SAndroid Build Coastguard Worker }
50*bb4ee6a4SAndroid Build Coastguard Worker
config_default_posix_acl() -> bool51*bb4ee6a4SAndroid Build Coastguard Worker const fn config_default_posix_acl() -> bool {
52*bb4ee6a4SAndroid Build Coastguard Worker true
53*bb4ee6a4SAndroid Build Coastguard Worker }
54*bb4ee6a4SAndroid Build Coastguard Worker
config_default_security_ctx() -> bool55*bb4ee6a4SAndroid Build Coastguard Worker const fn config_default_security_ctx() -> bool {
56*bb4ee6a4SAndroid Build Coastguard Worker true
57*bb4ee6a4SAndroid Build Coastguard Worker }
58*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_timeout<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Duration, D::Error>59*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_timeout<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Duration, D::Error> {
60*bb4ee6a4SAndroid Build Coastguard Worker let secs = u64::deserialize(deserializer)?;
61*bb4ee6a4SAndroid Build Coastguard Worker
62*bb4ee6a4SAndroid Build Coastguard Worker Ok(Duration::from_secs(secs))
63*bb4ee6a4SAndroid Build Coastguard Worker }
64*bb4ee6a4SAndroid Build Coastguard Worker
65*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
deserialize_privileged_quota_uids<'de, D: Deserializer<'de>>( deserializer: D, ) -> Result<Vec<libc::uid_t>, D::Error>66*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_privileged_quota_uids<'de, D: Deserializer<'de>>(
67*bb4ee6a4SAndroid Build Coastguard Worker deserializer: D,
68*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Vec<libc::uid_t>, D::Error> {
69*bb4ee6a4SAndroid Build Coastguard Worker // space-separated list
70*bb4ee6a4SAndroid Build Coastguard Worker let s: &str = serde::Deserialize::deserialize(deserializer)?;
71*bb4ee6a4SAndroid Build Coastguard Worker s.split(" ")
72*bb4ee6a4SAndroid Build Coastguard Worker .map(|s| {
73*bb4ee6a4SAndroid Build Coastguard Worker s.parse::<libc::uid_t>().map_err(|e| {
74*bb4ee6a4SAndroid Build Coastguard Worker <D as Deserializer>::Error::custom(format!(
75*bb4ee6a4SAndroid Build Coastguard Worker "failed to parse priviledged quota uid {s}: {e}"
76*bb4ee6a4SAndroid Build Coastguard Worker ))
77*bb4ee6a4SAndroid Build Coastguard Worker })
78*bb4ee6a4SAndroid Build Coastguard Worker })
79*bb4ee6a4SAndroid Build Coastguard Worker .collect()
80*bb4ee6a4SAndroid Build Coastguard Worker }
81*bb4ee6a4SAndroid Build Coastguard Worker
82*bb4ee6a4SAndroid Build Coastguard Worker /// Permission structure that is configured to map the UID-GID at runtime
83*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_permission_translation")]
84*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Clone, Eq, PartialEq, Serialize)]
85*bb4ee6a4SAndroid Build Coastguard Worker pub struct PermissionData {
86*bb4ee6a4SAndroid Build Coastguard Worker /// UID to be set for all the files in the path inside guest.
87*bb4ee6a4SAndroid Build Coastguard Worker pub guest_uid: libc::uid_t,
88*bb4ee6a4SAndroid Build Coastguard Worker
89*bb4ee6a4SAndroid Build Coastguard Worker /// GID to be set for all the files in the path inside guest.
90*bb4ee6a4SAndroid Build Coastguard Worker pub guest_gid: libc::gid_t,
91*bb4ee6a4SAndroid Build Coastguard Worker
92*bb4ee6a4SAndroid Build Coastguard Worker /// UID to be set for all the files in the path in the host.
93*bb4ee6a4SAndroid Build Coastguard Worker pub host_uid: libc::uid_t,
94*bb4ee6a4SAndroid Build Coastguard Worker
95*bb4ee6a4SAndroid Build Coastguard Worker /// GID to be set for all the files in the path in the host.
96*bb4ee6a4SAndroid Build Coastguard Worker pub host_gid: libc::gid_t,
97*bb4ee6a4SAndroid Build Coastguard Worker
98*bb4ee6a4SAndroid Build Coastguard Worker /// umask to be set at runtime for the files in the path.
99*bb4ee6a4SAndroid Build Coastguard Worker pub umask: libc::mode_t,
100*bb4ee6a4SAndroid Build Coastguard Worker
101*bb4ee6a4SAndroid Build Coastguard Worker /// This is the absolute path from the root of the shared directory.
102*bb4ee6a4SAndroid Build Coastguard Worker pub perm_path: String,
103*bb4ee6a4SAndroid Build Coastguard Worker }
104*bb4ee6a4SAndroid Build Coastguard Worker
105*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_runtime_ugid_map")]
process_ugid_map(result: Vec<Vec<String>>) -> Result<Vec<PermissionData>, io::Error>106*bb4ee6a4SAndroid Build Coastguard Worker fn process_ugid_map(result: Vec<Vec<String>>) -> Result<Vec<PermissionData>, io::Error> {
107*bb4ee6a4SAndroid Build Coastguard Worker let mut permissions = Vec::new();
108*bb4ee6a4SAndroid Build Coastguard Worker
109*bb4ee6a4SAndroid Build Coastguard Worker for inner_vec in result {
110*bb4ee6a4SAndroid Build Coastguard Worker let guest_uid = match libc::uid_t::from_str(&inner_vec[0]) {
111*bb4ee6a4SAndroid Build Coastguard Worker Ok(uid) => uid,
112*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => {
113*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::from_raw_os_error(libc::EINVAL));
114*bb4ee6a4SAndroid Build Coastguard Worker }
115*bb4ee6a4SAndroid Build Coastguard Worker };
116*bb4ee6a4SAndroid Build Coastguard Worker
117*bb4ee6a4SAndroid Build Coastguard Worker let guest_gid = match libc::gid_t::from_str(&inner_vec[1]) {
118*bb4ee6a4SAndroid Build Coastguard Worker Ok(gid) => gid,
119*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => {
120*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::from_raw_os_error(libc::EINVAL));
121*bb4ee6a4SAndroid Build Coastguard Worker }
122*bb4ee6a4SAndroid Build Coastguard Worker };
123*bb4ee6a4SAndroid Build Coastguard Worker
124*bb4ee6a4SAndroid Build Coastguard Worker let host_uid = match libc::uid_t::from_str(&inner_vec[2]) {
125*bb4ee6a4SAndroid Build Coastguard Worker Ok(uid) => uid,
126*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => {
127*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::from_raw_os_error(libc::EINVAL));
128*bb4ee6a4SAndroid Build Coastguard Worker }
129*bb4ee6a4SAndroid Build Coastguard Worker };
130*bb4ee6a4SAndroid Build Coastguard Worker
131*bb4ee6a4SAndroid Build Coastguard Worker let host_gid = match libc::gid_t::from_str(&inner_vec[3]) {
132*bb4ee6a4SAndroid Build Coastguard Worker Ok(gid) => gid,
133*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => {
134*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::from_raw_os_error(libc::EINVAL));
135*bb4ee6a4SAndroid Build Coastguard Worker }
136*bb4ee6a4SAndroid Build Coastguard Worker };
137*bb4ee6a4SAndroid Build Coastguard Worker
138*bb4ee6a4SAndroid Build Coastguard Worker let umask = match libc::mode_t::from_str(&inner_vec[4]) {
139*bb4ee6a4SAndroid Build Coastguard Worker Ok(mode) => mode,
140*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => {
141*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::from_raw_os_error(libc::EINVAL));
142*bb4ee6a4SAndroid Build Coastguard Worker }
143*bb4ee6a4SAndroid Build Coastguard Worker };
144*bb4ee6a4SAndroid Build Coastguard Worker
145*bb4ee6a4SAndroid Build Coastguard Worker let perm_path = inner_vec[5].clone();
146*bb4ee6a4SAndroid Build Coastguard Worker
147*bb4ee6a4SAndroid Build Coastguard Worker // Create PermissionData and push it to the vector
148*bb4ee6a4SAndroid Build Coastguard Worker permissions.push(PermissionData {
149*bb4ee6a4SAndroid Build Coastguard Worker guest_uid,
150*bb4ee6a4SAndroid Build Coastguard Worker guest_gid,
151*bb4ee6a4SAndroid Build Coastguard Worker host_uid,
152*bb4ee6a4SAndroid Build Coastguard Worker host_gid,
153*bb4ee6a4SAndroid Build Coastguard Worker umask,
154*bb4ee6a4SAndroid Build Coastguard Worker perm_path,
155*bb4ee6a4SAndroid Build Coastguard Worker });
156*bb4ee6a4SAndroid Build Coastguard Worker }
157*bb4ee6a4SAndroid Build Coastguard Worker
158*bb4ee6a4SAndroid Build Coastguard Worker Ok(permissions)
159*bb4ee6a4SAndroid Build Coastguard Worker }
160*bb4ee6a4SAndroid Build Coastguard Worker
161*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_runtime_ugid_map")]
deserialize_ugid_map<'de, D: Deserializer<'de>>( deserializer: D, ) -> Result<Vec<PermissionData>, D::Error>162*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_ugid_map<'de, D: Deserializer<'de>>(
163*bb4ee6a4SAndroid Build Coastguard Worker deserializer: D,
164*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Vec<PermissionData>, D::Error> {
165*bb4ee6a4SAndroid Build Coastguard Worker // space-separated list
166*bb4ee6a4SAndroid Build Coastguard Worker let s: &str = serde::Deserialize::deserialize(deserializer)?;
167*bb4ee6a4SAndroid Build Coastguard Worker
168*bb4ee6a4SAndroid Build Coastguard Worker let result: Vec<Vec<String>> = s
169*bb4ee6a4SAndroid Build Coastguard Worker .split(';')
170*bb4ee6a4SAndroid Build Coastguard Worker .map(|group| group.trim().split(' ').map(String::from).collect())
171*bb4ee6a4SAndroid Build Coastguard Worker .collect();
172*bb4ee6a4SAndroid Build Coastguard Worker
173*bb4ee6a4SAndroid Build Coastguard Worker // Length Validation for each inner vector
174*bb4ee6a4SAndroid Build Coastguard Worker for inner_vec in &result {
175*bb4ee6a4SAndroid Build Coastguard Worker if inner_vec.len() != 6 {
176*bb4ee6a4SAndroid Build Coastguard Worker return Err(D::Error::custom(
177*bb4ee6a4SAndroid Build Coastguard Worker "Invalid ugid_map format. Each group must have 6 elements.",
178*bb4ee6a4SAndroid Build Coastguard Worker ));
179*bb4ee6a4SAndroid Build Coastguard Worker }
180*bb4ee6a4SAndroid Build Coastguard Worker }
181*bb4ee6a4SAndroid Build Coastguard Worker
182*bb4ee6a4SAndroid Build Coastguard Worker let permissions = match process_ugid_map(result) {
183*bb4ee6a4SAndroid Build Coastguard Worker Ok(p) => p,
184*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
185*bb4ee6a4SAndroid Build Coastguard Worker return Err(D::Error::custom(format!(
186*bb4ee6a4SAndroid Build Coastguard Worker "Error processing uid_gid_map: {}",
187*bb4ee6a4SAndroid Build Coastguard Worker e
188*bb4ee6a4SAndroid Build Coastguard Worker )));
189*bb4ee6a4SAndroid Build Coastguard Worker }
190*bb4ee6a4SAndroid Build Coastguard Worker };
191*bb4ee6a4SAndroid Build Coastguard Worker
192*bb4ee6a4SAndroid Build Coastguard Worker Ok(permissions)
193*bb4ee6a4SAndroid Build Coastguard Worker }
194*bb4ee6a4SAndroid Build Coastguard Worker
195*bb4ee6a4SAndroid Build Coastguard Worker /// Options that configure the behavior of the file system.
196*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, FromKeyValues)]
197*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields, rename_all = "snake_case")]
198*bb4ee6a4SAndroid Build Coastguard Worker pub struct Config {
199*bb4ee6a4SAndroid Build Coastguard Worker /// How long the FUSE client should consider directory entries and file/directory attributes to
200*bb4ee6a4SAndroid Build Coastguard Worker /// be valid.
201*bb4ee6a4SAndroid Build Coastguard Worker /// This value corresponds to `entry_timeout` and `attr_timeout` in
202*bb4ee6a4SAndroid Build Coastguard Worker /// [libfuse's `fuse_config`](https://libfuse.github.io/doxygen/structfuse__config.html), but
203*bb4ee6a4SAndroid Build Coastguard Worker /// we use the same value for the two.
204*bb4ee6a4SAndroid Build Coastguard Worker ///
205*bb4ee6a4SAndroid Build Coastguard Worker /// If the contents of a directory or the attributes of a file or directory can only be
206*bb4ee6a4SAndroid Build Coastguard Worker /// modified by the FUSE client (i.e., the file system has exclusive access), then this should
207*bb4ee6a4SAndroid Build Coastguard Worker /// be a large value.
208*bb4ee6a4SAndroid Build Coastguard Worker /// The default value for this option is 5 seconds.
209*bb4ee6a4SAndroid Build Coastguard Worker #[serde(
210*bb4ee6a4SAndroid Build Coastguard Worker default = "config_default_timeout",
211*bb4ee6a4SAndroid Build Coastguard Worker deserialize_with = "deserialize_timeout"
212*bb4ee6a4SAndroid Build Coastguard Worker )]
213*bb4ee6a4SAndroid Build Coastguard Worker pub timeout: Duration,
214*bb4ee6a4SAndroid Build Coastguard Worker
215*bb4ee6a4SAndroid Build Coastguard Worker /// How long the FUSE client can cache negative lookup results.
216*bb4ee6a4SAndroid Build Coastguard Worker /// If a file lookup fails, the client can assume the file doesn't exist until the timeout and
217*bb4ee6a4SAndroid Build Coastguard Worker /// won't send lookup.
218*bb4ee6a4SAndroid Build Coastguard Worker /// The value 0 means that negative lookup shouldn't be cached.
219*bb4ee6a4SAndroid Build Coastguard Worker ///
220*bb4ee6a4SAndroid Build Coastguard Worker /// If the contents of a directory can only be modified by the FUSE client (i.e., the file
221*bb4ee6a4SAndroid Build Coastguard Worker /// system has exclusive access), then this should be a large value.
222*bb4ee6a4SAndroid Build Coastguard Worker /// The default value for this option is 0 seconds (= no negative cache).
223*bb4ee6a4SAndroid Build Coastguard Worker #[serde(
224*bb4ee6a4SAndroid Build Coastguard Worker default = "config_default_negative_timeout",
225*bb4ee6a4SAndroid Build Coastguard Worker deserialize_with = "deserialize_timeout"
226*bb4ee6a4SAndroid Build Coastguard Worker )]
227*bb4ee6a4SAndroid Build Coastguard Worker pub negative_timeout: Duration,
228*bb4ee6a4SAndroid Build Coastguard Worker
229*bb4ee6a4SAndroid Build Coastguard Worker /// The caching policy the file system should use. See the documentation of `CachePolicy` for
230*bb4ee6a4SAndroid Build Coastguard Worker /// more details.
231*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default, alias = "cache")]
232*bb4ee6a4SAndroid Build Coastguard Worker pub cache_policy: CachePolicy,
233*bb4ee6a4SAndroid Build Coastguard Worker
234*bb4ee6a4SAndroid Build Coastguard Worker /// Whether the file system should enabled writeback caching. This can improve performance as
235*bb4ee6a4SAndroid Build Coastguard Worker /// it allows the FUSE client to cache and coalesce multiple writes before sending them to
236*bb4ee6a4SAndroid Build Coastguard Worker /// the file system. However, enabling this option can increase the risk of data corruption
237*bb4ee6a4SAndroid Build Coastguard Worker /// if the file contents can change without the knowledge of the FUSE client (i.e., the
238*bb4ee6a4SAndroid Build Coastguard Worker /// server does **NOT** have exclusive access). Additionally, the file system should have
239*bb4ee6a4SAndroid Build Coastguard Worker /// read access to all files in the directory it is serving as the FUSE client may send
240*bb4ee6a4SAndroid Build Coastguard Worker /// read requests even for files opened with `O_WRONLY`.
241*bb4ee6a4SAndroid Build Coastguard Worker ///
242*bb4ee6a4SAndroid Build Coastguard Worker /// Therefore callers should only enable this option when they can guarantee that: 1) the file
243*bb4ee6a4SAndroid Build Coastguard Worker /// system has exclusive access to the directory and 2) the file system has read permissions
244*bb4ee6a4SAndroid Build Coastguard Worker /// for all files in that directory.
245*bb4ee6a4SAndroid Build Coastguard Worker ///
246*bb4ee6a4SAndroid Build Coastguard Worker /// The default value for this option is `false`.
247*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
248*bb4ee6a4SAndroid Build Coastguard Worker pub writeback: bool,
249*bb4ee6a4SAndroid Build Coastguard Worker
250*bb4ee6a4SAndroid Build Coastguard Worker /// Controls whether security.* xattrs (except for security.selinux) are re-written. When this
251*bb4ee6a4SAndroid Build Coastguard Worker /// is set to true, the server will add a "user.virtiofs" prefix to xattrs in the security
252*bb4ee6a4SAndroid Build Coastguard Worker /// namespace. Setting these xattrs requires CAP_SYS_ADMIN in the namespace where the file
253*bb4ee6a4SAndroid Build Coastguard Worker /// system was mounted and since the server usually runs in an unprivileged user namespace,
254*bb4ee6a4SAndroid Build Coastguard Worker /// it's unlikely to have that capability.
255*bb4ee6a4SAndroid Build Coastguard Worker ///
256*bb4ee6a4SAndroid Build Coastguard Worker /// The default value for this option is `false`.
257*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default, alias = "rewrite-security-xattrs")]
258*bb4ee6a4SAndroid Build Coastguard Worker pub rewrite_security_xattrs: bool,
259*bb4ee6a4SAndroid Build Coastguard Worker
260*bb4ee6a4SAndroid Build Coastguard Worker /// Use case-insensitive lookups for directory entries (ASCII only).
261*bb4ee6a4SAndroid Build Coastguard Worker ///
262*bb4ee6a4SAndroid Build Coastguard Worker /// The default value for this option is `false`.
263*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
264*bb4ee6a4SAndroid Build Coastguard Worker pub ascii_casefold: bool,
265*bb4ee6a4SAndroid Build Coastguard Worker
266*bb4ee6a4SAndroid Build Coastguard Worker // UIDs which are privileged to perform quota-related operations. We cannot perform a
267*bb4ee6a4SAndroid Build Coastguard Worker // CAP_FOWNER check so we consult this list when the VM tries to set the project quota and
268*bb4ee6a4SAndroid Build Coastguard Worker // the process uid doesn't match the owner uid. In that case, all uids in this list are
269*bb4ee6a4SAndroid Build Coastguard Worker // treated as if they have CAP_FOWNER.
270*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
271*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default, deserialize_with = "deserialize_privileged_quota_uids")]
272*bb4ee6a4SAndroid Build Coastguard Worker pub privileged_quota_uids: Vec<libc::uid_t>,
273*bb4ee6a4SAndroid Build Coastguard Worker
274*bb4ee6a4SAndroid Build Coastguard Worker /// Use DAX for shared files.
275*bb4ee6a4SAndroid Build Coastguard Worker ///
276*bb4ee6a4SAndroid Build Coastguard Worker /// Enabling DAX can improve performance for frequently accessed files by mapping regions of
277*bb4ee6a4SAndroid Build Coastguard Worker /// the file directly into the VM's memory region, allowing direct access with the cost of
278*bb4ee6a4SAndroid Build Coastguard Worker /// slightly increased latency the first time the file is accessed. Additionally, since the
279*bb4ee6a4SAndroid Build Coastguard Worker /// mapping is shared directly from the host kernel's file cache, enabling DAX can improve
280*bb4ee6a4SAndroid Build Coastguard Worker /// performance even when the cache policy is `Never`.
281*bb4ee6a4SAndroid Build Coastguard Worker ///
282*bb4ee6a4SAndroid Build Coastguard Worker /// The default value for this option is `false`.
283*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default, alias = "dax")]
284*bb4ee6a4SAndroid Build Coastguard Worker pub use_dax: bool,
285*bb4ee6a4SAndroid Build Coastguard Worker
286*bb4ee6a4SAndroid Build Coastguard Worker /// Enable support for POSIX acls.
287*bb4ee6a4SAndroid Build Coastguard Worker ///
288*bb4ee6a4SAndroid Build Coastguard Worker /// Enable POSIX acl support for the shared directory. This requires that the underlying file
289*bb4ee6a4SAndroid Build Coastguard Worker /// system also supports POSIX acls.
290*bb4ee6a4SAndroid Build Coastguard Worker ///
291*bb4ee6a4SAndroid Build Coastguard Worker /// The default value for this option is `true`.
292*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default = "config_default_posix_acl")]
293*bb4ee6a4SAndroid Build Coastguard Worker pub posix_acl: bool,
294*bb4ee6a4SAndroid Build Coastguard Worker
295*bb4ee6a4SAndroid Build Coastguard Worker // Maximum number of dynamic permission paths.
296*bb4ee6a4SAndroid Build Coastguard Worker //
297*bb4ee6a4SAndroid Build Coastguard Worker // The dynamic permission paths are used to set specific paths certain uid/gid after virtiofs
298*bb4ee6a4SAndroid Build Coastguard Worker // device is created. It is for arcvm special usage, normal device should not support
299*bb4ee6a4SAndroid Build Coastguard Worker // this feature.
300*bb4ee6a4SAndroid Build Coastguard Worker //
301*bb4ee6a4SAndroid Build Coastguard Worker // The default value for this option is 0.
302*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
303*bb4ee6a4SAndroid Build Coastguard Worker pub max_dynamic_perm: usize,
304*bb4ee6a4SAndroid Build Coastguard Worker
305*bb4ee6a4SAndroid Build Coastguard Worker // Maximum number of dynamic xattr paths.
306*bb4ee6a4SAndroid Build Coastguard Worker //
307*bb4ee6a4SAndroid Build Coastguard Worker // The dynamic xattr paths are used to set specific paths certain xattr after virtiofs
308*bb4ee6a4SAndroid Build Coastguard Worker // device is created. It is for arcvm special usage, normal device should not support
309*bb4ee6a4SAndroid Build Coastguard Worker // this feature.
310*bb4ee6a4SAndroid Build Coastguard Worker //
311*bb4ee6a4SAndroid Build Coastguard Worker // The default value for this option is 0.
312*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
313*bb4ee6a4SAndroid Build Coastguard Worker pub max_dynamic_xattr: usize,
314*bb4ee6a4SAndroid Build Coastguard Worker
315*bb4ee6a4SAndroid Build Coastguard Worker // Controls whether fuse_security_context feature is enabled
316*bb4ee6a4SAndroid Build Coastguard Worker //
317*bb4ee6a4SAndroid Build Coastguard Worker // The FUSE_SECURITY_CONTEXT feature needs write data into /proc/thread-self/attr/fscreate.
318*bb4ee6a4SAndroid Build Coastguard Worker // For the hosts that prohibit the write operation, the option should be set to false to
319*bb4ee6a4SAndroid Build Coastguard Worker // disable the FUSE_SECURITY_CONTEXT feature. When FUSE_SECURITY_CONTEXT is disabled, the
320*bb4ee6a4SAndroid Build Coastguard Worker // security context won't be passed with fuse request, which makes guest created files/dir
321*bb4ee6a4SAndroid Build Coastguard Worker // having unlabeled security context or empty security context.
322*bb4ee6a4SAndroid Build Coastguard Worker //
323*bb4ee6a4SAndroid Build Coastguard Worker // The default value for this option is true
324*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default = "config_default_security_ctx")]
325*bb4ee6a4SAndroid Build Coastguard Worker pub security_ctx: bool,
326*bb4ee6a4SAndroid Build Coastguard Worker
327*bb4ee6a4SAndroid Build Coastguard Worker // Specifies run-time UID/GID mapping that works without user namespaces.
328*bb4ee6a4SAndroid Build Coastguard Worker //
329*bb4ee6a4SAndroid Build Coastguard Worker // The virtio-fs usually does mapping of UIDs/GIDs between host and guest with user namespace.
330*bb4ee6a4SAndroid Build Coastguard Worker // In Android, however, user namespace isn't available for non-root users.
331*bb4ee6a4SAndroid Build Coastguard Worker // This allows mapping UIDs and GIDs without user namespace by intercepting FUSE
332*bb4ee6a4SAndroid Build Coastguard Worker // requests and translating UID/GID in virito-fs's process at runtime.
333*bb4ee6a4SAndroid Build Coastguard Worker //
334*bb4ee6a4SAndroid Build Coastguard Worker // The format is "guest-uid, guest-gid, host-uid, host-gid, umask, path;{repeat}"
335*bb4ee6a4SAndroid Build Coastguard Worker //
336*bb4ee6a4SAndroid Build Coastguard Worker // guest-uid: UID to be set for all the files in the path inside guest.
337*bb4ee6a4SAndroid Build Coastguard Worker // guest-gid: GID to be set for all the files in the path inside guest.
338*bb4ee6a4SAndroid Build Coastguard Worker // host-uid: UID to be set for all the files in the path in the host.
339*bb4ee6a4SAndroid Build Coastguard Worker // host-gid: GID to be set for all the files in the path in the host.
340*bb4ee6a4SAndroid Build Coastguard Worker // umask: umask to be set at runtime for the files in the path.
341*bb4ee6a4SAndroid Build Coastguard Worker // path: This is the absolute path from the root of the shared directory.
342*bb4ee6a4SAndroid Build Coastguard Worker //
343*bb4ee6a4SAndroid Build Coastguard Worker // This follows similar format to ARCVM IOCTL "FS_IOC_SETPERMISSION"
344*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_runtime_ugid_map")]
345*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default, deserialize_with = "deserialize_ugid_map")]
346*bb4ee6a4SAndroid Build Coastguard Worker pub ugid_map: Vec<PermissionData>,
347*bb4ee6a4SAndroid Build Coastguard Worker }
348*bb4ee6a4SAndroid Build Coastguard Worker
349*bb4ee6a4SAndroid Build Coastguard Worker impl Default for Config {
default() -> Self350*bb4ee6a4SAndroid Build Coastguard Worker fn default() -> Self {
351*bb4ee6a4SAndroid Build Coastguard Worker Config {
352*bb4ee6a4SAndroid Build Coastguard Worker timeout: config_default_timeout(),
353*bb4ee6a4SAndroid Build Coastguard Worker negative_timeout: config_default_negative_timeout(),
354*bb4ee6a4SAndroid Build Coastguard Worker cache_policy: Default::default(),
355*bb4ee6a4SAndroid Build Coastguard Worker writeback: false,
356*bb4ee6a4SAndroid Build Coastguard Worker rewrite_security_xattrs: false,
357*bb4ee6a4SAndroid Build Coastguard Worker ascii_casefold: false,
358*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
359*bb4ee6a4SAndroid Build Coastguard Worker privileged_quota_uids: Default::default(),
360*bb4ee6a4SAndroid Build Coastguard Worker use_dax: false,
361*bb4ee6a4SAndroid Build Coastguard Worker posix_acl: config_default_posix_acl(),
362*bb4ee6a4SAndroid Build Coastguard Worker max_dynamic_perm: 0,
363*bb4ee6a4SAndroid Build Coastguard Worker max_dynamic_xattr: 0,
364*bb4ee6a4SAndroid Build Coastguard Worker security_ctx: config_default_security_ctx(),
365*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_runtime_ugid_map")]
366*bb4ee6a4SAndroid Build Coastguard Worker ugid_map: Vec::new(),
367*bb4ee6a4SAndroid Build Coastguard Worker }
368*bb4ee6a4SAndroid Build Coastguard Worker }
369*bb4ee6a4SAndroid Build Coastguard Worker }
370*bb4ee6a4SAndroid Build Coastguard Worker
371*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(test, feature = "fs_runtime_ugid_map"))]
372*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
373*bb4ee6a4SAndroid Build Coastguard Worker
374*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
375*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_deserialize_ugid_map_valid()376*bb4ee6a4SAndroid Build Coastguard Worker fn test_deserialize_ugid_map_valid() {
377*bb4ee6a4SAndroid Build Coastguard Worker let input_string =
378*bb4ee6a4SAndroid Build Coastguard Worker "\"1000 1000 1000 1000 0022 /path/to/dir;2000 2000 2000 2000 0022 /path/to/other/dir\"";
379*bb4ee6a4SAndroid Build Coastguard Worker
380*bb4ee6a4SAndroid Build Coastguard Worker let mut deserializer = serde_json::Deserializer::from_str(input_string);
381*bb4ee6a4SAndroid Build Coastguard Worker let result = deserialize_ugid_map(&mut deserializer).unwrap();
382*bb4ee6a4SAndroid Build Coastguard Worker
383*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(result.len(), 2);
384*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
385*bb4ee6a4SAndroid Build Coastguard Worker result,
386*bb4ee6a4SAndroid Build Coastguard Worker vec![
387*bb4ee6a4SAndroid Build Coastguard Worker PermissionData {
388*bb4ee6a4SAndroid Build Coastguard Worker guest_uid: 1000,
389*bb4ee6a4SAndroid Build Coastguard Worker guest_gid: 1000,
390*bb4ee6a4SAndroid Build Coastguard Worker host_uid: 1000,
391*bb4ee6a4SAndroid Build Coastguard Worker host_gid: 1000,
392*bb4ee6a4SAndroid Build Coastguard Worker umask: 22,
393*bb4ee6a4SAndroid Build Coastguard Worker perm_path: "/path/to/dir".to_string(),
394*bb4ee6a4SAndroid Build Coastguard Worker },
395*bb4ee6a4SAndroid Build Coastguard Worker PermissionData {
396*bb4ee6a4SAndroid Build Coastguard Worker guest_uid: 2000,
397*bb4ee6a4SAndroid Build Coastguard Worker guest_gid: 2000,
398*bb4ee6a4SAndroid Build Coastguard Worker host_uid: 2000,
399*bb4ee6a4SAndroid Build Coastguard Worker host_gid: 2000,
400*bb4ee6a4SAndroid Build Coastguard Worker umask: 22,
401*bb4ee6a4SAndroid Build Coastguard Worker perm_path: "/path/to/other/dir".to_string(),
402*bb4ee6a4SAndroid Build Coastguard Worker },
403*bb4ee6a4SAndroid Build Coastguard Worker ]
404*bb4ee6a4SAndroid Build Coastguard Worker );
405*bb4ee6a4SAndroid Build Coastguard Worker }
406*bb4ee6a4SAndroid Build Coastguard Worker
407*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_process_ugid_map_valid()408*bb4ee6a4SAndroid Build Coastguard Worker fn test_process_ugid_map_valid() {
409*bb4ee6a4SAndroid Build Coastguard Worker let input_vec = vec![
410*bb4ee6a4SAndroid Build Coastguard Worker vec![
411*bb4ee6a4SAndroid Build Coastguard Worker "1000".to_string(),
412*bb4ee6a4SAndroid Build Coastguard Worker "1000".to_string(),
413*bb4ee6a4SAndroid Build Coastguard Worker "1000".to_string(),
414*bb4ee6a4SAndroid Build Coastguard Worker "1000".to_string(),
415*bb4ee6a4SAndroid Build Coastguard Worker "0022".to_string(),
416*bb4ee6a4SAndroid Build Coastguard Worker "/path/to/dir".to_string(),
417*bb4ee6a4SAndroid Build Coastguard Worker ],
418*bb4ee6a4SAndroid Build Coastguard Worker vec![
419*bb4ee6a4SAndroid Build Coastguard Worker "2000".to_string(),
420*bb4ee6a4SAndroid Build Coastguard Worker "2000".to_string(),
421*bb4ee6a4SAndroid Build Coastguard Worker "2000".to_string(),
422*bb4ee6a4SAndroid Build Coastguard Worker "2000".to_string(),
423*bb4ee6a4SAndroid Build Coastguard Worker "0022".to_string(),
424*bb4ee6a4SAndroid Build Coastguard Worker "/path/to/other/dir".to_string(),
425*bb4ee6a4SAndroid Build Coastguard Worker ],
426*bb4ee6a4SAndroid Build Coastguard Worker ];
427*bb4ee6a4SAndroid Build Coastguard Worker
428*bb4ee6a4SAndroid Build Coastguard Worker let result = process_ugid_map(input_vec).unwrap();
429*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(result.len(), 2);
430*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
431*bb4ee6a4SAndroid Build Coastguard Worker result,
432*bb4ee6a4SAndroid Build Coastguard Worker vec![
433*bb4ee6a4SAndroid Build Coastguard Worker PermissionData {
434*bb4ee6a4SAndroid Build Coastguard Worker guest_uid: 1000,
435*bb4ee6a4SAndroid Build Coastguard Worker guest_gid: 1000,
436*bb4ee6a4SAndroid Build Coastguard Worker host_uid: 1000,
437*bb4ee6a4SAndroid Build Coastguard Worker host_gid: 1000,
438*bb4ee6a4SAndroid Build Coastguard Worker umask: 22,
439*bb4ee6a4SAndroid Build Coastguard Worker perm_path: "/path/to/dir".to_string(),
440*bb4ee6a4SAndroid Build Coastguard Worker },
441*bb4ee6a4SAndroid Build Coastguard Worker PermissionData {
442*bb4ee6a4SAndroid Build Coastguard Worker guest_uid: 2000,
443*bb4ee6a4SAndroid Build Coastguard Worker guest_gid: 2000,
444*bb4ee6a4SAndroid Build Coastguard Worker host_uid: 2000,
445*bb4ee6a4SAndroid Build Coastguard Worker host_gid: 2000,
446*bb4ee6a4SAndroid Build Coastguard Worker umask: 22,
447*bb4ee6a4SAndroid Build Coastguard Worker perm_path: "/path/to/other/dir".to_string(),
448*bb4ee6a4SAndroid Build Coastguard Worker },
449*bb4ee6a4SAndroid Build Coastguard Worker ]
450*bb4ee6a4SAndroid Build Coastguard Worker );
451*bb4ee6a4SAndroid Build Coastguard Worker }
452*bb4ee6a4SAndroid Build Coastguard Worker
453*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_deserialize_ugid_map_invalid_format()454*bb4ee6a4SAndroid Build Coastguard Worker fn test_deserialize_ugid_map_invalid_format() {
455*bb4ee6a4SAndroid Build Coastguard Worker let input_string = "\"1000 1000 1000 0022 /path/to/dir\""; // Missing one element
456*bb4ee6a4SAndroid Build Coastguard Worker
457*bb4ee6a4SAndroid Build Coastguard Worker // Create a Deserializer from the input string
458*bb4ee6a4SAndroid Build Coastguard Worker let mut deserializer = serde_json::Deserializer::from_str(input_string);
459*bb4ee6a4SAndroid Build Coastguard Worker let result = deserialize_ugid_map(&mut deserializer);
460*bb4ee6a4SAndroid Build Coastguard Worker assert!(result.is_err());
461*bb4ee6a4SAndroid Build Coastguard Worker }
462*bb4ee6a4SAndroid Build Coastguard Worker
463*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_deserialize_ugid_map_invalid_guest_uid()464*bb4ee6a4SAndroid Build Coastguard Worker fn test_deserialize_ugid_map_invalid_guest_uid() {
465*bb4ee6a4SAndroid Build Coastguard Worker let input_string = "\"invalid 1000 1000 1000 0022 /path/to/dir\""; // Invalid guest-UID
466*bb4ee6a4SAndroid Build Coastguard Worker
467*bb4ee6a4SAndroid Build Coastguard Worker // Create a Deserializer from the input string
468*bb4ee6a4SAndroid Build Coastguard Worker let mut deserializer = serde_json::Deserializer::from_str(input_string);
469*bb4ee6a4SAndroid Build Coastguard Worker let result = deserialize_ugid_map(&mut deserializer);
470*bb4ee6a4SAndroid Build Coastguard Worker assert!(result.is_err());
471*bb4ee6a4SAndroid Build Coastguard Worker }
472*bb4ee6a4SAndroid Build Coastguard Worker
473*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_deserialize_ugid_map_invalid_guest_gid()474*bb4ee6a4SAndroid Build Coastguard Worker fn test_deserialize_ugid_map_invalid_guest_gid() {
475*bb4ee6a4SAndroid Build Coastguard Worker let input_string = "\"1000 invalid 1000 1000 0022 /path/to/dir\""; // Invalid guest-GID
476*bb4ee6a4SAndroid Build Coastguard Worker
477*bb4ee6a4SAndroid Build Coastguard Worker // Create a Deserializer from the input string
478*bb4ee6a4SAndroid Build Coastguard Worker let mut deserializer = serde_json::Deserializer::from_str(input_string);
479*bb4ee6a4SAndroid Build Coastguard Worker let result = deserialize_ugid_map(&mut deserializer);
480*bb4ee6a4SAndroid Build Coastguard Worker assert!(result.is_err());
481*bb4ee6a4SAndroid Build Coastguard Worker }
482*bb4ee6a4SAndroid Build Coastguard Worker
483*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_deserialize_ugid_map_invalid_umask()484*bb4ee6a4SAndroid Build Coastguard Worker fn test_deserialize_ugid_map_invalid_umask() {
485*bb4ee6a4SAndroid Build Coastguard Worker let input_string = "\"1000 1000 1000 1000 invalid /path/to/dir\""; // Invalid umask
486*bb4ee6a4SAndroid Build Coastguard Worker
487*bb4ee6a4SAndroid Build Coastguard Worker // Create a Deserializer from the input string
488*bb4ee6a4SAndroid Build Coastguard Worker let mut deserializer = serde_json::Deserializer::from_str(input_string);
489*bb4ee6a4SAndroid Build Coastguard Worker let result = deserialize_ugid_map(&mut deserializer);
490*bb4ee6a4SAndroid Build Coastguard Worker assert!(result.is_err());
491*bb4ee6a4SAndroid Build Coastguard Worker }
492*bb4ee6a4SAndroid Build Coastguard Worker
493*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_deserialize_ugid_map_invalid_host_uid()494*bb4ee6a4SAndroid Build Coastguard Worker fn test_deserialize_ugid_map_invalid_host_uid() {
495*bb4ee6a4SAndroid Build Coastguard Worker let input_string = "\"1000 1000 invalid 1000 0022 /path/to/dir\""; // Invalid host-UID
496*bb4ee6a4SAndroid Build Coastguard Worker
497*bb4ee6a4SAndroid Build Coastguard Worker // Create a Deserializer from the input string
498*bb4ee6a4SAndroid Build Coastguard Worker let mut deserializer = serde_json::Deserializer::from_str(input_string);
499*bb4ee6a4SAndroid Build Coastguard Worker let result = deserialize_ugid_map(&mut deserializer);
500*bb4ee6a4SAndroid Build Coastguard Worker assert!(result.is_err());
501*bb4ee6a4SAndroid Build Coastguard Worker }
502*bb4ee6a4SAndroid Build Coastguard Worker
503*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_deserialize_ugid_map_invalid_host_gid()504*bb4ee6a4SAndroid Build Coastguard Worker fn test_deserialize_ugid_map_invalid_host_gid() {
505*bb4ee6a4SAndroid Build Coastguard Worker let input_string = "\"1000 1000 1000 invalid 0022 /path/to/dir\""; // Invalid host-UID
506*bb4ee6a4SAndroid Build Coastguard Worker
507*bb4ee6a4SAndroid Build Coastguard Worker // Create a Deserializer from the input string
508*bb4ee6a4SAndroid Build Coastguard Worker let mut deserializer = serde_json::Deserializer::from_str(input_string);
509*bb4ee6a4SAndroid Build Coastguard Worker let result = deserialize_ugid_map(&mut deserializer);
510*bb4ee6a4SAndroid Build Coastguard Worker assert!(result.is_err());
511*bb4ee6a4SAndroid Build Coastguard Worker }
512*bb4ee6a4SAndroid Build Coastguard Worker }
513