xref: /aosp_15_r20/external/crosvm/devices/src/virtio/fs/passthrough.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 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 use std::borrow::Cow;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::cell::RefCell;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::btree_map;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::CStr;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::CString;
12*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_runtime_ugid_map")]
13*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::OsStr;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::mem;
17*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
18*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::MaybeUninit;
19*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_int;
20*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_long;
21*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_runtime_ugid_map")]
22*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::ffi::OsStrExt;
23*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_runtime_ugid_map")]
24*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
25*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr;
26*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::addr_of;
27*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::addr_of_mut;
28*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::AtomicBool;
29*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::AtomicU64;
30*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::Ordering;
31*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
32*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::MutexGuard;
33*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_permission_translation")]
34*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::RwLock;
35*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
36*bb4ee6a4SAndroid Build Coastguard Worker 
37*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
38*bb4ee6a4SAndroid Build Coastguard Worker use base::debug;
39*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
40*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_ior_nr;
41*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_iow_nr;
42*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_iowr_nr;
43*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_mut_ptr;
44*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_ptr;
45*bb4ee6a4SAndroid Build Coastguard Worker use base::syscall;
46*bb4ee6a4SAndroid Build Coastguard Worker use base::unix::FileFlags;
47*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
48*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
49*bb4ee6a4SAndroid Build Coastguard Worker use base::FromRawDescriptor;
50*bb4ee6a4SAndroid Build Coastguard Worker use base::IoctlNr;
51*bb4ee6a4SAndroid Build Coastguard Worker use base::Protection;
52*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
53*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::Context;
54*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::DirectoryIterator;
55*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::Entry;
56*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::FileSystem;
57*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::FsOptions;
58*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::GetxattrReply;
59*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::IoctlFlags;
60*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::IoctlReply;
61*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::ListxattrReply;
62*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::OpenOptions;
63*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::RemoveMappingOne;
64*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::SetattrValid;
65*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::ZeroCopyReader;
66*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::ZeroCopyWriter;
67*bb4ee6a4SAndroid Build Coastguard Worker use fuse::filesystem::ROOT_ID;
68*bb4ee6a4SAndroid Build Coastguard Worker use fuse::sys::WRITE_KILL_PRIV;
69*bb4ee6a4SAndroid Build Coastguard Worker use fuse::Mapper;
70*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
71*bb4ee6a4SAndroid Build Coastguard Worker use protobuf::Message;
72*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
73*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
74*bb4ee6a4SAndroid Build Coastguard Worker use system_api::client::OrgChromiumSpaced;
75*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
76*bb4ee6a4SAndroid Build Coastguard Worker use system_api::spaced::SetProjectIdReply;
77*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
78*bb4ee6a4SAndroid Build Coastguard Worker use system_api::spaced::SetProjectInheritanceFlagReply;
79*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
80*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
81*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
82*bb4ee6a4SAndroid Build Coastguard Worker 
83*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
84*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::arc_ioctl::FsPathXattrDataBuffer;
85*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
86*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::arc_ioctl::FsPermissionDataBuffer;
87*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
88*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::arc_ioctl::XattrData;
89*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::caps::Capability;
90*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::caps::Caps;
91*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::caps::Set as CapSet;
92*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::caps::Value as CapValue;
93*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::config::CachePolicy;
94*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::config::Config;
95*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_permission_translation")]
96*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::config::PermissionData;
97*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::expiring_map::ExpiringMap;
98*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::multikey::MultikeyBTreeMap;
99*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::fs::read_dir::ReadDir;
100*bb4ee6a4SAndroid Build Coastguard Worker 
101*bb4ee6a4SAndroid Build Coastguard Worker const EMPTY_CSTR: &CStr = c"";
102*bb4ee6a4SAndroid Build Coastguard Worker const PROC_CSTR: &CStr = c"/proc";
103*bb4ee6a4SAndroid Build Coastguard Worker const UNLABELED_CSTR: &CStr = c"unlabeled";
104*bb4ee6a4SAndroid Build Coastguard Worker 
105*bb4ee6a4SAndroid Build Coastguard Worker const USER_VIRTIOFS_XATTR: &[u8] = b"user.virtiofs.";
106*bb4ee6a4SAndroid Build Coastguard Worker const SECURITY_XATTR: &[u8] = b"security.";
107*bb4ee6a4SAndroid Build Coastguard Worker const SELINUX_XATTR: &[u8] = b"security.selinux";
108*bb4ee6a4SAndroid Build Coastguard Worker 
109*bb4ee6a4SAndroid Build Coastguard Worker const FSCRYPT_KEY_DESCRIPTOR_SIZE: usize = 8;
110*bb4ee6a4SAndroid Build Coastguard Worker const FSCRYPT_KEY_IDENTIFIER_SIZE: usize = 16;
111*bb4ee6a4SAndroid Build Coastguard Worker 
112*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
113*bb4ee6a4SAndroid Build Coastguard Worker const FS_PROJINHERIT_FL: c_int = 0x20000000;
114*bb4ee6a4SAndroid Build Coastguard Worker 
115*bb4ee6a4SAndroid Build Coastguard Worker // 25 seconds is the default timeout for dbus-send.
116*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
117*bb4ee6a4SAndroid Build Coastguard Worker const DEFAULT_DBUS_TIMEOUT: Duration = Duration::from_secs(25);
118*bb4ee6a4SAndroid Build Coastguard Worker 
119*bb4ee6a4SAndroid Build Coastguard Worker /// Internal utility wrapper for `cros_tracing::trace_event!()` macro with VirtioFS calls.
120*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! fs_trace {
121*bb4ee6a4SAndroid Build Coastguard Worker     ($tag:expr, $name:expr, $($arg:expr),+) => {
122*bb4ee6a4SAndroid Build Coastguard Worker         cros_tracing::trace_event!(VirtioFs, $name, $tag, $($arg),*)
123*bb4ee6a4SAndroid Build Coastguard Worker     };
124*bb4ee6a4SAndroid Build Coastguard Worker }
125*bb4ee6a4SAndroid Build Coastguard Worker 
126*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
127*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, AsBytes, FromZeroes, FromBytes)]
128*bb4ee6a4SAndroid Build Coastguard Worker struct fscrypt_policy_v1 {
129*bb4ee6a4SAndroid Build Coastguard Worker     _version: u8,
130*bb4ee6a4SAndroid Build Coastguard Worker     _contents_encryption_mode: u8,
131*bb4ee6a4SAndroid Build Coastguard Worker     _filenames_encryption_mode: u8,
132*bb4ee6a4SAndroid Build Coastguard Worker     _flags: u8,
133*bb4ee6a4SAndroid Build Coastguard Worker     _master_key_descriptor: [u8; FSCRYPT_KEY_DESCRIPTOR_SIZE],
134*bb4ee6a4SAndroid Build Coastguard Worker }
135*bb4ee6a4SAndroid Build Coastguard Worker 
136*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
137*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, AsBytes, FromZeroes, FromBytes)]
138*bb4ee6a4SAndroid Build Coastguard Worker struct fscrypt_policy_v2 {
139*bb4ee6a4SAndroid Build Coastguard Worker     _version: u8,
140*bb4ee6a4SAndroid Build Coastguard Worker     _contents_encryption_mode: u8,
141*bb4ee6a4SAndroid Build Coastguard Worker     _filenames_encryption_mode: u8,
142*bb4ee6a4SAndroid Build Coastguard Worker     _flags: u8,
143*bb4ee6a4SAndroid Build Coastguard Worker     __reserved: [u8; 4],
144*bb4ee6a4SAndroid Build Coastguard Worker     master_key_identifier: [u8; FSCRYPT_KEY_IDENTIFIER_SIZE],
145*bb4ee6a4SAndroid Build Coastguard Worker }
146*bb4ee6a4SAndroid Build Coastguard Worker 
147*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
148*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, FromZeroes, FromBytes)]
149*bb4ee6a4SAndroid Build Coastguard Worker union fscrypt_policy {
150*bb4ee6a4SAndroid Build Coastguard Worker     _version: u8,
151*bb4ee6a4SAndroid Build Coastguard Worker     _v1: fscrypt_policy_v1,
152*bb4ee6a4SAndroid Build Coastguard Worker     _v2: fscrypt_policy_v2,
153*bb4ee6a4SAndroid Build Coastguard Worker }
154*bb4ee6a4SAndroid Build Coastguard Worker 
155*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
156*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, FromZeroes, FromBytes)]
157*bb4ee6a4SAndroid Build Coastguard Worker struct fscrypt_get_policy_ex_arg {
158*bb4ee6a4SAndroid Build Coastguard Worker     policy_size: u64,       /* input/output */
159*bb4ee6a4SAndroid Build Coastguard Worker     policy: fscrypt_policy, /* output */
160*bb4ee6a4SAndroid Build Coastguard Worker }
161*bb4ee6a4SAndroid Build Coastguard Worker 
162*bb4ee6a4SAndroid Build Coastguard Worker impl From<&fscrypt_get_policy_ex_arg> for &[u8] {
from(value: &fscrypt_get_policy_ex_arg) -> Self163*bb4ee6a4SAndroid Build Coastguard Worker     fn from(value: &fscrypt_get_policy_ex_arg) -> Self {
164*bb4ee6a4SAndroid Build Coastguard Worker         assert!(value.policy_size <= size_of::<fscrypt_policy>() as u64);
165*bb4ee6a4SAndroid Build Coastguard Worker         let data_raw: *const fscrypt_get_policy_ex_arg = value;
166*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: the length of the output slice is asserted to be within the struct it points to
167*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
168*bb4ee6a4SAndroid Build Coastguard Worker             std::slice::from_raw_parts(
169*bb4ee6a4SAndroid Build Coastguard Worker                 data_raw.cast(),
170*bb4ee6a4SAndroid Build Coastguard Worker                 value.policy_size as usize + size_of::<u64>(),
171*bb4ee6a4SAndroid Build Coastguard Worker             )
172*bb4ee6a4SAndroid Build Coastguard Worker         }
173*bb4ee6a4SAndroid Build Coastguard Worker     }
174*bb4ee6a4SAndroid Build Coastguard Worker }
175*bb4ee6a4SAndroid Build Coastguard Worker 
176*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iowr_nr!(FS_IOC_GET_ENCRYPTION_POLICY_EX, 'f' as u32, 22, [u8; 9]);
177*bb4ee6a4SAndroid Build Coastguard Worker 
178*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
179*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, AsBytes, FromZeroes, FromBytes)]
180*bb4ee6a4SAndroid Build Coastguard Worker struct fsxattr {
181*bb4ee6a4SAndroid Build Coastguard Worker     fsx_xflags: u32,     /* xflags field value (get/set) */
182*bb4ee6a4SAndroid Build Coastguard Worker     fsx_extsize: u32,    /* extsize field value (get/set) */
183*bb4ee6a4SAndroid Build Coastguard Worker     fsx_nextents: u32,   /* nextents field value (get) */
184*bb4ee6a4SAndroid Build Coastguard Worker     fsx_projid: u32,     /* project identifier (get/set) */
185*bb4ee6a4SAndroid Build Coastguard Worker     fsx_cowextsize: u32, /* CoW extsize field value (get/set) */
186*bb4ee6a4SAndroid Build Coastguard Worker     fsx_pad: [u8; 8],
187*bb4ee6a4SAndroid Build Coastguard Worker }
188*bb4ee6a4SAndroid Build Coastguard Worker 
189*bb4ee6a4SAndroid Build Coastguard Worker ioctl_ior_nr!(FS_IOC_FSGETXATTR, 'X' as u32, 31, fsxattr);
190*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iow_nr!(FS_IOC_FSSETXATTR, 'X' as u32, 32, fsxattr);
191*bb4ee6a4SAndroid Build Coastguard Worker 
192*bb4ee6a4SAndroid Build Coastguard Worker ioctl_ior_nr!(FS_IOC_GETFLAGS, 'f' as u32, 1, c_long);
193*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iow_nr!(FS_IOC_SETFLAGS, 'f' as u32, 2, c_long);
194*bb4ee6a4SAndroid Build Coastguard Worker 
195*bb4ee6a4SAndroid Build Coastguard Worker ioctl_ior_nr!(FS_IOC32_GETFLAGS, 'f' as u32, 1, u32);
196*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iow_nr!(FS_IOC32_SETFLAGS, 'f' as u32, 2, u32);
197*bb4ee6a4SAndroid Build Coastguard Worker 
198*bb4ee6a4SAndroid Build Coastguard Worker ioctl_ior_nr!(FS_IOC64_GETFLAGS, 'f' as u32, 1, u64);
199*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iow_nr!(FS_IOC64_SETFLAGS, 'f' as u32, 2, u64);
200*bb4ee6a4SAndroid Build Coastguard Worker 
201*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
202*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iow_nr!(FS_IOC_SETPERMISSION, 'f' as u32, 1, FsPermissionDataBuffer);
203*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
204*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iow_nr!(FS_IOC_SETPATHXATTR, 'f' as u32, 1, FsPathXattrDataBuffer);
205*bb4ee6a4SAndroid Build Coastguard Worker 
206*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
207*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, AsBytes, FromZeroes, FromBytes)]
208*bb4ee6a4SAndroid Build Coastguard Worker struct fsverity_enable_arg {
209*bb4ee6a4SAndroid Build Coastguard Worker     _version: u32,
210*bb4ee6a4SAndroid Build Coastguard Worker     _hash_algorithm: u32,
211*bb4ee6a4SAndroid Build Coastguard Worker     _block_size: u32,
212*bb4ee6a4SAndroid Build Coastguard Worker     salt_size: u32,
213*bb4ee6a4SAndroid Build Coastguard Worker     salt_ptr: u64,
214*bb4ee6a4SAndroid Build Coastguard Worker     sig_size: u32,
215*bb4ee6a4SAndroid Build Coastguard Worker     __reserved1: u32,
216*bb4ee6a4SAndroid Build Coastguard Worker     sig_ptr: u64,
217*bb4ee6a4SAndroid Build Coastguard Worker     __reserved2: [u64; 11],
218*bb4ee6a4SAndroid Build Coastguard Worker }
219*bb4ee6a4SAndroid Build Coastguard Worker 
220*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
221*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, AsBytes, FromZeroes, FromBytes)]
222*bb4ee6a4SAndroid Build Coastguard Worker struct fsverity_digest {
223*bb4ee6a4SAndroid Build Coastguard Worker     _digest_algorithm: u16,
224*bb4ee6a4SAndroid Build Coastguard Worker     digest_size: u16,
225*bb4ee6a4SAndroid Build Coastguard Worker     // __u8 digest[];
226*bb4ee6a4SAndroid Build Coastguard Worker }
227*bb4ee6a4SAndroid Build Coastguard Worker 
228*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iow_nr!(FS_IOC_ENABLE_VERITY, 'f' as u32, 133, fsverity_enable_arg);
229*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iowr_nr!(FS_IOC_MEASURE_VERITY, 'f' as u32, 134, fsverity_digest);
230*bb4ee6a4SAndroid Build Coastguard Worker 
231*bb4ee6a4SAndroid Build Coastguard Worker pub type Inode = u64;
232*bb4ee6a4SAndroid Build Coastguard Worker type Handle = u64;
233*bb4ee6a4SAndroid Build Coastguard Worker 
234*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
235*bb4ee6a4SAndroid Build Coastguard Worker struct InodeAltKey {
236*bb4ee6a4SAndroid Build Coastguard Worker     ino: libc::ino64_t,
237*bb4ee6a4SAndroid Build Coastguard Worker     dev: libc::dev_t,
238*bb4ee6a4SAndroid Build Coastguard Worker }
239*bb4ee6a4SAndroid Build Coastguard Worker 
240*bb4ee6a4SAndroid Build Coastguard Worker #[derive(PartialEq, Eq, Debug)]
241*bb4ee6a4SAndroid Build Coastguard Worker enum FileType {
242*bb4ee6a4SAndroid Build Coastguard Worker     Regular,
243*bb4ee6a4SAndroid Build Coastguard Worker     Directory,
244*bb4ee6a4SAndroid Build Coastguard Worker     Other,
245*bb4ee6a4SAndroid Build Coastguard Worker }
246*bb4ee6a4SAndroid Build Coastguard Worker 
247*bb4ee6a4SAndroid Build Coastguard Worker impl From<libc::mode_t> for FileType {
from(mode: libc::mode_t) -> Self248*bb4ee6a4SAndroid Build Coastguard Worker     fn from(mode: libc::mode_t) -> Self {
249*bb4ee6a4SAndroid Build Coastguard Worker         match mode & libc::S_IFMT {
250*bb4ee6a4SAndroid Build Coastguard Worker             libc::S_IFREG => FileType::Regular,
251*bb4ee6a4SAndroid Build Coastguard Worker             libc::S_IFDIR => FileType::Directory,
252*bb4ee6a4SAndroid Build Coastguard Worker             _ => FileType::Other,
253*bb4ee6a4SAndroid Build Coastguard Worker         }
254*bb4ee6a4SAndroid Build Coastguard Worker     }
255*bb4ee6a4SAndroid Build Coastguard Worker }
256*bb4ee6a4SAndroid Build Coastguard Worker 
257*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
258*bb4ee6a4SAndroid Build Coastguard Worker struct InodeData {
259*bb4ee6a4SAndroid Build Coastguard Worker     inode: Inode,
260*bb4ee6a4SAndroid Build Coastguard Worker     // (File, open_flags)
261*bb4ee6a4SAndroid Build Coastguard Worker     file: Mutex<(File, libc::c_int)>,
262*bb4ee6a4SAndroid Build Coastguard Worker     refcount: AtomicU64,
263*bb4ee6a4SAndroid Build Coastguard Worker     filetype: FileType,
264*bb4ee6a4SAndroid Build Coastguard Worker     path: String,
265*bb4ee6a4SAndroid Build Coastguard Worker }
266*bb4ee6a4SAndroid Build Coastguard Worker 
267*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for InodeData {
as_raw_descriptor(&self) -> RawDescriptor268*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
269*bb4ee6a4SAndroid Build Coastguard Worker         self.file.lock().0.as_raw_descriptor()
270*bb4ee6a4SAndroid Build Coastguard Worker     }
271*bb4ee6a4SAndroid Build Coastguard Worker }
272*bb4ee6a4SAndroid Build Coastguard Worker 
273*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
274*bb4ee6a4SAndroid Build Coastguard Worker struct HandleData {
275*bb4ee6a4SAndroid Build Coastguard Worker     inode: Inode,
276*bb4ee6a4SAndroid Build Coastguard Worker     file: Mutex<File>,
277*bb4ee6a4SAndroid Build Coastguard Worker }
278*bb4ee6a4SAndroid Build Coastguard Worker 
279*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for HandleData {
as_raw_descriptor(&self) -> RawDescriptor280*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
281*bb4ee6a4SAndroid Build Coastguard Worker         self.file.lock().as_raw_descriptor()
282*bb4ee6a4SAndroid Build Coastguard Worker     }
283*bb4ee6a4SAndroid Build Coastguard Worker }
284*bb4ee6a4SAndroid Build Coastguard Worker 
285*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! scoped_cred {
286*bb4ee6a4SAndroid Build Coastguard Worker     ($name:ident, $ty:ty, $syscall_nr:expr) => {
287*bb4ee6a4SAndroid Build Coastguard Worker         #[derive(Debug)]
288*bb4ee6a4SAndroid Build Coastguard Worker         struct $name {
289*bb4ee6a4SAndroid Build Coastguard Worker             old: $ty,
290*bb4ee6a4SAndroid Build Coastguard Worker         }
291*bb4ee6a4SAndroid Build Coastguard Worker 
292*bb4ee6a4SAndroid Build Coastguard Worker         impl $name {
293*bb4ee6a4SAndroid Build Coastguard Worker             // Changes the effective uid/gid of the current thread to `val`. Changes the thread's
294*bb4ee6a4SAndroid Build Coastguard Worker             // credentials back to `old` when the returned struct is dropped.
295*bb4ee6a4SAndroid Build Coastguard Worker             fn new(val: $ty, old: $ty) -> io::Result<Option<$name>> {
296*bb4ee6a4SAndroid Build Coastguard Worker                 if val == old {
297*bb4ee6a4SAndroid Build Coastguard Worker                     // Nothing to do since we already have the correct value.
298*bb4ee6a4SAndroid Build Coastguard Worker                     return Ok(None);
299*bb4ee6a4SAndroid Build Coastguard Worker                 }
300*bb4ee6a4SAndroid Build Coastguard Worker 
301*bb4ee6a4SAndroid Build Coastguard Worker                 // We want credential changes to be per-thread because otherwise
302*bb4ee6a4SAndroid Build Coastguard Worker                 // we might interfere with operations being carried out on other
303*bb4ee6a4SAndroid Build Coastguard Worker                 // threads with different uids/gids.  However, posix requires that
304*bb4ee6a4SAndroid Build Coastguard Worker                 // all threads in a process share the same credentials.  To do this
305*bb4ee6a4SAndroid Build Coastguard Worker                 // libc uses signals to ensure that when one thread changes its
306*bb4ee6a4SAndroid Build Coastguard Worker                 // credentials the other threads do the same thing.
307*bb4ee6a4SAndroid Build Coastguard Worker                 //
308*bb4ee6a4SAndroid Build Coastguard Worker                 // So instead we invoke the syscall directly in order to get around
309*bb4ee6a4SAndroid Build Coastguard Worker                 // this limitation.  Another option is to use the setfsuid and
310*bb4ee6a4SAndroid Build Coastguard Worker                 // setfsgid systems calls.   However since those calls have no way to
311*bb4ee6a4SAndroid Build Coastguard Worker                 // return an error, it's preferable to do this instead.
312*bb4ee6a4SAndroid Build Coastguard Worker 
313*bb4ee6a4SAndroid Build Coastguard Worker                 // SAFETY: this call is safe because it doesn't modify any memory and we
314*bb4ee6a4SAndroid Build Coastguard Worker                 // check the return value.
315*bb4ee6a4SAndroid Build Coastguard Worker                 let res = unsafe { libc::syscall($syscall_nr, -1, val, -1) };
316*bb4ee6a4SAndroid Build Coastguard Worker                 if res == 0 {
317*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(Some($name { old }))
318*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
319*bb4ee6a4SAndroid Build Coastguard Worker                     Err(io::Error::last_os_error())
320*bb4ee6a4SAndroid Build Coastguard Worker                 }
321*bb4ee6a4SAndroid Build Coastguard Worker             }
322*bb4ee6a4SAndroid Build Coastguard Worker         }
323*bb4ee6a4SAndroid Build Coastguard Worker 
324*bb4ee6a4SAndroid Build Coastguard Worker         impl Drop for $name {
325*bb4ee6a4SAndroid Build Coastguard Worker             fn drop(&mut self) {
326*bb4ee6a4SAndroid Build Coastguard Worker                 // SAFETY: trivially safe
327*bb4ee6a4SAndroid Build Coastguard Worker                 let res = unsafe { libc::syscall($syscall_nr, -1, self.old, -1) };
328*bb4ee6a4SAndroid Build Coastguard Worker                 if res < 0 {
329*bb4ee6a4SAndroid Build Coastguard Worker                     error!(
330*bb4ee6a4SAndroid Build Coastguard Worker                         "failed to change credentials back to {}: {}",
331*bb4ee6a4SAndroid Build Coastguard Worker                         self.old,
332*bb4ee6a4SAndroid Build Coastguard Worker                         io::Error::last_os_error(),
333*bb4ee6a4SAndroid Build Coastguard Worker                     );
334*bb4ee6a4SAndroid Build Coastguard Worker                 }
335*bb4ee6a4SAndroid Build Coastguard Worker             }
336*bb4ee6a4SAndroid Build Coastguard Worker         }
337*bb4ee6a4SAndroid Build Coastguard Worker     };
338*bb4ee6a4SAndroid Build Coastguard Worker }
339*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(target_arch = "arm"))]
340*bb4ee6a4SAndroid Build Coastguard Worker scoped_cred!(ScopedUid, libc::uid_t, libc::SYS_setresuid);
341*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "arm")]
342*bb4ee6a4SAndroid Build Coastguard Worker scoped_cred!(ScopedUid, libc::uid_t, libc::SYS_setresuid32);
343*bb4ee6a4SAndroid Build Coastguard Worker 
344*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(target_arch = "arm"))]
345*bb4ee6a4SAndroid Build Coastguard Worker scoped_cred!(ScopedGid, libc::gid_t, libc::SYS_setresgid);
346*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "arm")]
347*bb4ee6a4SAndroid Build Coastguard Worker scoped_cred!(ScopedGid, libc::gid_t, libc::SYS_setresgid32);
348*bb4ee6a4SAndroid Build Coastguard Worker 
349*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(target_arch = "arm"))]
350*bb4ee6a4SAndroid Build Coastguard Worker const SYS_GETEUID: libc::c_long = libc::SYS_geteuid;
351*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "arm")]
352*bb4ee6a4SAndroid Build Coastguard Worker const SYS_GETEUID: libc::c_long = libc::SYS_geteuid32;
353*bb4ee6a4SAndroid Build Coastguard Worker 
354*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(target_arch = "arm"))]
355*bb4ee6a4SAndroid Build Coastguard Worker const SYS_GETEGID: libc::c_long = libc::SYS_getegid;
356*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "arm")]
357*bb4ee6a4SAndroid Build Coastguard Worker const SYS_GETEGID: libc::c_long = libc::SYS_getegid32;
358*bb4ee6a4SAndroid Build Coastguard Worker 
359*bb4ee6a4SAndroid Build Coastguard Worker thread_local! {
360*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: both calls take no parameters and only return an integer value. The kernel also
361*bb4ee6a4SAndroid Build Coastguard Worker     // guarantees that they can never fail.
362*bb4ee6a4SAndroid Build Coastguard Worker     static THREAD_EUID: libc::uid_t = unsafe { libc::syscall(SYS_GETEUID) as libc::uid_t };
363*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: both calls take no parameters and only return an integer value. The kernel also
364*bb4ee6a4SAndroid Build Coastguard Worker     // guarantees that they can never fail.
365*bb4ee6a4SAndroid Build Coastguard Worker     static THREAD_EGID: libc::gid_t = unsafe { libc::syscall(SYS_GETEGID) as libc::gid_t };
366*bb4ee6a4SAndroid Build Coastguard Worker }
367*bb4ee6a4SAndroid Build Coastguard Worker 
set_creds( uid: libc::uid_t, gid: libc::gid_t, ) -> io::Result<(Option<ScopedUid>, Option<ScopedGid>)>368*bb4ee6a4SAndroid Build Coastguard Worker fn set_creds(
369*bb4ee6a4SAndroid Build Coastguard Worker     uid: libc::uid_t,
370*bb4ee6a4SAndroid Build Coastguard Worker     gid: libc::gid_t,
371*bb4ee6a4SAndroid Build Coastguard Worker ) -> io::Result<(Option<ScopedUid>, Option<ScopedGid>)> {
372*bb4ee6a4SAndroid Build Coastguard Worker     let olduid = THREAD_EUID.with(|uid| *uid);
373*bb4ee6a4SAndroid Build Coastguard Worker     let oldgid = THREAD_EGID.with(|gid| *gid);
374*bb4ee6a4SAndroid Build Coastguard Worker 
375*bb4ee6a4SAndroid Build Coastguard Worker     // We have to change the gid before we change the uid because if we change the uid first then we
376*bb4ee6a4SAndroid Build Coastguard Worker     // lose the capability to change the gid.  However changing back can happen in any order.
377*bb4ee6a4SAndroid Build Coastguard Worker     ScopedGid::new(gid, oldgid).and_then(|gid| Ok((ScopedUid::new(uid, olduid)?, gid)))
378*bb4ee6a4SAndroid Build Coastguard Worker }
379*bb4ee6a4SAndroid Build Coastguard Worker 
380*bb4ee6a4SAndroid Build Coastguard Worker thread_local!(static THREAD_FSCREATE: RefCell<Option<File>> = const { RefCell::new(None) });
381*bb4ee6a4SAndroid Build Coastguard Worker 
382*bb4ee6a4SAndroid Build Coastguard Worker // Opens and returns a write-only handle to /proc/thread-self/attr/fscreate. Panics if it fails to
383*bb4ee6a4SAndroid Build Coastguard Worker // open the file.
open_fscreate(proc: &File) -> File384*bb4ee6a4SAndroid Build Coastguard Worker fn open_fscreate(proc: &File) -> File {
385*bb4ee6a4SAndroid Build Coastguard Worker     let fscreate = c"thread-self/attr/fscreate";
386*bb4ee6a4SAndroid Build Coastguard Worker 
387*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: this doesn't modify any memory and we check the return value.
388*bb4ee6a4SAndroid Build Coastguard Worker     let raw_descriptor = unsafe {
389*bb4ee6a4SAndroid Build Coastguard Worker         libc::openat(
390*bb4ee6a4SAndroid Build Coastguard Worker             proc.as_raw_descriptor(),
391*bb4ee6a4SAndroid Build Coastguard Worker             fscreate.as_ptr(),
392*bb4ee6a4SAndroid Build Coastguard Worker             libc::O_CLOEXEC | libc::O_WRONLY,
393*bb4ee6a4SAndroid Build Coastguard Worker         )
394*bb4ee6a4SAndroid Build Coastguard Worker     };
395*bb4ee6a4SAndroid Build Coastguard Worker 
396*bb4ee6a4SAndroid Build Coastguard Worker     // We don't expect this to fail and we're not in a position to return an error here so just
397*bb4ee6a4SAndroid Build Coastguard Worker     // panic.
398*bb4ee6a4SAndroid Build Coastguard Worker     if raw_descriptor < 0 {
399*bb4ee6a4SAndroid Build Coastguard Worker         panic!(
400*bb4ee6a4SAndroid Build Coastguard Worker             "Failed to open /proc/thread-self/attr/fscreate: {}",
401*bb4ee6a4SAndroid Build Coastguard Worker             io::Error::last_os_error()
402*bb4ee6a4SAndroid Build Coastguard Worker         );
403*bb4ee6a4SAndroid Build Coastguard Worker     }
404*bb4ee6a4SAndroid Build Coastguard Worker 
405*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: safe because we just opened this descriptor.
406*bb4ee6a4SAndroid Build Coastguard Worker     unsafe { File::from_raw_descriptor(raw_descriptor) }
407*bb4ee6a4SAndroid Build Coastguard Worker }
408*bb4ee6a4SAndroid Build Coastguard Worker 
409*bb4ee6a4SAndroid Build Coastguard Worker struct ScopedSecurityContext;
410*bb4ee6a4SAndroid Build Coastguard Worker 
411*bb4ee6a4SAndroid Build Coastguard Worker impl ScopedSecurityContext {
new(proc: &File, ctx: &CStr) -> io::Result<ScopedSecurityContext>412*bb4ee6a4SAndroid Build Coastguard Worker     fn new(proc: &File, ctx: &CStr) -> io::Result<ScopedSecurityContext> {
413*bb4ee6a4SAndroid Build Coastguard Worker         THREAD_FSCREATE.with(|thread_fscreate| {
414*bb4ee6a4SAndroid Build Coastguard Worker             let mut fscreate = thread_fscreate.borrow_mut();
415*bb4ee6a4SAndroid Build Coastguard Worker             let file = fscreate.get_or_insert_with(|| open_fscreate(proc));
416*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
417*bb4ee6a4SAndroid Build Coastguard Worker             let ret = unsafe {
418*bb4ee6a4SAndroid Build Coastguard Worker                 libc::write(
419*bb4ee6a4SAndroid Build Coastguard Worker                     file.as_raw_descriptor(),
420*bb4ee6a4SAndroid Build Coastguard Worker                     ctx.as_ptr() as *const libc::c_void,
421*bb4ee6a4SAndroid Build Coastguard Worker                     ctx.to_bytes_with_nul().len(),
422*bb4ee6a4SAndroid Build Coastguard Worker                 )
423*bb4ee6a4SAndroid Build Coastguard Worker             };
424*bb4ee6a4SAndroid Build Coastguard Worker             if ret < 0 {
425*bb4ee6a4SAndroid Build Coastguard Worker                 Err(io::Error::last_os_error())
426*bb4ee6a4SAndroid Build Coastguard Worker             } else {
427*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(ScopedSecurityContext)
428*bb4ee6a4SAndroid Build Coastguard Worker             }
429*bb4ee6a4SAndroid Build Coastguard Worker         })
430*bb4ee6a4SAndroid Build Coastguard Worker     }
431*bb4ee6a4SAndroid Build Coastguard Worker }
432*bb4ee6a4SAndroid Build Coastguard Worker 
433*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for ScopedSecurityContext {
drop(&mut self)434*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
435*bb4ee6a4SAndroid Build Coastguard Worker         THREAD_FSCREATE.with(|thread_fscreate| {
436*bb4ee6a4SAndroid Build Coastguard Worker             // expect is safe here because the thread local would have been initialized by the call
437*bb4ee6a4SAndroid Build Coastguard Worker             // to `new` above.
438*bb4ee6a4SAndroid Build Coastguard Worker             let fscreate = thread_fscreate.borrow();
439*bb4ee6a4SAndroid Build Coastguard Worker             let file = fscreate
440*bb4ee6a4SAndroid Build Coastguard Worker                 .as_ref()
441*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("Uninitialized thread-local when dropping ScopedSecurityContext");
442*bb4ee6a4SAndroid Build Coastguard Worker 
443*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
444*bb4ee6a4SAndroid Build Coastguard Worker             let ret = unsafe { libc::write(file.as_raw_descriptor(), ptr::null(), 0) };
445*bb4ee6a4SAndroid Build Coastguard Worker 
446*bb4ee6a4SAndroid Build Coastguard Worker             if ret < 0 {
447*bb4ee6a4SAndroid Build Coastguard Worker                 warn!(
448*bb4ee6a4SAndroid Build Coastguard Worker                     "Failed to restore security context: {}",
449*bb4ee6a4SAndroid Build Coastguard Worker                     io::Error::last_os_error()
450*bb4ee6a4SAndroid Build Coastguard Worker                 );
451*bb4ee6a4SAndroid Build Coastguard Worker             }
452*bb4ee6a4SAndroid Build Coastguard Worker         })
453*bb4ee6a4SAndroid Build Coastguard Worker     }
454*bb4ee6a4SAndroid Build Coastguard Worker }
455*bb4ee6a4SAndroid Build Coastguard Worker 
456*bb4ee6a4SAndroid Build Coastguard Worker struct ScopedUmask {
457*bb4ee6a4SAndroid Build Coastguard Worker     old: libc::mode_t,
458*bb4ee6a4SAndroid Build Coastguard Worker     mask: libc::mode_t,
459*bb4ee6a4SAndroid Build Coastguard Worker }
460*bb4ee6a4SAndroid Build Coastguard Worker 
461*bb4ee6a4SAndroid Build Coastguard Worker impl ScopedUmask {
new(mask: libc::mode_t) -> ScopedUmask462*bb4ee6a4SAndroid Build Coastguard Worker     fn new(mask: libc::mode_t) -> ScopedUmask {
463*bb4ee6a4SAndroid Build Coastguard Worker         ScopedUmask {
464*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and always succeeds.
465*bb4ee6a4SAndroid Build Coastguard Worker             old: unsafe { libc::umask(mask) },
466*bb4ee6a4SAndroid Build Coastguard Worker             mask,
467*bb4ee6a4SAndroid Build Coastguard Worker         }
468*bb4ee6a4SAndroid Build Coastguard Worker     }
469*bb4ee6a4SAndroid Build Coastguard Worker }
470*bb4ee6a4SAndroid Build Coastguard Worker 
471*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for ScopedUmask {
drop(&mut self)472*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
473*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and always succeeds.
474*bb4ee6a4SAndroid Build Coastguard Worker         let previous = unsafe { libc::umask(self.old) };
475*bb4ee6a4SAndroid Build Coastguard Worker         debug_assert_eq!(
476*bb4ee6a4SAndroid Build Coastguard Worker             previous, self.mask,
477*bb4ee6a4SAndroid Build Coastguard Worker             "umask changed while holding ScopedUmask"
478*bb4ee6a4SAndroid Build Coastguard Worker         );
479*bb4ee6a4SAndroid Build Coastguard Worker     }
480*bb4ee6a4SAndroid Build Coastguard Worker }
481*bb4ee6a4SAndroid Build Coastguard Worker 
482*bb4ee6a4SAndroid Build Coastguard Worker struct ScopedFsetid(Caps);
483*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for ScopedFsetid {
drop(&mut self)484*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
485*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = raise_cap_fsetid(&mut self.0) {
486*bb4ee6a4SAndroid Build Coastguard Worker             error!(
487*bb4ee6a4SAndroid Build Coastguard Worker                 "Failed to restore CAP_FSETID: {}.  Some operations may be broken.",
488*bb4ee6a4SAndroid Build Coastguard Worker                 e
489*bb4ee6a4SAndroid Build Coastguard Worker             )
490*bb4ee6a4SAndroid Build Coastguard Worker         }
491*bb4ee6a4SAndroid Build Coastguard Worker     }
492*bb4ee6a4SAndroid Build Coastguard Worker }
493*bb4ee6a4SAndroid Build Coastguard Worker 
raise_cap_fsetid(c: &mut Caps) -> io::Result<()>494*bb4ee6a4SAndroid Build Coastguard Worker fn raise_cap_fsetid(c: &mut Caps) -> io::Result<()> {
495*bb4ee6a4SAndroid Build Coastguard Worker     c.update(&[Capability::Fsetid], CapSet::Effective, CapValue::Set)?;
496*bb4ee6a4SAndroid Build Coastguard Worker     c.apply()
497*bb4ee6a4SAndroid Build Coastguard Worker }
498*bb4ee6a4SAndroid Build Coastguard Worker 
499*bb4ee6a4SAndroid Build Coastguard Worker // Drops CAP_FSETID from the effective set for the current thread and returns an RAII guard that
500*bb4ee6a4SAndroid Build Coastguard Worker // adds the capability back when it is dropped.
drop_cap_fsetid() -> io::Result<ScopedFsetid>501*bb4ee6a4SAndroid Build Coastguard Worker fn drop_cap_fsetid() -> io::Result<ScopedFsetid> {
502*bb4ee6a4SAndroid Build Coastguard Worker     let mut caps = Caps::for_current_thread()?;
503*bb4ee6a4SAndroid Build Coastguard Worker     caps.update(&[Capability::Fsetid], CapSet::Effective, CapValue::Clear)?;
504*bb4ee6a4SAndroid Build Coastguard Worker     caps.apply()?;
505*bb4ee6a4SAndroid Build Coastguard Worker     Ok(ScopedFsetid(caps))
506*bb4ee6a4SAndroid Build Coastguard Worker }
507*bb4ee6a4SAndroid Build Coastguard Worker 
ebadf() -> io::Error508*bb4ee6a4SAndroid Build Coastguard Worker fn ebadf() -> io::Error {
509*bb4ee6a4SAndroid Build Coastguard Worker     io::Error::from_raw_os_error(libc::EBADF)
510*bb4ee6a4SAndroid Build Coastguard Worker }
511*bb4ee6a4SAndroid Build Coastguard Worker 
eexist() -> io::Error512*bb4ee6a4SAndroid Build Coastguard Worker fn eexist() -> io::Error {
513*bb4ee6a4SAndroid Build Coastguard Worker     io::Error::from_raw_os_error(libc::EEXIST)
514*bb4ee6a4SAndroid Build Coastguard Worker }
515*bb4ee6a4SAndroid Build Coastguard Worker 
stat<F: AsRawDescriptor + ?Sized>(f: &F) -> io::Result<libc::stat64>516*bb4ee6a4SAndroid Build Coastguard Worker fn stat<F: AsRawDescriptor + ?Sized>(f: &F) -> io::Result<libc::stat64> {
517*bb4ee6a4SAndroid Build Coastguard Worker     let mut st: MaybeUninit<libc::stat64> = MaybeUninit::<libc::stat64>::zeroed();
518*bb4ee6a4SAndroid Build Coastguard Worker 
519*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: the kernel will only write data in `st` and we check the return value.
520*bb4ee6a4SAndroid Build Coastguard Worker     syscall!(unsafe {
521*bb4ee6a4SAndroid Build Coastguard Worker         libc::fstatat64(
522*bb4ee6a4SAndroid Build Coastguard Worker             f.as_raw_descriptor(),
523*bb4ee6a4SAndroid Build Coastguard Worker             EMPTY_CSTR.as_ptr(),
524*bb4ee6a4SAndroid Build Coastguard Worker             st.as_mut_ptr(),
525*bb4ee6a4SAndroid Build Coastguard Worker             libc::AT_EMPTY_PATH | libc::AT_SYMLINK_NOFOLLOW,
526*bb4ee6a4SAndroid Build Coastguard Worker         )
527*bb4ee6a4SAndroid Build Coastguard Worker     })?;
528*bb4ee6a4SAndroid Build Coastguard Worker 
529*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: the kernel guarantees that the struct is now fully initialized.
530*bb4ee6a4SAndroid Build Coastguard Worker     Ok(unsafe { st.assume_init() })
531*bb4ee6a4SAndroid Build Coastguard Worker }
532*bb4ee6a4SAndroid Build Coastguard Worker 
statat<D: AsRawDescriptor>(dir: &D, name: &CStr) -> io::Result<libc::stat64>533*bb4ee6a4SAndroid Build Coastguard Worker fn statat<D: AsRawDescriptor>(dir: &D, name: &CStr) -> io::Result<libc::stat64> {
534*bb4ee6a4SAndroid Build Coastguard Worker     let mut st = MaybeUninit::<libc::stat64>::zeroed();
535*bb4ee6a4SAndroid Build Coastguard Worker 
536*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: the kernel will only write data in `st` and we check the return value.
537*bb4ee6a4SAndroid Build Coastguard Worker     syscall!(unsafe {
538*bb4ee6a4SAndroid Build Coastguard Worker         libc::fstatat64(
539*bb4ee6a4SAndroid Build Coastguard Worker             dir.as_raw_descriptor(),
540*bb4ee6a4SAndroid Build Coastguard Worker             name.as_ptr(),
541*bb4ee6a4SAndroid Build Coastguard Worker             st.as_mut_ptr(),
542*bb4ee6a4SAndroid Build Coastguard Worker             libc::AT_SYMLINK_NOFOLLOW,
543*bb4ee6a4SAndroid Build Coastguard Worker         )
544*bb4ee6a4SAndroid Build Coastguard Worker     })?;
545*bb4ee6a4SAndroid Build Coastguard Worker 
546*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: the kernel guarantees that the struct is now fully initialized.
547*bb4ee6a4SAndroid Build Coastguard Worker     Ok(unsafe { st.assume_init() })
548*bb4ee6a4SAndroid Build Coastguard Worker }
549*bb4ee6a4SAndroid Build Coastguard Worker 
550*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
is_android_project_id(project_id: u32) -> bool551*bb4ee6a4SAndroid Build Coastguard Worker fn is_android_project_id(project_id: u32) -> bool {
552*bb4ee6a4SAndroid Build Coastguard Worker     // The following constants defines the valid range of project ID used by
553*bb4ee6a4SAndroid Build Coastguard Worker     // Android and are taken from android_filesystem_config.h in Android
554*bb4ee6a4SAndroid Build Coastguard Worker     // codebase.
555*bb4ee6a4SAndroid Build Coastguard Worker     //
556*bb4ee6a4SAndroid Build Coastguard Worker     // Project IDs reserved for Android files on external storage. Total 100 IDs
557*bb4ee6a4SAndroid Build Coastguard Worker     // from PROJECT_ID_EXT_DEFAULT (1000) are reserved.
558*bb4ee6a4SAndroid Build Coastguard Worker     const PROJECT_ID_FOR_ANDROID_FILES: std::ops::RangeInclusive<u32> = 1000..=1099;
559*bb4ee6a4SAndroid Build Coastguard Worker     // Project IDs reserved for Android apps.
560*bb4ee6a4SAndroid Build Coastguard Worker     // The lower-limit of the range is PROJECT_ID_EXT_DATA_START.
561*bb4ee6a4SAndroid Build Coastguard Worker     // The upper-limit of the range differs before and after T. Here we use that
562*bb4ee6a4SAndroid Build Coastguard Worker     // of T (PROJECT_ID_APP_CACHE_END) as it is larger.
563*bb4ee6a4SAndroid Build Coastguard Worker     const PROJECT_ID_FOR_ANDROID_APPS: std::ops::RangeInclusive<u32> = 20000..=69999;
564*bb4ee6a4SAndroid Build Coastguard Worker 
565*bb4ee6a4SAndroid Build Coastguard Worker     PROJECT_ID_FOR_ANDROID_FILES.contains(&project_id)
566*bb4ee6a4SAndroid Build Coastguard Worker         || PROJECT_ID_FOR_ANDROID_APPS.contains(&project_id)
567*bb4ee6a4SAndroid Build Coastguard Worker }
568*bb4ee6a4SAndroid Build Coastguard Worker 
569*bb4ee6a4SAndroid Build Coastguard Worker /// Per-directory cache for `PassthroughFs::ascii_casefold_lookup()`.
570*bb4ee6a4SAndroid Build Coastguard Worker ///
571*bb4ee6a4SAndroid Build Coastguard Worker /// The key of the underlying `BTreeMap` is a lower-cased file name in the direcoty.
572*bb4ee6a4SAndroid Build Coastguard Worker /// The value is the case-sensitive file name stored in the host file system.
573*bb4ee6a4SAndroid Build Coastguard Worker /// We assume that if PassthroughFs has exclusive access to the filesystem, this cache exhaustively
574*bb4ee6a4SAndroid Build Coastguard Worker ///  covers all file names that exist within the directory.
575*bb4ee6a4SAndroid Build Coastguard Worker /// So every `PassthroughFs`'s handler that adds or removes files in the directory is expected to
576*bb4ee6a4SAndroid Build Coastguard Worker /// update this cache.
577*bb4ee6a4SAndroid Build Coastguard Worker struct CasefoldCache(BTreeMap<Vec<u8>, CString>);
578*bb4ee6a4SAndroid Build Coastguard Worker 
579*bb4ee6a4SAndroid Build Coastguard Worker impl CasefoldCache {
new(dir: &InodeData) -> io::Result<Self>580*bb4ee6a4SAndroid Build Coastguard Worker     fn new(dir: &InodeData) -> io::Result<Self> {
581*bb4ee6a4SAndroid Build Coastguard Worker         let mut mp = BTreeMap::new();
582*bb4ee6a4SAndroid Build Coastguard Worker 
583*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = [0u8; 1024];
584*bb4ee6a4SAndroid Build Coastguard Worker         let mut offset = 0;
585*bb4ee6a4SAndroid Build Coastguard Worker         loop {
586*bb4ee6a4SAndroid Build Coastguard Worker             let mut read_dir = ReadDir::new(dir, offset, &mut buf[..])?;
587*bb4ee6a4SAndroid Build Coastguard Worker             if read_dir.remaining() == 0 {
588*bb4ee6a4SAndroid Build Coastguard Worker                 break;
589*bb4ee6a4SAndroid Build Coastguard Worker             }
590*bb4ee6a4SAndroid Build Coastguard Worker 
591*bb4ee6a4SAndroid Build Coastguard Worker             while let Some(entry) = read_dir.next() {
592*bb4ee6a4SAndroid Build Coastguard Worker                 offset = entry.offset as libc::off64_t;
593*bb4ee6a4SAndroid Build Coastguard Worker                 let entry_name = entry.name;
594*bb4ee6a4SAndroid Build Coastguard Worker                 mp.insert(
595*bb4ee6a4SAndroid Build Coastguard Worker                     entry_name.to_bytes().to_ascii_lowercase(),
596*bb4ee6a4SAndroid Build Coastguard Worker                     entry_name.to_owned(),
597*bb4ee6a4SAndroid Build Coastguard Worker                 );
598*bb4ee6a4SAndroid Build Coastguard Worker             }
599*bb4ee6a4SAndroid Build Coastguard Worker         }
600*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Self(mp))
601*bb4ee6a4SAndroid Build Coastguard Worker     }
602*bb4ee6a4SAndroid Build Coastguard Worker 
insert(&mut self, name: &CStr)603*bb4ee6a4SAndroid Build Coastguard Worker     fn insert(&mut self, name: &CStr) {
604*bb4ee6a4SAndroid Build Coastguard Worker         let lower_case = name.to_bytes().to_ascii_lowercase();
605*bb4ee6a4SAndroid Build Coastguard Worker         self.0.insert(lower_case, name.into());
606*bb4ee6a4SAndroid Build Coastguard Worker     }
607*bb4ee6a4SAndroid Build Coastguard Worker 
lookup(&self, name: &[u8]) -> Option<CString>608*bb4ee6a4SAndroid Build Coastguard Worker     fn lookup(&self, name: &[u8]) -> Option<CString> {
609*bb4ee6a4SAndroid Build Coastguard Worker         let lower = name.to_ascii_lowercase();
610*bb4ee6a4SAndroid Build Coastguard Worker         self.0.get(&lower).cloned()
611*bb4ee6a4SAndroid Build Coastguard Worker     }
612*bb4ee6a4SAndroid Build Coastguard Worker 
remove(&mut self, name: &CStr)613*bb4ee6a4SAndroid Build Coastguard Worker     fn remove(&mut self, name: &CStr) {
614*bb4ee6a4SAndroid Build Coastguard Worker         let lower_case = name.to_bytes().to_ascii_lowercase();
615*bb4ee6a4SAndroid Build Coastguard Worker         self.0.remove(&lower_case);
616*bb4ee6a4SAndroid Build Coastguard Worker     }
617*bb4ee6a4SAndroid Build Coastguard Worker }
618*bb4ee6a4SAndroid Build Coastguard Worker 
619*bb4ee6a4SAndroid Build Coastguard Worker /// Time expiring mapping from an inode of a directory to `CasefoldCache` for the directory.
620*bb4ee6a4SAndroid Build Coastguard Worker /// Each entry will be expired after `timeout`.
621*bb4ee6a4SAndroid Build Coastguard Worker /// When ascii_casefold is disabled, this struct does nothing.
622*bb4ee6a4SAndroid Build Coastguard Worker struct ExpiringCasefoldLookupCaches {
623*bb4ee6a4SAndroid Build Coastguard Worker     inner: ExpiringMap<Inode, CasefoldCache>,
624*bb4ee6a4SAndroid Build Coastguard Worker }
625*bb4ee6a4SAndroid Build Coastguard Worker 
626*bb4ee6a4SAndroid Build Coastguard Worker impl ExpiringCasefoldLookupCaches {
new(timeout: Duration) -> Self627*bb4ee6a4SAndroid Build Coastguard Worker     fn new(timeout: Duration) -> Self {
628*bb4ee6a4SAndroid Build Coastguard Worker         Self {
629*bb4ee6a4SAndroid Build Coastguard Worker             inner: ExpiringMap::new(timeout),
630*bb4ee6a4SAndroid Build Coastguard Worker         }
631*bb4ee6a4SAndroid Build Coastguard Worker     }
632*bb4ee6a4SAndroid Build Coastguard Worker 
insert(&mut self, parent: Inode, name: &CStr)633*bb4ee6a4SAndroid Build Coastguard Worker     fn insert(&mut self, parent: Inode, name: &CStr) {
634*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(dir_cache) = self.inner.get_mut(&parent) {
635*bb4ee6a4SAndroid Build Coastguard Worker             dir_cache.insert(name);
636*bb4ee6a4SAndroid Build Coastguard Worker         }
637*bb4ee6a4SAndroid Build Coastguard Worker     }
638*bb4ee6a4SAndroid Build Coastguard Worker 
remove(&mut self, parent: Inode, name: &CStr)639*bb4ee6a4SAndroid Build Coastguard Worker     fn remove(&mut self, parent: Inode, name: &CStr) {
640*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(dir_cache) = self.inner.get_mut(&parent) {
641*bb4ee6a4SAndroid Build Coastguard Worker             dir_cache.remove(name);
642*bb4ee6a4SAndroid Build Coastguard Worker         }
643*bb4ee6a4SAndroid Build Coastguard Worker     }
644*bb4ee6a4SAndroid Build Coastguard Worker 
forget(&mut self, parent: Inode)645*bb4ee6a4SAndroid Build Coastguard Worker     fn forget(&mut self, parent: Inode) {
646*bb4ee6a4SAndroid Build Coastguard Worker         self.inner.remove(&parent);
647*bb4ee6a4SAndroid Build Coastguard Worker     }
648*bb4ee6a4SAndroid Build Coastguard Worker 
649*bb4ee6a4SAndroid Build Coastguard Worker     /// Get `CasefoldCache` for the given directory.
650*bb4ee6a4SAndroid Build Coastguard Worker     /// If the cache doesn't exist, generate it by fetching directory information with
651*bb4ee6a4SAndroid Build Coastguard Worker     /// `getdents64()`.
get(&mut self, parent: &InodeData) -> io::Result<&CasefoldCache>652*bb4ee6a4SAndroid Build Coastguard Worker     fn get(&mut self, parent: &InodeData) -> io::Result<&CasefoldCache> {
653*bb4ee6a4SAndroid Build Coastguard Worker         self.inner
654*bb4ee6a4SAndroid Build Coastguard Worker             .get_or_insert_with(&parent.inode, || CasefoldCache::new(parent))
655*bb4ee6a4SAndroid Build Coastguard Worker     }
656*bb4ee6a4SAndroid Build Coastguard Worker 
657*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(test)]
exists_in_cache(&mut self, parent: Inode, name: &CStr) -> bool658*bb4ee6a4SAndroid Build Coastguard Worker     fn exists_in_cache(&mut self, parent: Inode, name: &CStr) -> bool {
659*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(dir_cache) = self.inner.get(&parent) {
660*bb4ee6a4SAndroid Build Coastguard Worker             dir_cache.lookup(name.to_bytes()).is_some()
661*bb4ee6a4SAndroid Build Coastguard Worker         } else {
662*bb4ee6a4SAndroid Build Coastguard Worker             false
663*bb4ee6a4SAndroid Build Coastguard Worker         }
664*bb4ee6a4SAndroid Build Coastguard Worker     }
665*bb4ee6a4SAndroid Build Coastguard Worker }
666*bb4ee6a4SAndroid Build Coastguard Worker 
667*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_permission_translation")]
668*bb4ee6a4SAndroid Build Coastguard Worker impl PermissionData {
need_set_permission(&self, path: &str) -> bool669*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) fn need_set_permission(&self, path: &str) -> bool {
670*bb4ee6a4SAndroid Build Coastguard Worker         path.starts_with(&self.perm_path)
671*bb4ee6a4SAndroid Build Coastguard Worker     }
672*bb4ee6a4SAndroid Build Coastguard Worker }
673*bb4ee6a4SAndroid Build Coastguard Worker 
674*bb4ee6a4SAndroid Build Coastguard Worker /// A file system that simply "passes through" all requests it receives to the underlying file
675*bb4ee6a4SAndroid Build Coastguard Worker /// system. To keep the implementation simple it servers the contents of its root directory. Users
676*bb4ee6a4SAndroid Build Coastguard Worker /// that wish to serve only a specific directory should set up the environment so that that
677*bb4ee6a4SAndroid Build Coastguard Worker /// directory ends up as the root of the file system process. One way to accomplish this is via a
678*bb4ee6a4SAndroid Build Coastguard Worker /// combination of mount namespaces and the pivot_root system call.
679*bb4ee6a4SAndroid Build Coastguard Worker pub struct PassthroughFs {
680*bb4ee6a4SAndroid Build Coastguard Worker     // Mutex that must be acquired before executing a process-wide operation such as fchdir.
681*bb4ee6a4SAndroid Build Coastguard Worker     process_lock: Mutex<()>,
682*bb4ee6a4SAndroid Build Coastguard Worker     // virtio-fs tag that the guest uses when mounting. This is only used for debugging
683*bb4ee6a4SAndroid Build Coastguard Worker     // when tracing is enabled.
684*bb4ee6a4SAndroid Build Coastguard Worker     tag: String,
685*bb4ee6a4SAndroid Build Coastguard Worker 
686*bb4ee6a4SAndroid Build Coastguard Worker     // File descriptors for various points in the file system tree.
687*bb4ee6a4SAndroid Build Coastguard Worker     inodes: Mutex<MultikeyBTreeMap<Inode, InodeAltKey, Arc<InodeData>>>,
688*bb4ee6a4SAndroid Build Coastguard Worker     next_inode: AtomicU64,
689*bb4ee6a4SAndroid Build Coastguard Worker 
690*bb4ee6a4SAndroid Build Coastguard Worker     // File descriptors for open files and directories. Unlike the fds in `inodes`, these _can_ be
691*bb4ee6a4SAndroid Build Coastguard Worker     // used for reading and writing data.
692*bb4ee6a4SAndroid Build Coastguard Worker     handles: Mutex<BTreeMap<Handle, Arc<HandleData>>>,
693*bb4ee6a4SAndroid Build Coastguard Worker     next_handle: AtomicU64,
694*bb4ee6a4SAndroid Build Coastguard Worker 
695*bb4ee6a4SAndroid Build Coastguard Worker     // File descriptor pointing to the `/proc` directory. This is used to convert an fd from
696*bb4ee6a4SAndroid Build Coastguard Worker     // `inodes` into one that can go into `handles`. This is accomplished by reading the
697*bb4ee6a4SAndroid Build Coastguard Worker     // `self/fd/{}` symlink. We keep an open fd here in case the file system tree that we are meant
698*bb4ee6a4SAndroid Build Coastguard Worker     // to be serving doesn't have access to `/proc`.
699*bb4ee6a4SAndroid Build Coastguard Worker     proc: File,
700*bb4ee6a4SAndroid Build Coastguard Worker 
701*bb4ee6a4SAndroid Build Coastguard Worker     // Whether writeback caching is enabled for this directory. This will only be true when
702*bb4ee6a4SAndroid Build Coastguard Worker     // `cfg.writeback` is true and `init` was called with `FsOptions::WRITEBACK_CACHE`.
703*bb4ee6a4SAndroid Build Coastguard Worker     writeback: AtomicBool,
704*bb4ee6a4SAndroid Build Coastguard Worker 
705*bb4ee6a4SAndroid Build Coastguard Worker     // Whether zero message opens are supported by the kernel driver.
706*bb4ee6a4SAndroid Build Coastguard Worker     zero_message_open: AtomicBool,
707*bb4ee6a4SAndroid Build Coastguard Worker 
708*bb4ee6a4SAndroid Build Coastguard Worker     // Whether zero message opendir is supported by the kernel driver.
709*bb4ee6a4SAndroid Build Coastguard Worker     zero_message_opendir: AtomicBool,
710*bb4ee6a4SAndroid Build Coastguard Worker 
711*bb4ee6a4SAndroid Build Coastguard Worker     // Used to communicate with other processes using D-Bus.
712*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
713*bb4ee6a4SAndroid Build Coastguard Worker     dbus_connection: Option<Mutex<dbus::blocking::Connection>>,
714*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
715*bb4ee6a4SAndroid Build Coastguard Worker     dbus_fd: Option<std::os::unix::io::RawFd>,
716*bb4ee6a4SAndroid Build Coastguard Worker 
717*bb4ee6a4SAndroid Build Coastguard Worker     // Time-expiring cache for `ascii_casefold_lookup()`.
718*bb4ee6a4SAndroid Build Coastguard Worker     // The key is an inode of a directory, and the value is a cache for the directory.
719*bb4ee6a4SAndroid Build Coastguard Worker     // Each value will be expired `cfg.timeout` after it's created.
720*bb4ee6a4SAndroid Build Coastguard Worker     //
721*bb4ee6a4SAndroid Build Coastguard Worker     // TODO(b/267748212): Instead of per-device Mutex, we might want to have per-directory Mutex
722*bb4ee6a4SAndroid Build Coastguard Worker     // if we use PassthroughFs in multi-threaded environments.
723*bb4ee6a4SAndroid Build Coastguard Worker     expiring_casefold_lookup_caches: Option<Mutex<ExpiringCasefoldLookupCaches>>,
724*bb4ee6a4SAndroid Build Coastguard Worker 
725*bb4ee6a4SAndroid Build Coastguard Worker     // paths and coresponding permission setting set by `crosvm_client_fs_permission_set` API
726*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "fs_permission_translation")]
727*bb4ee6a4SAndroid Build Coastguard Worker     permission_paths: RwLock<Vec<PermissionData>>,
728*bb4ee6a4SAndroid Build Coastguard Worker 
729*bb4ee6a4SAndroid Build Coastguard Worker     // paths and coresponding xattr setting set by `crosvm_client_fs_xattr_set` API
730*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
731*bb4ee6a4SAndroid Build Coastguard Worker     xattr_paths: RwLock<Vec<XattrData>>,
732*bb4ee6a4SAndroid Build Coastguard Worker 
733*bb4ee6a4SAndroid Build Coastguard Worker     cfg: Config,
734*bb4ee6a4SAndroid Build Coastguard Worker 
735*bb4ee6a4SAndroid Build Coastguard Worker     // Set the root directory when pivot root isn't enabled for jailed process.
736*bb4ee6a4SAndroid Build Coastguard Worker     //
737*bb4ee6a4SAndroid Build Coastguard Worker     // virtio-fs typically uses mount namespaces and pivot_root for file system isolation,
738*bb4ee6a4SAndroid Build Coastguard Worker     // making the jailed process's root directory "/".
739*bb4ee6a4SAndroid Build Coastguard Worker     //
740*bb4ee6a4SAndroid Build Coastguard Worker     // However, Android's security model prevents crosvm from having the necessary SYS_ADMIN
741*bb4ee6a4SAndroid Build Coastguard Worker     // capability for mount namespaces and pivot_root. This lack of isolation means that
742*bb4ee6a4SAndroid Build Coastguard Worker     // root_dir defaults to the path provided via "--shared-dir".
743*bb4ee6a4SAndroid Build Coastguard Worker     root_dir: String,
744*bb4ee6a4SAndroid Build Coastguard Worker }
745*bb4ee6a4SAndroid Build Coastguard Worker 
746*bb4ee6a4SAndroid Build Coastguard Worker impl std::fmt::Debug for PassthroughFs {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result747*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
748*bb4ee6a4SAndroid Build Coastguard Worker         f.debug_struct("PassthroughFs")
749*bb4ee6a4SAndroid Build Coastguard Worker             .field("tag", &self.tag)
750*bb4ee6a4SAndroid Build Coastguard Worker             .field("next_inode", &self.next_inode)
751*bb4ee6a4SAndroid Build Coastguard Worker             .field("next_handle", &self.next_handle)
752*bb4ee6a4SAndroid Build Coastguard Worker             .field("proc", &self.proc)
753*bb4ee6a4SAndroid Build Coastguard Worker             .field("writeback", &self.writeback)
754*bb4ee6a4SAndroid Build Coastguard Worker             .field("zero_message_open", &self.zero_message_open)
755*bb4ee6a4SAndroid Build Coastguard Worker             .field("zero_message_opendir", &self.zero_message_opendir)
756*bb4ee6a4SAndroid Build Coastguard Worker             .field("cfg", &self.cfg)
757*bb4ee6a4SAndroid Build Coastguard Worker             .finish()
758*bb4ee6a4SAndroid Build Coastguard Worker     }
759*bb4ee6a4SAndroid Build Coastguard Worker }
760*bb4ee6a4SAndroid Build Coastguard Worker 
761*bb4ee6a4SAndroid Build Coastguard Worker impl PassthroughFs {
new(tag: &str, cfg: Config) -> io::Result<PassthroughFs>762*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(tag: &str, cfg: Config) -> io::Result<PassthroughFs> {
763*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value.
764*bb4ee6a4SAndroid Build Coastguard Worker         let raw_descriptor = syscall!(unsafe {
765*bb4ee6a4SAndroid Build Coastguard Worker             libc::openat64(
766*bb4ee6a4SAndroid Build Coastguard Worker                 libc::AT_FDCWD,
767*bb4ee6a4SAndroid Build Coastguard Worker                 PROC_CSTR.as_ptr(),
768*bb4ee6a4SAndroid Build Coastguard Worker                 libc::O_PATH | libc::O_NOFOLLOW | libc::O_CLOEXEC,
769*bb4ee6a4SAndroid Build Coastguard Worker             )
770*bb4ee6a4SAndroid Build Coastguard Worker         })?;
771*bb4ee6a4SAndroid Build Coastguard Worker 
772*bb4ee6a4SAndroid Build Coastguard Worker         // Privileged UIDs can use D-Bus to perform some operations.
773*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
774*bb4ee6a4SAndroid Build Coastguard Worker         let (dbus_connection, dbus_fd) = if cfg.privileged_quota_uids.is_empty() {
775*bb4ee6a4SAndroid Build Coastguard Worker             (None, None)
776*bb4ee6a4SAndroid Build Coastguard Worker         } else {
777*bb4ee6a4SAndroid Build Coastguard Worker             let mut channel = dbus::channel::Channel::get_private(dbus::channel::BusType::System)
778*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
779*bb4ee6a4SAndroid Build Coastguard Worker             channel.set_watch_enabled(true);
780*bb4ee6a4SAndroid Build Coastguard Worker             let dbus_fd = channel.watch().fd;
781*bb4ee6a4SAndroid Build Coastguard Worker             channel.set_watch_enabled(false);
782*bb4ee6a4SAndroid Build Coastguard Worker             (
783*bb4ee6a4SAndroid Build Coastguard Worker                 Some(Mutex::new(dbus::blocking::Connection::from(channel))),
784*bb4ee6a4SAndroid Build Coastguard Worker                 Some(dbus_fd),
785*bb4ee6a4SAndroid Build Coastguard Worker             )
786*bb4ee6a4SAndroid Build Coastguard Worker         };
787*bb4ee6a4SAndroid Build Coastguard Worker 
788*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: safe because we just opened this descriptor.
789*bb4ee6a4SAndroid Build Coastguard Worker         let proc = unsafe { File::from_raw_descriptor(raw_descriptor) };
790*bb4ee6a4SAndroid Build Coastguard Worker 
791*bb4ee6a4SAndroid Build Coastguard Worker         let expiring_casefold_lookup_caches = if cfg.ascii_casefold {
792*bb4ee6a4SAndroid Build Coastguard Worker             Some(Mutex::new(ExpiringCasefoldLookupCaches::new(cfg.timeout)))
793*bb4ee6a4SAndroid Build Coastguard Worker         } else {
794*bb4ee6a4SAndroid Build Coastguard Worker             None
795*bb4ee6a4SAndroid Build Coastguard Worker         };
796*bb4ee6a4SAndroid Build Coastguard Worker 
797*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(unused_mut)]
798*bb4ee6a4SAndroid Build Coastguard Worker         let mut passthroughfs = PassthroughFs {
799*bb4ee6a4SAndroid Build Coastguard Worker             process_lock: Mutex::new(()),
800*bb4ee6a4SAndroid Build Coastguard Worker             tag: tag.to_string(),
801*bb4ee6a4SAndroid Build Coastguard Worker             inodes: Mutex::new(MultikeyBTreeMap::new()),
802*bb4ee6a4SAndroid Build Coastguard Worker             next_inode: AtomicU64::new(ROOT_ID + 1),
803*bb4ee6a4SAndroid Build Coastguard Worker 
804*bb4ee6a4SAndroid Build Coastguard Worker             handles: Mutex::new(BTreeMap::new()),
805*bb4ee6a4SAndroid Build Coastguard Worker             next_handle: AtomicU64::new(1),
806*bb4ee6a4SAndroid Build Coastguard Worker 
807*bb4ee6a4SAndroid Build Coastguard Worker             proc,
808*bb4ee6a4SAndroid Build Coastguard Worker 
809*bb4ee6a4SAndroid Build Coastguard Worker             writeback: AtomicBool::new(false),
810*bb4ee6a4SAndroid Build Coastguard Worker             zero_message_open: AtomicBool::new(false),
811*bb4ee6a4SAndroid Build Coastguard Worker             zero_message_opendir: AtomicBool::new(false),
812*bb4ee6a4SAndroid Build Coastguard Worker 
813*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "arc_quota")]
814*bb4ee6a4SAndroid Build Coastguard Worker             dbus_connection,
815*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "arc_quota")]
816*bb4ee6a4SAndroid Build Coastguard Worker             dbus_fd,
817*bb4ee6a4SAndroid Build Coastguard Worker             expiring_casefold_lookup_caches,
818*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "fs_permission_translation")]
819*bb4ee6a4SAndroid Build Coastguard Worker             permission_paths: RwLock::new(Vec::new()),
820*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "arc_quota")]
821*bb4ee6a4SAndroid Build Coastguard Worker             xattr_paths: RwLock::new(Vec::new()),
822*bb4ee6a4SAndroid Build Coastguard Worker             cfg,
823*bb4ee6a4SAndroid Build Coastguard Worker             root_dir: "/".to_string(),
824*bb4ee6a4SAndroid Build Coastguard Worker         };
825*bb4ee6a4SAndroid Build Coastguard Worker 
826*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "fs_runtime_ugid_map")]
827*bb4ee6a4SAndroid Build Coastguard Worker         passthroughfs.set_permission_path();
828*bb4ee6a4SAndroid Build Coastguard Worker 
829*bb4ee6a4SAndroid Build Coastguard Worker         cros_tracing::trace_simple_print!(
830*bb4ee6a4SAndroid Build Coastguard Worker             VirtioFs,
831*bb4ee6a4SAndroid Build Coastguard Worker             "New PassthroughFS initialized: {:?}",
832*bb4ee6a4SAndroid Build Coastguard Worker             passthroughfs
833*bb4ee6a4SAndroid Build Coastguard Worker         );
834*bb4ee6a4SAndroid Build Coastguard Worker         Ok(passthroughfs)
835*bb4ee6a4SAndroid Build Coastguard Worker     }
836*bb4ee6a4SAndroid Build Coastguard Worker 
837*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "fs_runtime_ugid_map")]
set_permission_path(&mut self)838*bb4ee6a4SAndroid Build Coastguard Worker     fn set_permission_path(&mut self) {
839*bb4ee6a4SAndroid Build Coastguard Worker         if !self.cfg.ugid_map.is_empty() {
840*bb4ee6a4SAndroid Build Coastguard Worker             let mut write_lock = self
841*bb4ee6a4SAndroid Build Coastguard Worker                 .permission_paths
842*bb4ee6a4SAndroid Build Coastguard Worker                 .write()
843*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("Failed to acquire write lock on permission_paths");
844*bb4ee6a4SAndroid Build Coastguard Worker             *write_lock = self.cfg.ugid_map.clone();
845*bb4ee6a4SAndroid Build Coastguard Worker         }
846*bb4ee6a4SAndroid Build Coastguard Worker     }
847*bb4ee6a4SAndroid Build Coastguard Worker 
848*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "fs_runtime_ugid_map")]
set_root_dir(&mut self, shared_dir: String) -> io::Result<()>849*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_root_dir(&mut self, shared_dir: String) -> io::Result<()> {
850*bb4ee6a4SAndroid Build Coastguard Worker         let canonicalized_root = match std::fs::canonicalize(shared_dir) {
851*bb4ee6a4SAndroid Build Coastguard Worker             Ok(path) => path,
852*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
853*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(io::Error::new(
854*bb4ee6a4SAndroid Build Coastguard Worker                     io::ErrorKind::InvalidInput,
855*bb4ee6a4SAndroid Build Coastguard Worker                     format!("Failed to canonicalize root_dir: {}", e),
856*bb4ee6a4SAndroid Build Coastguard Worker                 ));
857*bb4ee6a4SAndroid Build Coastguard Worker             }
858*bb4ee6a4SAndroid Build Coastguard Worker         };
859*bb4ee6a4SAndroid Build Coastguard Worker         self.root_dir = canonicalized_root.to_string_lossy().to_string();
860*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
861*bb4ee6a4SAndroid Build Coastguard Worker     }
862*bb4ee6a4SAndroid Build Coastguard Worker 
cfg(&self) -> &Config863*bb4ee6a4SAndroid Build Coastguard Worker     pub fn cfg(&self) -> &Config {
864*bb4ee6a4SAndroid Build Coastguard Worker         &self.cfg
865*bb4ee6a4SAndroid Build Coastguard Worker     }
866*bb4ee6a4SAndroid Build Coastguard Worker 
keep_rds(&self) -> Vec<RawDescriptor>867*bb4ee6a4SAndroid Build Coastguard Worker     pub fn keep_rds(&self) -> Vec<RawDescriptor> {
868*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg_attr(not(feature = "arc_quota"), allow(unused_mut))]
869*bb4ee6a4SAndroid Build Coastguard Worker         let mut keep_rds = vec![self.proc.as_raw_descriptor()];
870*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
871*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(fd) = self.dbus_fd {
872*bb4ee6a4SAndroid Build Coastguard Worker             keep_rds.push(fd);
873*bb4ee6a4SAndroid Build Coastguard Worker         }
874*bb4ee6a4SAndroid Build Coastguard Worker         keep_rds
875*bb4ee6a4SAndroid Build Coastguard Worker     }
876*bb4ee6a4SAndroid Build Coastguard Worker 
rewrite_xattr_name<'xattr>(&self, name: &'xattr CStr) -> Cow<'xattr, CStr>877*bb4ee6a4SAndroid Build Coastguard Worker     fn rewrite_xattr_name<'xattr>(&self, name: &'xattr CStr) -> Cow<'xattr, CStr> {
878*bb4ee6a4SAndroid Build Coastguard Worker         if !self.cfg.rewrite_security_xattrs {
879*bb4ee6a4SAndroid Build Coastguard Worker             return Cow::Borrowed(name);
880*bb4ee6a4SAndroid Build Coastguard Worker         }
881*bb4ee6a4SAndroid Build Coastguard Worker 
882*bb4ee6a4SAndroid Build Coastguard Worker         // Does not include nul-terminator.
883*bb4ee6a4SAndroid Build Coastguard Worker         let buf = name.to_bytes();
884*bb4ee6a4SAndroid Build Coastguard Worker         if !buf.starts_with(SECURITY_XATTR) || buf == SELINUX_XATTR {
885*bb4ee6a4SAndroid Build Coastguard Worker             return Cow::Borrowed(name);
886*bb4ee6a4SAndroid Build Coastguard Worker         }
887*bb4ee6a4SAndroid Build Coastguard Worker 
888*bb4ee6a4SAndroid Build Coastguard Worker         let mut newname = USER_VIRTIOFS_XATTR.to_vec();
889*bb4ee6a4SAndroid Build Coastguard Worker         newname.extend_from_slice(buf);
890*bb4ee6a4SAndroid Build Coastguard Worker 
891*bb4ee6a4SAndroid Build Coastguard Worker         // The unwrap is safe here because the prefix doesn't contain any interior nul-bytes and the
892*bb4ee6a4SAndroid Build Coastguard Worker         // to_bytes() call above will not return a byte slice with any interior nul-bytes either.
893*bb4ee6a4SAndroid Build Coastguard Worker         Cow::Owned(CString::new(newname).expect("Failed to re-write xattr name"))
894*bb4ee6a4SAndroid Build Coastguard Worker     }
895*bb4ee6a4SAndroid Build Coastguard Worker 
find_inode(&self, inode: Inode) -> io::Result<Arc<InodeData>>896*bb4ee6a4SAndroid Build Coastguard Worker     fn find_inode(&self, inode: Inode) -> io::Result<Arc<InodeData>> {
897*bb4ee6a4SAndroid Build Coastguard Worker         self.inodes.lock().get(&inode).cloned().ok_or_else(ebadf)
898*bb4ee6a4SAndroid Build Coastguard Worker     }
899*bb4ee6a4SAndroid Build Coastguard Worker 
find_handle(&self, handle: Handle, inode: Inode) -> io::Result<Arc<HandleData>>900*bb4ee6a4SAndroid Build Coastguard Worker     fn find_handle(&self, handle: Handle, inode: Inode) -> io::Result<Arc<HandleData>> {
901*bb4ee6a4SAndroid Build Coastguard Worker         self.handles
902*bb4ee6a4SAndroid Build Coastguard Worker             .lock()
903*bb4ee6a4SAndroid Build Coastguard Worker             .get(&handle)
904*bb4ee6a4SAndroid Build Coastguard Worker             .filter(|hd| hd.inode == inode)
905*bb4ee6a4SAndroid Build Coastguard Worker             .cloned()
906*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or_else(ebadf)
907*bb4ee6a4SAndroid Build Coastguard Worker     }
908*bb4ee6a4SAndroid Build Coastguard Worker 
open_fd(&self, fd: RawDescriptor, flags: i32) -> io::Result<File>909*bb4ee6a4SAndroid Build Coastguard Worker     fn open_fd(&self, fd: RawDescriptor, flags: i32) -> io::Result<File> {
910*bb4ee6a4SAndroid Build Coastguard Worker         let pathname = CString::new(format!("self/fd/{}", fd))
911*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
912*bb4ee6a4SAndroid Build Coastguard Worker 
913*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value. We don't really
914*bb4ee6a4SAndroid Build Coastguard Worker         // check `flags` because if the kernel can't handle poorly specified flags then we have
915*bb4ee6a4SAndroid Build Coastguard Worker         // much bigger problems. Also, clear the `O_NOFOLLOW` flag if it is set since we need
916*bb4ee6a4SAndroid Build Coastguard Worker         // to follow the `/proc/self/fd` symlink to get the file.
917*bb4ee6a4SAndroid Build Coastguard Worker         let raw_descriptor = syscall!(unsafe {
918*bb4ee6a4SAndroid Build Coastguard Worker             libc::openat64(
919*bb4ee6a4SAndroid Build Coastguard Worker                 self.proc.as_raw_descriptor(),
920*bb4ee6a4SAndroid Build Coastguard Worker                 pathname.as_ptr(),
921*bb4ee6a4SAndroid Build Coastguard Worker                 (flags | libc::O_CLOEXEC) & !(libc::O_NOFOLLOW | libc::O_DIRECT),
922*bb4ee6a4SAndroid Build Coastguard Worker             )
923*bb4ee6a4SAndroid Build Coastguard Worker         })?;
924*bb4ee6a4SAndroid Build Coastguard Worker 
925*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: safe because we just opened this descriptor.
926*bb4ee6a4SAndroid Build Coastguard Worker         Ok(unsafe { File::from_raw_descriptor(raw_descriptor) })
927*bb4ee6a4SAndroid Build Coastguard Worker     }
928*bb4ee6a4SAndroid Build Coastguard Worker 
929*bb4ee6a4SAndroid Build Coastguard Worker     /// Modifies the provided open flags based on the writeback caching configuration.
930*bb4ee6a4SAndroid Build Coastguard Worker     /// Return the updated open flags.
update_open_flags(&self, mut flags: i32) -> i32931*bb4ee6a4SAndroid Build Coastguard Worker     fn update_open_flags(&self, mut flags: i32) -> i32 {
932*bb4ee6a4SAndroid Build Coastguard Worker         // When writeback caching is enabled, the kernel may send read requests even if the
933*bb4ee6a4SAndroid Build Coastguard Worker         // userspace program opened the file write-only. So we need to ensure that we have opened
934*bb4ee6a4SAndroid Build Coastguard Worker         // the file for reading as well as writing.
935*bb4ee6a4SAndroid Build Coastguard Worker         let writeback = self.writeback.load(Ordering::Relaxed);
936*bb4ee6a4SAndroid Build Coastguard Worker         if writeback && flags & libc::O_ACCMODE == libc::O_WRONLY {
937*bb4ee6a4SAndroid Build Coastguard Worker             flags &= !libc::O_ACCMODE;
938*bb4ee6a4SAndroid Build Coastguard Worker             flags |= libc::O_RDWR;
939*bb4ee6a4SAndroid Build Coastguard Worker         }
940*bb4ee6a4SAndroid Build Coastguard Worker 
941*bb4ee6a4SAndroid Build Coastguard Worker         // When writeback caching is enabled the kernel is responsible for handling `O_APPEND`.
942*bb4ee6a4SAndroid Build Coastguard Worker         // However, this breaks atomicity as the file may have changed on disk, invalidating the
943*bb4ee6a4SAndroid Build Coastguard Worker         // cached copy of the data in the kernel and the offset that the kernel thinks is the end of
944*bb4ee6a4SAndroid Build Coastguard Worker         // the file. Just allow this for now as it is the user's responsibility to enable writeback
945*bb4ee6a4SAndroid Build Coastguard Worker         // caching only for directories that are not shared. It also means that we need to clear the
946*bb4ee6a4SAndroid Build Coastguard Worker         // `O_APPEND` flag.
947*bb4ee6a4SAndroid Build Coastguard Worker         if writeback && flags & libc::O_APPEND != 0 {
948*bb4ee6a4SAndroid Build Coastguard Worker             flags &= !libc::O_APPEND;
949*bb4ee6a4SAndroid Build Coastguard Worker         }
950*bb4ee6a4SAndroid Build Coastguard Worker 
951*bb4ee6a4SAndroid Build Coastguard Worker         flags
952*bb4ee6a4SAndroid Build Coastguard Worker     }
953*bb4ee6a4SAndroid Build Coastguard Worker 
open_inode(&self, inode: &InodeData, mut flags: i32) -> io::Result<File>954*bb4ee6a4SAndroid Build Coastguard Worker     fn open_inode(&self, inode: &InodeData, mut flags: i32) -> io::Result<File> {
955*bb4ee6a4SAndroid Build Coastguard Worker         // handle writeback caching cases
956*bb4ee6a4SAndroid Build Coastguard Worker         flags = self.update_open_flags(flags);
957*bb4ee6a4SAndroid Build Coastguard Worker 
958*bb4ee6a4SAndroid Build Coastguard Worker         self.open_fd(inode.as_raw_descriptor(), flags)
959*bb4ee6a4SAndroid Build Coastguard Worker     }
960*bb4ee6a4SAndroid Build Coastguard Worker 
961*bb4ee6a4SAndroid Build Coastguard Worker     // Increases the inode refcount and returns the inode.
increase_inode_refcount(&self, inode_data: &InodeData) -> Inode962*bb4ee6a4SAndroid Build Coastguard Worker     fn increase_inode_refcount(&self, inode_data: &InodeData) -> Inode {
963*bb4ee6a4SAndroid Build Coastguard Worker         // Matches with the release store in `forget`.
964*bb4ee6a4SAndroid Build Coastguard Worker         inode_data.refcount.fetch_add(1, Ordering::Acquire);
965*bb4ee6a4SAndroid Build Coastguard Worker         inode_data.inode
966*bb4ee6a4SAndroid Build Coastguard Worker     }
967*bb4ee6a4SAndroid Build Coastguard Worker 
968*bb4ee6a4SAndroid Build Coastguard Worker     // Creates a new entry for `f` or increases the refcount of the existing entry for `f`.
969*bb4ee6a4SAndroid Build Coastguard Worker     // The inodes mutex lock must not be already taken by the same thread otherwise this
970*bb4ee6a4SAndroid Build Coastguard Worker     // will deadlock.
add_entry( &self, f: File, #[cfg_attr(not(feature = "fs_permission_translation"), allow(unused_mut))] mut st: libc::stat64, open_flags: libc::c_int, path: String, ) -> Entry971*bb4ee6a4SAndroid Build Coastguard Worker     fn add_entry(
972*bb4ee6a4SAndroid Build Coastguard Worker         &self,
973*bb4ee6a4SAndroid Build Coastguard Worker         f: File,
974*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg_attr(not(feature = "fs_permission_translation"), allow(unused_mut))]
975*bb4ee6a4SAndroid Build Coastguard Worker         mut st: libc::stat64,
976*bb4ee6a4SAndroid Build Coastguard Worker         open_flags: libc::c_int,
977*bb4ee6a4SAndroid Build Coastguard Worker         path: String,
978*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Entry {
979*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
980*bb4ee6a4SAndroid Build Coastguard Worker         self.set_permission(&mut st, &path);
981*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "fs_runtime_ugid_map")]
982*bb4ee6a4SAndroid Build Coastguard Worker         self.set_ugid_permission(&mut st, &path);
983*bb4ee6a4SAndroid Build Coastguard Worker         let mut inodes = self.inodes.lock();
984*bb4ee6a4SAndroid Build Coastguard Worker 
985*bb4ee6a4SAndroid Build Coastguard Worker         let altkey = InodeAltKey {
986*bb4ee6a4SAndroid Build Coastguard Worker             ino: st.st_ino,
987*bb4ee6a4SAndroid Build Coastguard Worker             dev: st.st_dev,
988*bb4ee6a4SAndroid Build Coastguard Worker         };
989*bb4ee6a4SAndroid Build Coastguard Worker 
990*bb4ee6a4SAndroid Build Coastguard Worker         let inode = if let Some(data) = inodes.get_alt(&altkey) {
991*bb4ee6a4SAndroid Build Coastguard Worker             self.increase_inode_refcount(data)
992*bb4ee6a4SAndroid Build Coastguard Worker         } else {
993*bb4ee6a4SAndroid Build Coastguard Worker             let inode = self.next_inode.fetch_add(1, Ordering::Relaxed);
994*bb4ee6a4SAndroid Build Coastguard Worker             inodes.insert(
995*bb4ee6a4SAndroid Build Coastguard Worker                 inode,
996*bb4ee6a4SAndroid Build Coastguard Worker                 altkey,
997*bb4ee6a4SAndroid Build Coastguard Worker                 Arc::new(InodeData {
998*bb4ee6a4SAndroid Build Coastguard Worker                     inode,
999*bb4ee6a4SAndroid Build Coastguard Worker                     file: Mutex::new((f, open_flags)),
1000*bb4ee6a4SAndroid Build Coastguard Worker                     refcount: AtomicU64::new(1),
1001*bb4ee6a4SAndroid Build Coastguard Worker                     filetype: st.st_mode.into(),
1002*bb4ee6a4SAndroid Build Coastguard Worker                     path,
1003*bb4ee6a4SAndroid Build Coastguard Worker                 }),
1004*bb4ee6a4SAndroid Build Coastguard Worker             );
1005*bb4ee6a4SAndroid Build Coastguard Worker 
1006*bb4ee6a4SAndroid Build Coastguard Worker             inode
1007*bb4ee6a4SAndroid Build Coastguard Worker         };
1008*bb4ee6a4SAndroid Build Coastguard Worker 
1009*bb4ee6a4SAndroid Build Coastguard Worker         Entry {
1010*bb4ee6a4SAndroid Build Coastguard Worker             inode,
1011*bb4ee6a4SAndroid Build Coastguard Worker             generation: 0,
1012*bb4ee6a4SAndroid Build Coastguard Worker             attr: st,
1013*bb4ee6a4SAndroid Build Coastguard Worker             // We use the same timeout for the attribute and the entry.
1014*bb4ee6a4SAndroid Build Coastguard Worker             attr_timeout: self.cfg.timeout,
1015*bb4ee6a4SAndroid Build Coastguard Worker             entry_timeout: self.cfg.timeout,
1016*bb4ee6a4SAndroid Build Coastguard Worker         }
1017*bb4ee6a4SAndroid Build Coastguard Worker     }
1018*bb4ee6a4SAndroid Build Coastguard Worker 
1019*bb4ee6a4SAndroid Build Coastguard Worker     /// Acquires lock of `expiring_casefold_lookup_caches` if `ascii_casefold` is enabled.
lock_casefold_lookup_caches(&self) -> Option<MutexGuard<'_, ExpiringCasefoldLookupCaches>>1020*bb4ee6a4SAndroid Build Coastguard Worker     fn lock_casefold_lookup_caches(&self) -> Option<MutexGuard<'_, ExpiringCasefoldLookupCaches>> {
1021*bb4ee6a4SAndroid Build Coastguard Worker         self.expiring_casefold_lookup_caches
1022*bb4ee6a4SAndroid Build Coastguard Worker             .as_ref()
1023*bb4ee6a4SAndroid Build Coastguard Worker             .map(|c| c.lock())
1024*bb4ee6a4SAndroid Build Coastguard Worker     }
1025*bb4ee6a4SAndroid Build Coastguard Worker 
1026*bb4ee6a4SAndroid Build Coastguard Worker     // Returns an actual case-sensitive file name that matches with the given `name`.
1027*bb4ee6a4SAndroid Build Coastguard Worker     // Returns `Ok(None)` if no file matches with the give `name`.
1028*bb4ee6a4SAndroid Build Coastguard Worker     // This function will panic if casefold is not enabled.
get_case_unfolded_name( &self, parent: &InodeData, name: &[u8], ) -> io::Result<Option<CString>>1029*bb4ee6a4SAndroid Build Coastguard Worker     fn get_case_unfolded_name(
1030*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1031*bb4ee6a4SAndroid Build Coastguard Worker         parent: &InodeData,
1032*bb4ee6a4SAndroid Build Coastguard Worker         name: &[u8],
1033*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<Option<CString>> {
1034*bb4ee6a4SAndroid Build Coastguard Worker         let mut caches = self
1035*bb4ee6a4SAndroid Build Coastguard Worker             .lock_casefold_lookup_caches()
1036*bb4ee6a4SAndroid Build Coastguard Worker             .expect("casefold must be enabled");
1037*bb4ee6a4SAndroid Build Coastguard Worker         let dir_cache = caches.get(parent)?;
1038*bb4ee6a4SAndroid Build Coastguard Worker         Ok(dir_cache.lookup(name))
1039*bb4ee6a4SAndroid Build Coastguard Worker     }
1040*bb4ee6a4SAndroid Build Coastguard Worker 
1041*bb4ee6a4SAndroid Build Coastguard Worker     // Performs an ascii case insensitive lookup.
ascii_casefold_lookup(&self, parent: &InodeData, name: &[u8]) -> io::Result<Entry>1042*bb4ee6a4SAndroid Build Coastguard Worker     fn ascii_casefold_lookup(&self, parent: &InodeData, name: &[u8]) -> io::Result<Entry> {
1043*bb4ee6a4SAndroid Build Coastguard Worker         match self.get_case_unfolded_name(parent, name)? {
1044*bb4ee6a4SAndroid Build Coastguard Worker             None => Err(io::Error::from_raw_os_error(libc::ENOENT)),
1045*bb4ee6a4SAndroid Build Coastguard Worker             Some(actual_name) => self.do_lookup(parent, &actual_name),
1046*bb4ee6a4SAndroid Build Coastguard Worker         }
1047*bb4ee6a4SAndroid Build Coastguard Worker     }
1048*bb4ee6a4SAndroid Build Coastguard Worker 
1049*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(test)]
exists_in_casefold_cache(&self, parent: Inode, name: &CStr) -> bool1050*bb4ee6a4SAndroid Build Coastguard Worker     fn exists_in_casefold_cache(&self, parent: Inode, name: &CStr) -> bool {
1051*bb4ee6a4SAndroid Build Coastguard Worker         let mut cache = self
1052*bb4ee6a4SAndroid Build Coastguard Worker             .lock_casefold_lookup_caches()
1053*bb4ee6a4SAndroid Build Coastguard Worker             .expect("casefold must be enabled");
1054*bb4ee6a4SAndroid Build Coastguard Worker         cache.exists_in_cache(parent, name)
1055*bb4ee6a4SAndroid Build Coastguard Worker     }
1056*bb4ee6a4SAndroid Build Coastguard Worker 
do_lookup(&self, parent: &InodeData, name: &CStr) -> io::Result<Entry>1057*bb4ee6a4SAndroid Build Coastguard Worker     fn do_lookup(&self, parent: &InodeData, name: &CStr) -> io::Result<Entry> {
1058*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg_attr(not(feature = "fs_permission_translation"), allow(unused_mut))]
1059*bb4ee6a4SAndroid Build Coastguard Worker         let mut st = statat(parent, name)?;
1060*bb4ee6a4SAndroid Build Coastguard Worker 
1061*bb4ee6a4SAndroid Build Coastguard Worker         let altkey = InodeAltKey {
1062*bb4ee6a4SAndroid Build Coastguard Worker             ino: st.st_ino,
1063*bb4ee6a4SAndroid Build Coastguard Worker             dev: st.st_dev,
1064*bb4ee6a4SAndroid Build Coastguard Worker         };
1065*bb4ee6a4SAndroid Build Coastguard Worker 
1066*bb4ee6a4SAndroid Build Coastguard Worker         let path = format!(
1067*bb4ee6a4SAndroid Build Coastguard Worker             "{}/{}",
1068*bb4ee6a4SAndroid Build Coastguard Worker             parent.path.clone(),
1069*bb4ee6a4SAndroid Build Coastguard Worker             name.to_str().unwrap_or("<non UTF-8 str>")
1070*bb4ee6a4SAndroid Build Coastguard Worker         );
1071*bb4ee6a4SAndroid Build Coastguard Worker 
1072*bb4ee6a4SAndroid Build Coastguard Worker         // Check if we already have an entry before opening a new file.
1073*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(data) = self.inodes.lock().get_alt(&altkey) {
1074*bb4ee6a4SAndroid Build Coastguard Worker             // Return the same inode with the reference counter increased.
1075*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "arc_quota")]
1076*bb4ee6a4SAndroid Build Coastguard Worker             self.set_permission(&mut st, &path);
1077*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "fs_runtime_ugid_map")]
1078*bb4ee6a4SAndroid Build Coastguard Worker             self.set_ugid_permission(&mut st, &path);
1079*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(Entry {
1080*bb4ee6a4SAndroid Build Coastguard Worker                 inode: self.increase_inode_refcount(data),
1081*bb4ee6a4SAndroid Build Coastguard Worker                 generation: 0,
1082*bb4ee6a4SAndroid Build Coastguard Worker                 attr: st,
1083*bb4ee6a4SAndroid Build Coastguard Worker                 // We use the same timeout for the attribute and the entry.
1084*bb4ee6a4SAndroid Build Coastguard Worker                 attr_timeout: self.cfg.timeout,
1085*bb4ee6a4SAndroid Build Coastguard Worker                 entry_timeout: self.cfg.timeout,
1086*bb4ee6a4SAndroid Build Coastguard Worker             });
1087*bb4ee6a4SAndroid Build Coastguard Worker         }
1088*bb4ee6a4SAndroid Build Coastguard Worker 
1089*bb4ee6a4SAndroid Build Coastguard Worker         // Open a regular file with O_RDONLY to store in `InodeData` so explicit open requests can
1090*bb4ee6a4SAndroid Build Coastguard Worker         // be skipped later if the ZERO_MESSAGE_{OPEN,OPENDIR} features are enabled.
1091*bb4ee6a4SAndroid Build Coastguard Worker         // If the crosvm process doesn't have a read permission, fall back to O_PATH below.
1092*bb4ee6a4SAndroid Build Coastguard Worker         let mut flags = libc::O_RDONLY | libc::O_NOFOLLOW | libc::O_CLOEXEC;
1093*bb4ee6a4SAndroid Build Coastguard Worker         match FileType::from(st.st_mode) {
1094*bb4ee6a4SAndroid Build Coastguard Worker             FileType::Regular => {}
1095*bb4ee6a4SAndroid Build Coastguard Worker             FileType::Directory => flags |= libc::O_DIRECTORY,
1096*bb4ee6a4SAndroid Build Coastguard Worker             FileType::Other => flags |= libc::O_PATH,
1097*bb4ee6a4SAndroid Build Coastguard Worker         };
1098*bb4ee6a4SAndroid Build Coastguard Worker 
1099*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value.
1100*bb4ee6a4SAndroid Build Coastguard Worker         let fd = match unsafe {
1101*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(libc::openat64(
1102*bb4ee6a4SAndroid Build Coastguard Worker                 parent.as_raw_descriptor(),
1103*bb4ee6a4SAndroid Build Coastguard Worker                 name.as_ptr(),
1104*bb4ee6a4SAndroid Build Coastguard Worker                 flags
1105*bb4ee6a4SAndroid Build Coastguard Worker             ))
1106*bb4ee6a4SAndroid Build Coastguard Worker         } {
1107*bb4ee6a4SAndroid Build Coastguard Worker             Ok(fd) => fd,
1108*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) if e.errno() == libc::EACCES => {
1109*bb4ee6a4SAndroid Build Coastguard Worker                 // If O_RDONLY is unavailable, fall back to O_PATH to get an FD to store in
1110*bb4ee6a4SAndroid Build Coastguard Worker                 // `InodeData`.
1111*bb4ee6a4SAndroid Build Coastguard Worker                 // Note that some operations which should be allowed without read permissions
1112*bb4ee6a4SAndroid Build Coastguard Worker                 // require syscalls that don't support O_PATH fds. For those syscalls, we will
1113*bb4ee6a4SAndroid Build Coastguard Worker                 // need to fall back to their path-based equivalents with /self/fd/${FD}.
1114*bb4ee6a4SAndroid Build Coastguard Worker                 // e.g. `fgetxattr()` for an O_PATH FD fails while `getxaattr()` for /self/fd/${FD}
1115*bb4ee6a4SAndroid Build Coastguard Worker                 // works.
1116*bb4ee6a4SAndroid Build Coastguard Worker                 flags |= libc::O_PATH;
1117*bb4ee6a4SAndroid Build Coastguard Worker                 // SAFETY: this doesn't modify any memory and we check the return value.
1118*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe {
1119*bb4ee6a4SAndroid Build Coastguard Worker                     syscall!(libc::openat64(
1120*bb4ee6a4SAndroid Build Coastguard Worker                         parent.as_raw_descriptor(),
1121*bb4ee6a4SAndroid Build Coastguard Worker                         name.as_ptr(),
1122*bb4ee6a4SAndroid Build Coastguard Worker                         flags
1123*bb4ee6a4SAndroid Build Coastguard Worker                     ))
1124*bb4ee6a4SAndroid Build Coastguard Worker                 }?
1125*bb4ee6a4SAndroid Build Coastguard Worker             }
1126*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
1127*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(e.into());
1128*bb4ee6a4SAndroid Build Coastguard Worker             }
1129*bb4ee6a4SAndroid Build Coastguard Worker         };
1130*bb4ee6a4SAndroid Build Coastguard Worker 
1131*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: safe because we own the fd.
1132*bb4ee6a4SAndroid Build Coastguard Worker         let f = unsafe { File::from_raw_descriptor(fd) };
1133*bb4ee6a4SAndroid Build Coastguard Worker         // We made sure the lock acquired for `self.inodes` is released automatically when
1134*bb4ee6a4SAndroid Build Coastguard Worker         // the if block above is exited, so a call to `self.add_entry()` should not cause a deadlock
1135*bb4ee6a4SAndroid Build Coastguard Worker         // here. This would not be the case if this were executed in an else block instead.
1136*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.add_entry(f, st, flags, path))
1137*bb4ee6a4SAndroid Build Coastguard Worker     }
1138*bb4ee6a4SAndroid Build Coastguard Worker 
get_cache_open_options(&self, flags: u32) -> OpenOptions1139*bb4ee6a4SAndroid Build Coastguard Worker     fn get_cache_open_options(&self, flags: u32) -> OpenOptions {
1140*bb4ee6a4SAndroid Build Coastguard Worker         let mut opts = OpenOptions::empty();
1141*bb4ee6a4SAndroid Build Coastguard Worker         match self.cfg.cache_policy {
1142*bb4ee6a4SAndroid Build Coastguard Worker             // We only set the direct I/O option on files.
1143*bb4ee6a4SAndroid Build Coastguard Worker             CachePolicy::Never => opts.set(
1144*bb4ee6a4SAndroid Build Coastguard Worker                 OpenOptions::DIRECT_IO,
1145*bb4ee6a4SAndroid Build Coastguard Worker                 flags & (libc::O_DIRECTORY as u32) == 0,
1146*bb4ee6a4SAndroid Build Coastguard Worker             ),
1147*bb4ee6a4SAndroid Build Coastguard Worker             CachePolicy::Always => {
1148*bb4ee6a4SAndroid Build Coastguard Worker                 opts |= if flags & (libc::O_DIRECTORY as u32) == 0 {
1149*bb4ee6a4SAndroid Build Coastguard Worker                     OpenOptions::KEEP_CACHE
1150*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
1151*bb4ee6a4SAndroid Build Coastguard Worker                     OpenOptions::CACHE_DIR
1152*bb4ee6a4SAndroid Build Coastguard Worker                 }
1153*bb4ee6a4SAndroid Build Coastguard Worker             }
1154*bb4ee6a4SAndroid Build Coastguard Worker             _ => {}
1155*bb4ee6a4SAndroid Build Coastguard Worker         };
1156*bb4ee6a4SAndroid Build Coastguard Worker         opts
1157*bb4ee6a4SAndroid Build Coastguard Worker     }
1158*bb4ee6a4SAndroid Build Coastguard Worker 
1159*bb4ee6a4SAndroid Build Coastguard Worker     // Performs lookup using original name first, if it fails and ascii_casefold is enabled,
1160*bb4ee6a4SAndroid Build Coastguard Worker     // it tries to unfold the name and do lookup again.
do_lookup_with_casefold_fallback( &self, parent: &InodeData, name: &CStr, ) -> io::Result<Entry>1161*bb4ee6a4SAndroid Build Coastguard Worker     fn do_lookup_with_casefold_fallback(
1162*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1163*bb4ee6a4SAndroid Build Coastguard Worker         parent: &InodeData,
1164*bb4ee6a4SAndroid Build Coastguard Worker         name: &CStr,
1165*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<Entry> {
1166*bb4ee6a4SAndroid Build Coastguard Worker         let mut res = self.do_lookup(parent, name);
1167*bb4ee6a4SAndroid Build Coastguard Worker         // If `ascii_casefold` is enabled, fallback to `ascii_casefold_lookup()`.
1168*bb4ee6a4SAndroid Build Coastguard Worker         if res.is_err() && self.cfg.ascii_casefold {
1169*bb4ee6a4SAndroid Build Coastguard Worker             res = self.ascii_casefold_lookup(parent, name.to_bytes());
1170*bb4ee6a4SAndroid Build Coastguard Worker         }
1171*bb4ee6a4SAndroid Build Coastguard Worker         res
1172*bb4ee6a4SAndroid Build Coastguard Worker     }
1173*bb4ee6a4SAndroid Build Coastguard Worker 
do_open(&self, inode: Inode, flags: u32) -> io::Result<(Option<Handle>, OpenOptions)>1174*bb4ee6a4SAndroid Build Coastguard Worker     fn do_open(&self, inode: Inode, flags: u32) -> io::Result<(Option<Handle>, OpenOptions)> {
1175*bb4ee6a4SAndroid Build Coastguard Worker         let inode_data = self.find_inode(inode)?;
1176*bb4ee6a4SAndroid Build Coastguard Worker 
1177*bb4ee6a4SAndroid Build Coastguard Worker         let file = Mutex::new(self.open_inode(&inode_data, flags as i32)?);
1178*bb4ee6a4SAndroid Build Coastguard Worker 
1179*bb4ee6a4SAndroid Build Coastguard Worker         let handle = self.next_handle.fetch_add(1, Ordering::Relaxed);
1180*bb4ee6a4SAndroid Build Coastguard Worker         let data = HandleData { inode, file };
1181*bb4ee6a4SAndroid Build Coastguard Worker 
1182*bb4ee6a4SAndroid Build Coastguard Worker         self.handles.lock().insert(handle, Arc::new(data));
1183*bb4ee6a4SAndroid Build Coastguard Worker 
1184*bb4ee6a4SAndroid Build Coastguard Worker         let opts = self.get_cache_open_options(flags);
1185*bb4ee6a4SAndroid Build Coastguard Worker 
1186*bb4ee6a4SAndroid Build Coastguard Worker         Ok((Some(handle), opts))
1187*bb4ee6a4SAndroid Build Coastguard Worker     }
1188*bb4ee6a4SAndroid Build Coastguard Worker 
do_open_at( &self, parent_data: Arc<InodeData>, name: &CStr, inode: Inode, flags: u32, ) -> io::Result<(Option<Handle>, OpenOptions)>1189*bb4ee6a4SAndroid Build Coastguard Worker     fn do_open_at(
1190*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1191*bb4ee6a4SAndroid Build Coastguard Worker         parent_data: Arc<InodeData>,
1192*bb4ee6a4SAndroid Build Coastguard Worker         name: &CStr,
1193*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
1194*bb4ee6a4SAndroid Build Coastguard Worker         flags: u32,
1195*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<(Option<Handle>, OpenOptions)> {
1196*bb4ee6a4SAndroid Build Coastguard Worker         let open_flags = self.update_open_flags(flags as i32);
1197*bb4ee6a4SAndroid Build Coastguard Worker 
1198*bb4ee6a4SAndroid Build Coastguard Worker         let fd_open = syscall!(
1199*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: return value is checked.
1200*bb4ee6a4SAndroid Build Coastguard Worker             unsafe {
1201*bb4ee6a4SAndroid Build Coastguard Worker                 libc::openat64(
1202*bb4ee6a4SAndroid Build Coastguard Worker                     parent_data.as_raw_descriptor(),
1203*bb4ee6a4SAndroid Build Coastguard Worker                     name.as_ptr(),
1204*bb4ee6a4SAndroid Build Coastguard Worker                     (open_flags | libc::O_CLOEXEC) & !(libc::O_NOFOLLOW | libc::O_DIRECT),
1205*bb4ee6a4SAndroid Build Coastguard Worker                 )
1206*bb4ee6a4SAndroid Build Coastguard Worker             }
1207*bb4ee6a4SAndroid Build Coastguard Worker         )?;
1208*bb4ee6a4SAndroid Build Coastguard Worker 
1209*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: fd_open is valid
1210*bb4ee6a4SAndroid Build Coastguard Worker         let file_open = unsafe { File::from_raw_descriptor(fd_open) };
1211*bb4ee6a4SAndroid Build Coastguard Worker         let handle = self.next_handle.fetch_add(1, Ordering::Relaxed);
1212*bb4ee6a4SAndroid Build Coastguard Worker         let data = HandleData {
1213*bb4ee6a4SAndroid Build Coastguard Worker             inode,
1214*bb4ee6a4SAndroid Build Coastguard Worker             file: Mutex::new(file_open),
1215*bb4ee6a4SAndroid Build Coastguard Worker         };
1216*bb4ee6a4SAndroid Build Coastguard Worker 
1217*bb4ee6a4SAndroid Build Coastguard Worker         self.handles.lock().insert(handle, Arc::new(data));
1218*bb4ee6a4SAndroid Build Coastguard Worker 
1219*bb4ee6a4SAndroid Build Coastguard Worker         let opts = self.get_cache_open_options(open_flags as u32);
1220*bb4ee6a4SAndroid Build Coastguard Worker         Ok((Some(handle), opts))
1221*bb4ee6a4SAndroid Build Coastguard Worker     }
1222*bb4ee6a4SAndroid Build Coastguard Worker 
do_release(&self, inode: Inode, handle: Handle) -> io::Result<()>1223*bb4ee6a4SAndroid Build Coastguard Worker     fn do_release(&self, inode: Inode, handle: Handle) -> io::Result<()> {
1224*bb4ee6a4SAndroid Build Coastguard Worker         let mut handles = self.handles.lock();
1225*bb4ee6a4SAndroid Build Coastguard Worker 
1226*bb4ee6a4SAndroid Build Coastguard Worker         if let btree_map::Entry::Occupied(e) = handles.entry(handle) {
1227*bb4ee6a4SAndroid Build Coastguard Worker             if e.get().inode == inode {
1228*bb4ee6a4SAndroid Build Coastguard Worker                 // We don't need to close the file here because that will happen automatically when
1229*bb4ee6a4SAndroid Build Coastguard Worker                 // the last `Arc` is dropped.
1230*bb4ee6a4SAndroid Build Coastguard Worker                 e.remove();
1231*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(());
1232*bb4ee6a4SAndroid Build Coastguard Worker             }
1233*bb4ee6a4SAndroid Build Coastguard Worker         }
1234*bb4ee6a4SAndroid Build Coastguard Worker 
1235*bb4ee6a4SAndroid Build Coastguard Worker         Err(ebadf())
1236*bb4ee6a4SAndroid Build Coastguard Worker     }
1237*bb4ee6a4SAndroid Build Coastguard Worker 
do_getattr(&self, inode: &InodeData) -> io::Result<(libc::stat64, Duration)>1238*bb4ee6a4SAndroid Build Coastguard Worker     fn do_getattr(&self, inode: &InodeData) -> io::Result<(libc::stat64, Duration)> {
1239*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(unused_mut)]
1240*bb4ee6a4SAndroid Build Coastguard Worker         let mut st = stat(inode)?;
1241*bb4ee6a4SAndroid Build Coastguard Worker 
1242*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
1243*bb4ee6a4SAndroid Build Coastguard Worker         self.set_permission(&mut st, &inode.path);
1244*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "fs_runtime_ugid_map")]
1245*bb4ee6a4SAndroid Build Coastguard Worker         self.set_ugid_permission(&mut st, &inode.path);
1246*bb4ee6a4SAndroid Build Coastguard Worker         Ok((st, self.cfg.timeout))
1247*bb4ee6a4SAndroid Build Coastguard Worker     }
1248*bb4ee6a4SAndroid Build Coastguard Worker 
do_unlink(&self, parent: &InodeData, name: &CStr, flags: libc::c_int) -> io::Result<()>1249*bb4ee6a4SAndroid Build Coastguard Worker     fn do_unlink(&self, parent: &InodeData, name: &CStr, flags: libc::c_int) -> io::Result<()> {
1250*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value.
1251*bb4ee6a4SAndroid Build Coastguard Worker         syscall!(unsafe { libc::unlinkat(parent.as_raw_descriptor(), name.as_ptr(), flags) })?;
1252*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1253*bb4ee6a4SAndroid Build Coastguard Worker     }
1254*bb4ee6a4SAndroid Build Coastguard Worker 
do_fsync<F: AsRawDescriptor>(&self, file: &F, datasync: bool) -> io::Result<()>1255*bb4ee6a4SAndroid Build Coastguard Worker     fn do_fsync<F: AsRawDescriptor>(&self, file: &F, datasync: bool) -> io::Result<()> {
1256*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value.
1257*bb4ee6a4SAndroid Build Coastguard Worker         syscall!(unsafe {
1258*bb4ee6a4SAndroid Build Coastguard Worker             if datasync {
1259*bb4ee6a4SAndroid Build Coastguard Worker                 libc::fdatasync(file.as_raw_descriptor())
1260*bb4ee6a4SAndroid Build Coastguard Worker             } else {
1261*bb4ee6a4SAndroid Build Coastguard Worker                 libc::fsync(file.as_raw_descriptor())
1262*bb4ee6a4SAndroid Build Coastguard Worker             }
1263*bb4ee6a4SAndroid Build Coastguard Worker         })?;
1264*bb4ee6a4SAndroid Build Coastguard Worker 
1265*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1266*bb4ee6a4SAndroid Build Coastguard Worker     }
1267*bb4ee6a4SAndroid Build Coastguard Worker 
1268*bb4ee6a4SAndroid Build Coastguard Worker     // Changes the CWD to `self.proc`, runs `f`, and then changes the CWD back to the root
1269*bb4ee6a4SAndroid Build Coastguard Worker     // directory. This effectively emulates an *at syscall starting at /proc, which is useful when
1270*bb4ee6a4SAndroid Build Coastguard Worker     // there is no *at syscall available. Panics if any of the fchdir calls fail or if there is no
1271*bb4ee6a4SAndroid Build Coastguard Worker     // root inode.
1272*bb4ee6a4SAndroid Build Coastguard Worker     //
1273*bb4ee6a4SAndroid Build Coastguard Worker     // NOTE: this method acquires an `self`-wide lock. If any locks are acquired in `f`, care must
1274*bb4ee6a4SAndroid Build Coastguard Worker     // be taken to avoid the risk of deadlocks.
with_proc_chdir<F, T>(&self, f: F) -> T where F: FnOnce() -> T,1275*bb4ee6a4SAndroid Build Coastguard Worker     fn with_proc_chdir<F, T>(&self, f: F) -> T
1276*bb4ee6a4SAndroid Build Coastguard Worker     where
1277*bb4ee6a4SAndroid Build Coastguard Worker         F: FnOnce() -> T,
1278*bb4ee6a4SAndroid Build Coastguard Worker     {
1279*bb4ee6a4SAndroid Build Coastguard Worker         let root = self.find_inode(ROOT_ID).expect("failed to find root inode");
1280*bb4ee6a4SAndroid Build Coastguard Worker 
1281*bb4ee6a4SAndroid Build Coastguard Worker         // Acquire a lock for `fchdir`.
1282*bb4ee6a4SAndroid Build Coastguard Worker         let _proc_lock = self.process_lock.lock();
1283*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value. Since the
1284*bb4ee6a4SAndroid Build Coastguard Worker         // fchdir should never fail we just use debug_asserts.
1285*bb4ee6a4SAndroid Build Coastguard Worker         let proc_cwd = unsafe { libc::fchdir(self.proc.as_raw_descriptor()) };
1286*bb4ee6a4SAndroid Build Coastguard Worker         debug_assert_eq!(
1287*bb4ee6a4SAndroid Build Coastguard Worker             proc_cwd,
1288*bb4ee6a4SAndroid Build Coastguard Worker             0,
1289*bb4ee6a4SAndroid Build Coastguard Worker             "failed to fchdir to /proc: {}",
1290*bb4ee6a4SAndroid Build Coastguard Worker             io::Error::last_os_error()
1291*bb4ee6a4SAndroid Build Coastguard Worker         );
1292*bb4ee6a4SAndroid Build Coastguard Worker 
1293*bb4ee6a4SAndroid Build Coastguard Worker         let res = f();
1294*bb4ee6a4SAndroid Build Coastguard Worker 
1295*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value. Since the
1296*bb4ee6a4SAndroid Build Coastguard Worker         // fchdir should never fail we just use debug_asserts.
1297*bb4ee6a4SAndroid Build Coastguard Worker         let root_cwd = unsafe { libc::fchdir(root.as_raw_descriptor()) };
1298*bb4ee6a4SAndroid Build Coastguard Worker         debug_assert_eq!(
1299*bb4ee6a4SAndroid Build Coastguard Worker             root_cwd,
1300*bb4ee6a4SAndroid Build Coastguard Worker             0,
1301*bb4ee6a4SAndroid Build Coastguard Worker             "failed to fchdir back to root directory: {}",
1302*bb4ee6a4SAndroid Build Coastguard Worker             io::Error::last_os_error()
1303*bb4ee6a4SAndroid Build Coastguard Worker         );
1304*bb4ee6a4SAndroid Build Coastguard Worker 
1305*bb4ee6a4SAndroid Build Coastguard Worker         res
1306*bb4ee6a4SAndroid Build Coastguard Worker     }
1307*bb4ee6a4SAndroid Build Coastguard Worker 
do_getxattr(&self, inode: &InodeData, name: &CStr, value: &mut [u8]) -> io::Result<usize>1308*bb4ee6a4SAndroid Build Coastguard Worker     fn do_getxattr(&self, inode: &InodeData, name: &CStr, value: &mut [u8]) -> io::Result<usize> {
1309*bb4ee6a4SAndroid Build Coastguard Worker         let file = inode.file.lock();
1310*bb4ee6a4SAndroid Build Coastguard Worker         let o_path_file = (file.1 & libc::O_PATH) != 0;
1311*bb4ee6a4SAndroid Build Coastguard Worker         let res = if o_path_file {
1312*bb4ee6a4SAndroid Build Coastguard Worker             // For FDs opened with `O_PATH`, we cannot call `fgetxattr` normally. Instead we
1313*bb4ee6a4SAndroid Build Coastguard Worker             // emulate an _at syscall by changing the CWD to /proc, running the path based syscall,
1314*bb4ee6a4SAndroid Build Coastguard Worker             //  and then setting the CWD back to the root directory.
1315*bb4ee6a4SAndroid Build Coastguard Worker             let path = CString::new(format!("self/fd/{}", file.0.as_raw_descriptor()))
1316*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
1317*bb4ee6a4SAndroid Build Coastguard Worker 
1318*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this will only modify `value` and we check the return value.
1319*bb4ee6a4SAndroid Build Coastguard Worker             self.with_proc_chdir(|| unsafe {
1320*bb4ee6a4SAndroid Build Coastguard Worker                 libc::getxattr(
1321*bb4ee6a4SAndroid Build Coastguard Worker                     path.as_ptr(),
1322*bb4ee6a4SAndroid Build Coastguard Worker                     name.as_ptr(),
1323*bb4ee6a4SAndroid Build Coastguard Worker                     value.as_mut_ptr() as *mut libc::c_void,
1324*bb4ee6a4SAndroid Build Coastguard Worker                     value.len() as libc::size_t,
1325*bb4ee6a4SAndroid Build Coastguard Worker                 )
1326*bb4ee6a4SAndroid Build Coastguard Worker             })
1327*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1328*bb4ee6a4SAndroid Build Coastguard Worker             // For regular files and directories, we can just use fgetxattr.
1329*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this will only write to `value` and we check the return value.
1330*bb4ee6a4SAndroid Build Coastguard Worker             unsafe {
1331*bb4ee6a4SAndroid Build Coastguard Worker                 libc::fgetxattr(
1332*bb4ee6a4SAndroid Build Coastguard Worker                     file.0.as_raw_descriptor(),
1333*bb4ee6a4SAndroid Build Coastguard Worker                     name.as_ptr(),
1334*bb4ee6a4SAndroid Build Coastguard Worker                     value.as_mut_ptr() as *mut libc::c_void,
1335*bb4ee6a4SAndroid Build Coastguard Worker                     value.len() as libc::size_t,
1336*bb4ee6a4SAndroid Build Coastguard Worker                 )
1337*bb4ee6a4SAndroid Build Coastguard Worker             }
1338*bb4ee6a4SAndroid Build Coastguard Worker         };
1339*bb4ee6a4SAndroid Build Coastguard Worker 
1340*bb4ee6a4SAndroid Build Coastguard Worker         if res < 0 {
1341*bb4ee6a4SAndroid Build Coastguard Worker             Err(io::Error::last_os_error())
1342*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1343*bb4ee6a4SAndroid Build Coastguard Worker             Ok(res as usize)
1344*bb4ee6a4SAndroid Build Coastguard Worker         }
1345*bb4ee6a4SAndroid Build Coastguard Worker     }
1346*bb4ee6a4SAndroid Build Coastguard Worker 
get_encryption_policy_ex<R: io::Read>( &self, inode: Inode, handle: Handle, mut r: R, ) -> io::Result<IoctlReply>1347*bb4ee6a4SAndroid Build Coastguard Worker     fn get_encryption_policy_ex<R: io::Read>(
1348*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1349*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
1350*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
1351*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1352*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<IoctlReply> {
1353*bb4ee6a4SAndroid Build Coastguard Worker         let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
1354*bb4ee6a4SAndroid Build Coastguard Worker             self.find_inode(inode)?
1355*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1356*bb4ee6a4SAndroid Build Coastguard Worker             self.find_handle(handle, inode)?
1357*bb4ee6a4SAndroid Build Coastguard Worker         };
1358*bb4ee6a4SAndroid Build Coastguard Worker 
1359*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this struct only has integer fields and any value is valid.
1360*bb4ee6a4SAndroid Build Coastguard Worker         let mut arg = unsafe { MaybeUninit::<fscrypt_get_policy_ex_arg>::zeroed().assume_init() };
1361*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(arg.policy_size.as_bytes_mut())?;
1362*bb4ee6a4SAndroid Build Coastguard Worker 
1363*bb4ee6a4SAndroid Build Coastguard Worker         let policy_size = cmp::min(arg.policy_size, size_of::<fscrypt_policy>() as u64);
1364*bb4ee6a4SAndroid Build Coastguard Worker         arg.policy_size = policy_size;
1365*bb4ee6a4SAndroid Build Coastguard Worker 
1366*bb4ee6a4SAndroid Build Coastguard Worker         let res =
1367*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: the kernel will only write to `arg` and we check the return value.
1368*bb4ee6a4SAndroid Build Coastguard Worker             unsafe { ioctl_with_mut_ptr(&*data, FS_IOC_GET_ENCRYPTION_POLICY_EX, &mut arg) };
1369*bb4ee6a4SAndroid Build Coastguard Worker         if res < 0 {
1370*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Err(io::Error::last_os_error())))
1371*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1372*bb4ee6a4SAndroid Build Coastguard Worker             let len = size_of::<u64>() + arg.policy_size as usize;
1373*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Ok(<&[u8]>::from(&arg)[..len].to_vec())))
1374*bb4ee6a4SAndroid Build Coastguard Worker         }
1375*bb4ee6a4SAndroid Build Coastguard Worker     }
1376*bb4ee6a4SAndroid Build Coastguard Worker 
get_fsxattr(&self, inode: Inode, handle: Handle) -> io::Result<IoctlReply>1377*bb4ee6a4SAndroid Build Coastguard Worker     fn get_fsxattr(&self, inode: Inode, handle: Handle) -> io::Result<IoctlReply> {
1378*bb4ee6a4SAndroid Build Coastguard Worker         let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
1379*bb4ee6a4SAndroid Build Coastguard Worker             self.find_inode(inode)?
1380*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1381*bb4ee6a4SAndroid Build Coastguard Worker             self.find_handle(handle, inode)?
1382*bb4ee6a4SAndroid Build Coastguard Worker         };
1383*bb4ee6a4SAndroid Build Coastguard Worker 
1384*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = MaybeUninit::<fsxattr>::zeroed();
1385*bb4ee6a4SAndroid Build Coastguard Worker 
1386*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: the kernel will only write to `buf` and we check the return value.
1387*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe { ioctl_with_mut_ptr(&*data, FS_IOC_FSGETXATTR, buf.as_mut_ptr()) };
1388*bb4ee6a4SAndroid Build Coastguard Worker         if res < 0 {
1389*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Err(io::Error::last_os_error())))
1390*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1391*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: the kernel guarantees that the policy is now initialized.
1392*bb4ee6a4SAndroid Build Coastguard Worker             let xattr = unsafe { buf.assume_init() };
1393*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Ok(xattr.as_bytes().to_vec())))
1394*bb4ee6a4SAndroid Build Coastguard Worker         }
1395*bb4ee6a4SAndroid Build Coastguard Worker     }
1396*bb4ee6a4SAndroid Build Coastguard Worker 
set_fsxattr<R: io::Read>( &self, #[cfg_attr(not(feature = "arc_quota"), allow(unused_variables))] ctx: Context, inode: Inode, handle: Handle, mut r: R, ) -> io::Result<IoctlReply>1397*bb4ee6a4SAndroid Build Coastguard Worker     fn set_fsxattr<R: io::Read>(
1398*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1399*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg_attr(not(feature = "arc_quota"), allow(unused_variables))] ctx: Context,
1400*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
1401*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
1402*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1403*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<IoctlReply> {
1404*bb4ee6a4SAndroid Build Coastguard Worker         let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
1405*bb4ee6a4SAndroid Build Coastguard Worker             self.find_inode(inode)?
1406*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1407*bb4ee6a4SAndroid Build Coastguard Worker             self.find_handle(handle, inode)?
1408*bb4ee6a4SAndroid Build Coastguard Worker         };
1409*bb4ee6a4SAndroid Build Coastguard Worker 
1410*bb4ee6a4SAndroid Build Coastguard Worker         let mut in_attr = fsxattr::new_zeroed();
1411*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(in_attr.as_bytes_mut())?;
1412*bb4ee6a4SAndroid Build Coastguard Worker 
1413*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
1414*bb4ee6a4SAndroid Build Coastguard Worker         let st = stat(&*data)?;
1415*bb4ee6a4SAndroid Build Coastguard Worker 
1416*bb4ee6a4SAndroid Build Coastguard Worker         // Changing quota project ID requires CAP_FOWNER or being file owner.
1417*bb4ee6a4SAndroid Build Coastguard Worker         // Here we use privileged_quota_uids because we cannot perform a CAP_FOWNER check.
1418*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
1419*bb4ee6a4SAndroid Build Coastguard Worker         if ctx.uid == st.st_uid || self.cfg.privileged_quota_uids.contains(&ctx.uid) {
1420*bb4ee6a4SAndroid Build Coastguard Worker             // Get the current fsxattr.
1421*bb4ee6a4SAndroid Build Coastguard Worker             let mut buf = MaybeUninit::<fsxattr>::zeroed();
1422*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: the kernel will only write to `buf` and we check the return value.
1423*bb4ee6a4SAndroid Build Coastguard Worker             let res = unsafe { ioctl_with_mut_ptr(&*data, FS_IOC_FSGETXATTR, buf.as_mut_ptr()) };
1424*bb4ee6a4SAndroid Build Coastguard Worker             if res < 0 {
1425*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(IoctlReply::Done(Err(io::Error::last_os_error())));
1426*bb4ee6a4SAndroid Build Coastguard Worker             }
1427*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: the kernel guarantees that the policy is now initialized.
1428*bb4ee6a4SAndroid Build Coastguard Worker             let current_attr = unsafe { buf.assume_init() };
1429*bb4ee6a4SAndroid Build Coastguard Worker 
1430*bb4ee6a4SAndroid Build Coastguard Worker             // Project ID cannot be changed inside a user namespace.
1431*bb4ee6a4SAndroid Build Coastguard Worker             // Use Spaced to avoid this restriction.
1432*bb4ee6a4SAndroid Build Coastguard Worker             if current_attr.fsx_projid != in_attr.fsx_projid {
1433*bb4ee6a4SAndroid Build Coastguard Worker                 let connection = self.dbus_connection.as_ref().unwrap().lock();
1434*bb4ee6a4SAndroid Build Coastguard Worker                 let proxy = connection.with_proxy(
1435*bb4ee6a4SAndroid Build Coastguard Worker                     "org.chromium.Spaced",
1436*bb4ee6a4SAndroid Build Coastguard Worker                     "/org/chromium/Spaced",
1437*bb4ee6a4SAndroid Build Coastguard Worker                     DEFAULT_DBUS_TIMEOUT,
1438*bb4ee6a4SAndroid Build Coastguard Worker                 );
1439*bb4ee6a4SAndroid Build Coastguard Worker                 let project_id = in_attr.fsx_projid;
1440*bb4ee6a4SAndroid Build Coastguard Worker                 if !is_android_project_id(project_id) {
1441*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(io::Error::from_raw_os_error(libc::EINVAL));
1442*bb4ee6a4SAndroid Build Coastguard Worker                 }
1443*bb4ee6a4SAndroid Build Coastguard Worker                 let file_clone = base::SafeDescriptor::try_from(&*data)?;
1444*bb4ee6a4SAndroid Build Coastguard Worker                 match proxy.set_project_id(file_clone.into(), project_id) {
1445*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(r) => {
1446*bb4ee6a4SAndroid Build Coastguard Worker                         let r = SetProjectIdReply::parse_from_bytes(&r)
1447*bb4ee6a4SAndroid Build Coastguard Worker                             .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
1448*bb4ee6a4SAndroid Build Coastguard Worker                         if !r.success {
1449*bb4ee6a4SAndroid Build Coastguard Worker                             return Ok(IoctlReply::Done(Err(io::Error::from_raw_os_error(
1450*bb4ee6a4SAndroid Build Coastguard Worker                                 r.error,
1451*bb4ee6a4SAndroid Build Coastguard Worker                             ))));
1452*bb4ee6a4SAndroid Build Coastguard Worker                         }
1453*bb4ee6a4SAndroid Build Coastguard Worker                     }
1454*bb4ee6a4SAndroid Build Coastguard Worker                     Err(e) => {
1455*bb4ee6a4SAndroid Build Coastguard Worker                         return Err(io::Error::new(io::ErrorKind::Other, e));
1456*bb4ee6a4SAndroid Build Coastguard Worker                     }
1457*bb4ee6a4SAndroid Build Coastguard Worker                 };
1458*bb4ee6a4SAndroid Build Coastguard Worker             }
1459*bb4ee6a4SAndroid Build Coastguard Worker         }
1460*bb4ee6a4SAndroid Build Coastguard Worker 
1461*bb4ee6a4SAndroid Build Coastguard Worker         //  SAFETY: this doesn't modify any memory and we check the return value.
1462*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe { ioctl_with_ptr(&*data, FS_IOC_FSSETXATTR, &in_attr) };
1463*bb4ee6a4SAndroid Build Coastguard Worker         if res < 0 {
1464*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Err(io::Error::last_os_error())))
1465*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1466*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Ok(Vec::new())))
1467*bb4ee6a4SAndroid Build Coastguard Worker         }
1468*bb4ee6a4SAndroid Build Coastguard Worker     }
1469*bb4ee6a4SAndroid Build Coastguard Worker 
get_flags(&self, inode: Inode, handle: Handle) -> io::Result<IoctlReply>1470*bb4ee6a4SAndroid Build Coastguard Worker     fn get_flags(&self, inode: Inode, handle: Handle) -> io::Result<IoctlReply> {
1471*bb4ee6a4SAndroid Build Coastguard Worker         let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
1472*bb4ee6a4SAndroid Build Coastguard Worker             self.find_inode(inode)?
1473*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1474*bb4ee6a4SAndroid Build Coastguard Worker             self.find_handle(handle, inode)?
1475*bb4ee6a4SAndroid Build Coastguard Worker         };
1476*bb4ee6a4SAndroid Build Coastguard Worker 
1477*bb4ee6a4SAndroid Build Coastguard Worker         // The ioctl encoding is a long but the parameter is actually an int.
1478*bb4ee6a4SAndroid Build Coastguard Worker         let mut flags: c_int = 0;
1479*bb4ee6a4SAndroid Build Coastguard Worker 
1480*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: the kernel will only write to `flags` and we check the return value.
1481*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe { ioctl_with_mut_ptr(&*data, FS_IOC_GETFLAGS, &mut flags) };
1482*bb4ee6a4SAndroid Build Coastguard Worker         if res < 0 {
1483*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Err(io::Error::last_os_error())))
1484*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1485*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Ok(flags.to_ne_bytes().to_vec())))
1486*bb4ee6a4SAndroid Build Coastguard Worker         }
1487*bb4ee6a4SAndroid Build Coastguard Worker     }
1488*bb4ee6a4SAndroid Build Coastguard Worker 
set_flags<R: io::Read>( &self, #[cfg_attr(not(feature = "arc_quota"), allow(unused_variables))] ctx: Context, inode: Inode, handle: Handle, mut r: R, ) -> io::Result<IoctlReply>1489*bb4ee6a4SAndroid Build Coastguard Worker     fn set_flags<R: io::Read>(
1490*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1491*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg_attr(not(feature = "arc_quota"), allow(unused_variables))] ctx: Context,
1492*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
1493*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
1494*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1495*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<IoctlReply> {
1496*bb4ee6a4SAndroid Build Coastguard Worker         let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
1497*bb4ee6a4SAndroid Build Coastguard Worker             self.find_inode(inode)?
1498*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1499*bb4ee6a4SAndroid Build Coastguard Worker             self.find_handle(handle, inode)?
1500*bb4ee6a4SAndroid Build Coastguard Worker         };
1501*bb4ee6a4SAndroid Build Coastguard Worker 
1502*bb4ee6a4SAndroid Build Coastguard Worker         // The ioctl encoding is a long but the parameter is actually an int.
1503*bb4ee6a4SAndroid Build Coastguard Worker         let mut in_flags: c_int = 0;
1504*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(in_flags.as_bytes_mut())?;
1505*bb4ee6a4SAndroid Build Coastguard Worker 
1506*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
1507*bb4ee6a4SAndroid Build Coastguard Worker         let st = stat(&*data)?;
1508*bb4ee6a4SAndroid Build Coastguard Worker 
1509*bb4ee6a4SAndroid Build Coastguard Worker         // Only privleged uid can perform FS_IOC_SETFLAGS through cryptohome.
1510*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
1511*bb4ee6a4SAndroid Build Coastguard Worker         if ctx.uid == st.st_uid || self.cfg.privileged_quota_uids.contains(&ctx.uid) {
1512*bb4ee6a4SAndroid Build Coastguard Worker             // Get the current flag.
1513*bb4ee6a4SAndroid Build Coastguard Worker             let mut buf = MaybeUninit::<c_int>::zeroed();
1514*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: the kernel will only write to `buf` and we check the return value.
1515*bb4ee6a4SAndroid Build Coastguard Worker             let res = unsafe { ioctl_with_mut_ptr(&*data, FS_IOC_GETFLAGS, buf.as_mut_ptr()) };
1516*bb4ee6a4SAndroid Build Coastguard Worker             if res < 0 {
1517*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(IoctlReply::Done(Err(io::Error::last_os_error())));
1518*bb4ee6a4SAndroid Build Coastguard Worker             }
1519*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: the kernel guarantees that the policy is now initialized.
1520*bb4ee6a4SAndroid Build Coastguard Worker             let current_flags = unsafe { buf.assume_init() };
1521*bb4ee6a4SAndroid Build Coastguard Worker 
1522*bb4ee6a4SAndroid Build Coastguard Worker             // Project inheritance flag cannot be changed inside a user namespace.
1523*bb4ee6a4SAndroid Build Coastguard Worker             // Use Spaced to avoid this restriction.
1524*bb4ee6a4SAndroid Build Coastguard Worker             if (in_flags & FS_PROJINHERIT_FL) != (current_flags & FS_PROJINHERIT_FL) {
1525*bb4ee6a4SAndroid Build Coastguard Worker                 let connection = self.dbus_connection.as_ref().unwrap().lock();
1526*bb4ee6a4SAndroid Build Coastguard Worker                 let proxy = connection.with_proxy(
1527*bb4ee6a4SAndroid Build Coastguard Worker                     "org.chromium.Spaced",
1528*bb4ee6a4SAndroid Build Coastguard Worker                     "/org/chromium/Spaced",
1529*bb4ee6a4SAndroid Build Coastguard Worker                     DEFAULT_DBUS_TIMEOUT,
1530*bb4ee6a4SAndroid Build Coastguard Worker                 );
1531*bb4ee6a4SAndroid Build Coastguard Worker                 // If the input flags contain FS_PROJINHERIT_FL, then it is a set. Otherwise it is a
1532*bb4ee6a4SAndroid Build Coastguard Worker                 // reset.
1533*bb4ee6a4SAndroid Build Coastguard Worker                 let enable = (in_flags & FS_PROJINHERIT_FL) == FS_PROJINHERIT_FL;
1534*bb4ee6a4SAndroid Build Coastguard Worker                 let file_clone = base::SafeDescriptor::try_from(&*data)?;
1535*bb4ee6a4SAndroid Build Coastguard Worker                 match proxy.set_project_inheritance_flag(file_clone.into(), enable) {
1536*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(r) => {
1537*bb4ee6a4SAndroid Build Coastguard Worker                         let r = SetProjectInheritanceFlagReply::parse_from_bytes(&r)
1538*bb4ee6a4SAndroid Build Coastguard Worker                             .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
1539*bb4ee6a4SAndroid Build Coastguard Worker                         if !r.success {
1540*bb4ee6a4SAndroid Build Coastguard Worker                             return Ok(IoctlReply::Done(Err(io::Error::from_raw_os_error(
1541*bb4ee6a4SAndroid Build Coastguard Worker                                 r.error,
1542*bb4ee6a4SAndroid Build Coastguard Worker                             ))));
1543*bb4ee6a4SAndroid Build Coastguard Worker                         }
1544*bb4ee6a4SAndroid Build Coastguard Worker                     }
1545*bb4ee6a4SAndroid Build Coastguard Worker                     Err(e) => {
1546*bb4ee6a4SAndroid Build Coastguard Worker                         return Err(io::Error::new(io::ErrorKind::Other, e));
1547*bb4ee6a4SAndroid Build Coastguard Worker                     }
1548*bb4ee6a4SAndroid Build Coastguard Worker                 };
1549*bb4ee6a4SAndroid Build Coastguard Worker             }
1550*bb4ee6a4SAndroid Build Coastguard Worker         }
1551*bb4ee6a4SAndroid Build Coastguard Worker 
1552*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value.
1553*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe { ioctl_with_ptr(&*data, FS_IOC_SETFLAGS, &in_flags) };
1554*bb4ee6a4SAndroid Build Coastguard Worker         if res < 0 {
1555*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Err(io::Error::last_os_error())))
1556*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1557*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Ok(Vec::new())))
1558*bb4ee6a4SAndroid Build Coastguard Worker         }
1559*bb4ee6a4SAndroid Build Coastguard Worker     }
1560*bb4ee6a4SAndroid Build Coastguard Worker 
enable_verity<R: io::Read>( &self, inode: Inode, handle: Handle, mut r: R, ) -> io::Result<IoctlReply>1561*bb4ee6a4SAndroid Build Coastguard Worker     fn enable_verity<R: io::Read>(
1562*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1563*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
1564*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
1565*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1566*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<IoctlReply> {
1567*bb4ee6a4SAndroid Build Coastguard Worker         let inode_data = self.find_inode(inode)?;
1568*bb4ee6a4SAndroid Build Coastguard Worker 
1569*bb4ee6a4SAndroid Build Coastguard Worker         // These match the return codes from `fsverity_ioctl_enable` in the kernel.
1570*bb4ee6a4SAndroid Build Coastguard Worker         match inode_data.filetype {
1571*bb4ee6a4SAndroid Build Coastguard Worker             FileType::Regular => {}
1572*bb4ee6a4SAndroid Build Coastguard Worker             FileType::Directory => return Err(io::Error::from_raw_os_error(libc::EISDIR)),
1573*bb4ee6a4SAndroid Build Coastguard Worker             FileType::Other => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
1574*bb4ee6a4SAndroid Build Coastguard Worker         }
1575*bb4ee6a4SAndroid Build Coastguard Worker 
1576*bb4ee6a4SAndroid Build Coastguard Worker         {
1577*bb4ee6a4SAndroid Build Coastguard Worker             // We cannot enable verity while holding a writable fd so get a new one, if necessary.
1578*bb4ee6a4SAndroid Build Coastguard Worker             let mut file = inode_data.file.lock();
1579*bb4ee6a4SAndroid Build Coastguard Worker             let mut flags = file.1;
1580*bb4ee6a4SAndroid Build Coastguard Worker             match flags & libc::O_ACCMODE {
1581*bb4ee6a4SAndroid Build Coastguard Worker                 libc::O_WRONLY | libc::O_RDWR => {
1582*bb4ee6a4SAndroid Build Coastguard Worker                     flags &= !libc::O_ACCMODE;
1583*bb4ee6a4SAndroid Build Coastguard Worker                     flags |= libc::O_RDONLY;
1584*bb4ee6a4SAndroid Build Coastguard Worker 
1585*bb4ee6a4SAndroid Build Coastguard Worker                     // We need to get a read-only handle for this file.
1586*bb4ee6a4SAndroid Build Coastguard Worker                     let newfile = self.open_fd(file.0.as_raw_descriptor(), libc::O_RDONLY)?;
1587*bb4ee6a4SAndroid Build Coastguard Worker                     *file = (newfile, flags);
1588*bb4ee6a4SAndroid Build Coastguard Worker                 }
1589*bb4ee6a4SAndroid Build Coastguard Worker                 libc::O_RDONLY => {}
1590*bb4ee6a4SAndroid Build Coastguard Worker                 _ => panic!("Unexpected flags: {:#x}", flags),
1591*bb4ee6a4SAndroid Build Coastguard Worker             }
1592*bb4ee6a4SAndroid Build Coastguard Worker         }
1593*bb4ee6a4SAndroid Build Coastguard Worker 
1594*bb4ee6a4SAndroid Build Coastguard Worker         let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
1595*bb4ee6a4SAndroid Build Coastguard Worker             inode_data
1596*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1597*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_handle(handle, inode)?;
1598*bb4ee6a4SAndroid Build Coastguard Worker 
1599*bb4ee6a4SAndroid Build Coastguard Worker             {
1600*bb4ee6a4SAndroid Build Coastguard Worker                 // We can't enable verity while holding a writable fd. We don't know whether the
1601*bb4ee6a4SAndroid Build Coastguard Worker                 // file was opened for writing so check it here. We don't expect
1602*bb4ee6a4SAndroid Build Coastguard Worker                 // this to be a frequent operation so the extra latency should be
1603*bb4ee6a4SAndroid Build Coastguard Worker                 // fine.
1604*bb4ee6a4SAndroid Build Coastguard Worker                 let mut file = data.file.lock();
1605*bb4ee6a4SAndroid Build Coastguard Worker                 let flags = FileFlags::from_file(&*file).map_err(io::Error::from)?;
1606*bb4ee6a4SAndroid Build Coastguard Worker                 match flags {
1607*bb4ee6a4SAndroid Build Coastguard Worker                     FileFlags::ReadWrite | FileFlags::Write => {
1608*bb4ee6a4SAndroid Build Coastguard Worker                         // We need to get a read-only handle for this file.
1609*bb4ee6a4SAndroid Build Coastguard Worker                         *file = self.open_fd(file.as_raw_descriptor(), libc::O_RDONLY)?;
1610*bb4ee6a4SAndroid Build Coastguard Worker                     }
1611*bb4ee6a4SAndroid Build Coastguard Worker                     FileFlags::Read => {}
1612*bb4ee6a4SAndroid Build Coastguard Worker                 }
1613*bb4ee6a4SAndroid Build Coastguard Worker             }
1614*bb4ee6a4SAndroid Build Coastguard Worker 
1615*bb4ee6a4SAndroid Build Coastguard Worker             data
1616*bb4ee6a4SAndroid Build Coastguard Worker         };
1617*bb4ee6a4SAndroid Build Coastguard Worker 
1618*bb4ee6a4SAndroid Build Coastguard Worker         let mut arg = fsverity_enable_arg::new_zeroed();
1619*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(arg.as_bytes_mut())?;
1620*bb4ee6a4SAndroid Build Coastguard Worker 
1621*bb4ee6a4SAndroid Build Coastguard Worker         let mut salt;
1622*bb4ee6a4SAndroid Build Coastguard Worker         if arg.salt_size > 0 {
1623*bb4ee6a4SAndroid Build Coastguard Worker             if arg.salt_size > self.max_buffer_size() {
1624*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(IoctlReply::Done(Err(io::Error::from_raw_os_error(
1625*bb4ee6a4SAndroid Build Coastguard Worker                     libc::ENOMEM,
1626*bb4ee6a4SAndroid Build Coastguard Worker                 ))));
1627*bb4ee6a4SAndroid Build Coastguard Worker             }
1628*bb4ee6a4SAndroid Build Coastguard Worker             salt = vec![0; arg.salt_size as usize];
1629*bb4ee6a4SAndroid Build Coastguard Worker             r.read_exact(&mut salt)?;
1630*bb4ee6a4SAndroid Build Coastguard Worker             arg.salt_ptr = salt.as_ptr() as usize as u64;
1631*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1632*bb4ee6a4SAndroid Build Coastguard Worker             arg.salt_ptr = 0;
1633*bb4ee6a4SAndroid Build Coastguard Worker         }
1634*bb4ee6a4SAndroid Build Coastguard Worker 
1635*bb4ee6a4SAndroid Build Coastguard Worker         let mut sig;
1636*bb4ee6a4SAndroid Build Coastguard Worker         if arg.sig_size > 0 {
1637*bb4ee6a4SAndroid Build Coastguard Worker             if arg.sig_size > self.max_buffer_size() {
1638*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(IoctlReply::Done(Err(io::Error::from_raw_os_error(
1639*bb4ee6a4SAndroid Build Coastguard Worker                     libc::ENOMEM,
1640*bb4ee6a4SAndroid Build Coastguard Worker                 ))));
1641*bb4ee6a4SAndroid Build Coastguard Worker             }
1642*bb4ee6a4SAndroid Build Coastguard Worker             sig = vec![0; arg.sig_size as usize];
1643*bb4ee6a4SAndroid Build Coastguard Worker             r.read_exact(&mut sig)?;
1644*bb4ee6a4SAndroid Build Coastguard Worker             arg.sig_ptr = sig.as_ptr() as usize as u64;
1645*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1646*bb4ee6a4SAndroid Build Coastguard Worker             arg.sig_ptr = 0;
1647*bb4ee6a4SAndroid Build Coastguard Worker         }
1648*bb4ee6a4SAndroid Build Coastguard Worker 
1649*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value.
1650*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe { ioctl_with_ptr(&*data, FS_IOC_ENABLE_VERITY, &arg) };
1651*bb4ee6a4SAndroid Build Coastguard Worker         if res < 0 {
1652*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Err(io::Error::last_os_error())))
1653*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1654*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Ok(Vec::new())))
1655*bb4ee6a4SAndroid Build Coastguard Worker         }
1656*bb4ee6a4SAndroid Build Coastguard Worker     }
1657*bb4ee6a4SAndroid Build Coastguard Worker 
measure_verity<R: io::Read>( &self, inode: Inode, handle: Handle, mut r: R, out_size: u32, ) -> io::Result<IoctlReply>1658*bb4ee6a4SAndroid Build Coastguard Worker     fn measure_verity<R: io::Read>(
1659*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1660*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
1661*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
1662*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1663*bb4ee6a4SAndroid Build Coastguard Worker         out_size: u32,
1664*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<IoctlReply> {
1665*bb4ee6a4SAndroid Build Coastguard Worker         let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
1666*bb4ee6a4SAndroid Build Coastguard Worker             self.find_inode(inode)?
1667*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1668*bb4ee6a4SAndroid Build Coastguard Worker             self.find_handle(handle, inode)?
1669*bb4ee6a4SAndroid Build Coastguard Worker         };
1670*bb4ee6a4SAndroid Build Coastguard Worker 
1671*bb4ee6a4SAndroid Build Coastguard Worker         let mut digest = fsverity_digest::new_zeroed();
1672*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(digest.as_bytes_mut())?;
1673*bb4ee6a4SAndroid Build Coastguard Worker 
1674*bb4ee6a4SAndroid Build Coastguard Worker         // Taken from fs/verity/fsverity_private.h.
1675*bb4ee6a4SAndroid Build Coastguard Worker         const FS_VERITY_MAX_DIGEST_SIZE: u16 = 64;
1676*bb4ee6a4SAndroid Build Coastguard Worker 
1677*bb4ee6a4SAndroid Build Coastguard Worker         // This digest size is what the fsverity command line utility uses.
1678*bb4ee6a4SAndroid Build Coastguard Worker         const DIGEST_SIZE: u16 = FS_VERITY_MAX_DIGEST_SIZE * 2 + 1;
1679*bb4ee6a4SAndroid Build Coastguard Worker         const BUFLEN: usize = size_of::<fsverity_digest>() + DIGEST_SIZE as usize;
1680*bb4ee6a4SAndroid Build Coastguard Worker         const ROUNDED_LEN: usize =
1681*bb4ee6a4SAndroid Build Coastguard Worker             (BUFLEN + size_of::<fsverity_digest>() - 1) / size_of::<fsverity_digest>();
1682*bb4ee6a4SAndroid Build Coastguard Worker 
1683*bb4ee6a4SAndroid Build Coastguard Worker         // Make sure we get a properly aligned allocation.
1684*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = [MaybeUninit::<fsverity_digest>::uninit(); ROUNDED_LEN];
1685*bb4ee6a4SAndroid Build Coastguard Worker 
1686*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: we are only writing data and not reading uninitialized memory.
1687*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
1688*bb4ee6a4SAndroid Build Coastguard Worker             // TODO: Replace with `MaybeUninit::slice_as_mut_ptr` once it is stabilized.
1689*bb4ee6a4SAndroid Build Coastguard Worker             addr_of_mut!((*(buf.as_mut_ptr() as *mut fsverity_digest)).digest_size)
1690*bb4ee6a4SAndroid Build Coastguard Worker                 .write(DIGEST_SIZE)
1691*bb4ee6a4SAndroid Build Coastguard Worker         };
1692*bb4ee6a4SAndroid Build Coastguard Worker 
1693*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this will only modify `buf` and we check the return value.
1694*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe { ioctl_with_mut_ptr(&*data, FS_IOC_MEASURE_VERITY, buf.as_mut_ptr()) };
1695*bb4ee6a4SAndroid Build Coastguard Worker         if res < 0 {
1696*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Err(io::Error::last_os_error())))
1697*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1698*bb4ee6a4SAndroid Build Coastguard Worker             let digest_size =
1699*bb4ee6a4SAndroid Build Coastguard Worker                 // SAFETY: this value was initialized by us already and then overwritten by the kernel.
1700*bb4ee6a4SAndroid Build Coastguard Worker                 // TODO: Replace with `MaybeUninit::slice_as_ptr` once it is stabilized.
1701*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe { addr_of!((*(buf.as_ptr() as *const fsverity_digest)).digest_size).read() };
1702*bb4ee6a4SAndroid Build Coastguard Worker             let outlen = size_of::<fsverity_digest>() as u32 + u32::from(digest_size);
1703*bb4ee6a4SAndroid Build Coastguard Worker 
1704*bb4ee6a4SAndroid Build Coastguard Worker             // The kernel guarantees this but it doesn't hurt to be paranoid.
1705*bb4ee6a4SAndroid Build Coastguard Worker             debug_assert!(outlen <= (ROUNDED_LEN * size_of::<fsverity_digest>()) as u32);
1706*bb4ee6a4SAndroid Build Coastguard Worker             if digest.digest_size < digest_size || out_size < outlen {
1707*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(IoctlReply::Done(Err(io::Error::from_raw_os_error(
1708*bb4ee6a4SAndroid Build Coastguard Worker                     libc::EOVERFLOW,
1709*bb4ee6a4SAndroid Build Coastguard Worker                 ))));
1710*bb4ee6a4SAndroid Build Coastguard Worker             }
1711*bb4ee6a4SAndroid Build Coastguard Worker 
1712*bb4ee6a4SAndroid Build Coastguard Worker             let buf: [MaybeUninit<u8>; ROUNDED_LEN * size_of::<fsverity_digest>()] =
1713*bb4ee6a4SAndroid Build Coastguard Worker                 // SAFETY: any bit pattern is valid for `MaybeUninit<u8>` and `fsverity_digest`
1714*bb4ee6a4SAndroid Build Coastguard Worker                 // doesn't contain any references.
1715*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe { mem::transmute(buf) };
1716*bb4ee6a4SAndroid Build Coastguard Worker 
1717*bb4ee6a4SAndroid Build Coastguard Worker             let buf =
1718*bb4ee6a4SAndroid Build Coastguard Worker                 // SAFETY: Casting to `*const [u8]` is safe because the kernel guarantees that the
1719*bb4ee6a4SAndroid Build Coastguard Worker                 // first `outlen` bytes of `buf` are initialized and `MaybeUninit<u8>` is guaranteed
1720*bb4ee6a4SAndroid Build Coastguard Worker                 // to have the same layout as `u8`.
1721*bb4ee6a4SAndroid Build Coastguard Worker                 // TODO: Replace with `MaybeUninit::slice_assume_init_ref` once it is stabilized.
1722*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe { &*(&buf[..outlen as usize] as *const [MaybeUninit<u8>] as *const [u8]) };
1723*bb4ee6a4SAndroid Build Coastguard Worker             Ok(IoctlReply::Done(Ok(buf.to_vec())))
1724*bb4ee6a4SAndroid Build Coastguard Worker         }
1725*bb4ee6a4SAndroid Build Coastguard Worker     }
1726*bb4ee6a4SAndroid Build Coastguard Worker }
1727*bb4ee6a4SAndroid Build Coastguard Worker 
1728*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "fs_runtime_ugid_map")]
1729*bb4ee6a4SAndroid Build Coastguard Worker impl PassthroughFs {
find_and_set_ugid_permission( &self, st: &mut libc::stat64, path: &str, is_root_path: bool, ) -> bool1730*bb4ee6a4SAndroid Build Coastguard Worker     fn find_and_set_ugid_permission(
1731*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1732*bb4ee6a4SAndroid Build Coastguard Worker         st: &mut libc::stat64,
1733*bb4ee6a4SAndroid Build Coastguard Worker         path: &str,
1734*bb4ee6a4SAndroid Build Coastguard Worker         is_root_path: bool,
1735*bb4ee6a4SAndroid Build Coastguard Worker     ) -> bool {
1736*bb4ee6a4SAndroid Build Coastguard Worker         for perm_data in self
1737*bb4ee6a4SAndroid Build Coastguard Worker             .permission_paths
1738*bb4ee6a4SAndroid Build Coastguard Worker             .read()
1739*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire permission_paths read lock")
1740*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1741*bb4ee6a4SAndroid Build Coastguard Worker         {
1742*bb4ee6a4SAndroid Build Coastguard Worker             if (is_root_path && perm_data.perm_path == "/")
1743*bb4ee6a4SAndroid Build Coastguard Worker                 || (!is_root_path
1744*bb4ee6a4SAndroid Build Coastguard Worker                     && perm_data.perm_path != "/"
1745*bb4ee6a4SAndroid Build Coastguard Worker                     && perm_data.need_set_permission(path))
1746*bb4ee6a4SAndroid Build Coastguard Worker             {
1747*bb4ee6a4SAndroid Build Coastguard Worker                 self.set_permission_from_data(st, perm_data);
1748*bb4ee6a4SAndroid Build Coastguard Worker                 return true;
1749*bb4ee6a4SAndroid Build Coastguard Worker             }
1750*bb4ee6a4SAndroid Build Coastguard Worker         }
1751*bb4ee6a4SAndroid Build Coastguard Worker         false
1752*bb4ee6a4SAndroid Build Coastguard Worker     }
1753*bb4ee6a4SAndroid Build Coastguard Worker 
set_permission_from_data(&self, st: &mut libc::stat64, perm_data: &PermissionData)1754*bb4ee6a4SAndroid Build Coastguard Worker     fn set_permission_from_data(&self, st: &mut libc::stat64, perm_data: &PermissionData) {
1755*bb4ee6a4SAndroid Build Coastguard Worker         st.st_uid = perm_data.guest_uid;
1756*bb4ee6a4SAndroid Build Coastguard Worker         st.st_gid = perm_data.guest_gid;
1757*bb4ee6a4SAndroid Build Coastguard Worker         st.st_mode = (st.st_mode & libc::S_IFMT) | (0o777 & !perm_data.umask);
1758*bb4ee6a4SAndroid Build Coastguard Worker     }
1759*bb4ee6a4SAndroid Build Coastguard Worker 
1760*bb4ee6a4SAndroid Build Coastguard Worker     /// Set permission according to path
set_ugid_permission(&self, st: &mut libc::stat64, path: &str)1761*bb4ee6a4SAndroid Build Coastguard Worker     fn set_ugid_permission(&self, st: &mut libc::stat64, path: &str) {
1762*bb4ee6a4SAndroid Build Coastguard Worker         let is_root_path = path.is_empty();
1763*bb4ee6a4SAndroid Build Coastguard Worker 
1764*bb4ee6a4SAndroid Build Coastguard Worker         if self.find_and_set_ugid_permission(st, path, is_root_path) {
1765*bb4ee6a4SAndroid Build Coastguard Worker             return;
1766*bb4ee6a4SAndroid Build Coastguard Worker         }
1767*bb4ee6a4SAndroid Build Coastguard Worker 
1768*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(perm_data) = self
1769*bb4ee6a4SAndroid Build Coastguard Worker             .permission_paths
1770*bb4ee6a4SAndroid Build Coastguard Worker             .read()
1771*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire permission_paths read lock")
1772*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1773*bb4ee6a4SAndroid Build Coastguard Worker             .find(|pd| pd.perm_path == "/")
1774*bb4ee6a4SAndroid Build Coastguard Worker         {
1775*bb4ee6a4SAndroid Build Coastguard Worker             self.set_permission_from_data(st, perm_data);
1776*bb4ee6a4SAndroid Build Coastguard Worker         }
1777*bb4ee6a4SAndroid Build Coastguard Worker     }
1778*bb4ee6a4SAndroid Build Coastguard Worker 
1779*bb4ee6a4SAndroid Build Coastguard Worker     /// Set host uid/gid to configured value according to path
change_ugid_creds(&self, ctx: &Context, parent_data: &InodeData, name: &CStr) -> (u32, u32)1780*bb4ee6a4SAndroid Build Coastguard Worker     fn change_ugid_creds(&self, ctx: &Context, parent_data: &InodeData, name: &CStr) -> (u32, u32) {
1781*bb4ee6a4SAndroid Build Coastguard Worker         let path = format!(
1782*bb4ee6a4SAndroid Build Coastguard Worker             "{}/{}",
1783*bb4ee6a4SAndroid Build Coastguard Worker             parent_data.path.clone(),
1784*bb4ee6a4SAndroid Build Coastguard Worker             name.to_str().unwrap_or("<non UTF-8 str>")
1785*bb4ee6a4SAndroid Build Coastguard Worker         );
1786*bb4ee6a4SAndroid Build Coastguard Worker 
1787*bb4ee6a4SAndroid Build Coastguard Worker         let is_root_path = path.is_empty();
1788*bb4ee6a4SAndroid Build Coastguard Worker 
1789*bb4ee6a4SAndroid Build Coastguard Worker         if self.find_ugid_creds_for_path(&path, is_root_path).is_some() {
1790*bb4ee6a4SAndroid Build Coastguard Worker             return self.find_ugid_creds_for_path(&path, is_root_path).unwrap();
1791*bb4ee6a4SAndroid Build Coastguard Worker         }
1792*bb4ee6a4SAndroid Build Coastguard Worker 
1793*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(perm_data) = self
1794*bb4ee6a4SAndroid Build Coastguard Worker             .permission_paths
1795*bb4ee6a4SAndroid Build Coastguard Worker             .read()
1796*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire permission_paths read lock")
1797*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1798*bb4ee6a4SAndroid Build Coastguard Worker             .find(|pd| pd.perm_path == "/")
1799*bb4ee6a4SAndroid Build Coastguard Worker         {
1800*bb4ee6a4SAndroid Build Coastguard Worker             return (perm_data.host_uid, perm_data.host_gid);
1801*bb4ee6a4SAndroid Build Coastguard Worker         }
1802*bb4ee6a4SAndroid Build Coastguard Worker 
1803*bb4ee6a4SAndroid Build Coastguard Worker         (ctx.uid, ctx.gid)
1804*bb4ee6a4SAndroid Build Coastguard Worker     }
1805*bb4ee6a4SAndroid Build Coastguard Worker 
find_ugid_creds_for_path(&self, path: &str, is_root_path: bool) -> Option<(u32, u32)>1806*bb4ee6a4SAndroid Build Coastguard Worker     fn find_ugid_creds_for_path(&self, path: &str, is_root_path: bool) -> Option<(u32, u32)> {
1807*bb4ee6a4SAndroid Build Coastguard Worker         for perm_data in self
1808*bb4ee6a4SAndroid Build Coastguard Worker             .permission_paths
1809*bb4ee6a4SAndroid Build Coastguard Worker             .read()
1810*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire permission_paths read lock")
1811*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1812*bb4ee6a4SAndroid Build Coastguard Worker         {
1813*bb4ee6a4SAndroid Build Coastguard Worker             if (is_root_path && perm_data.perm_path == "/")
1814*bb4ee6a4SAndroid Build Coastguard Worker                 || (!is_root_path
1815*bb4ee6a4SAndroid Build Coastguard Worker                     && perm_data.perm_path != "/"
1816*bb4ee6a4SAndroid Build Coastguard Worker                     && perm_data.need_set_permission(path))
1817*bb4ee6a4SAndroid Build Coastguard Worker             {
1818*bb4ee6a4SAndroid Build Coastguard Worker                 return Some((perm_data.host_uid, perm_data.host_gid));
1819*bb4ee6a4SAndroid Build Coastguard Worker             }
1820*bb4ee6a4SAndroid Build Coastguard Worker         }
1821*bb4ee6a4SAndroid Build Coastguard Worker         None
1822*bb4ee6a4SAndroid Build Coastguard Worker     }
1823*bb4ee6a4SAndroid Build Coastguard Worker }
1824*bb4ee6a4SAndroid Build Coastguard Worker 
1825*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "arc_quota")]
1826*bb4ee6a4SAndroid Build Coastguard Worker impl PassthroughFs {
1827*bb4ee6a4SAndroid Build Coastguard Worker     /// Convert u8 slice to string
string_from_u8_slice(&self, buf: &[u8]) -> io::Result<String>1828*bb4ee6a4SAndroid Build Coastguard Worker     fn string_from_u8_slice(&self, buf: &[u8]) -> io::Result<String> {
1829*bb4ee6a4SAndroid Build Coastguard Worker         match CStr::from_bytes_until_nul(buf).map(|s| s.to_string_lossy().to_string()) {
1830*bb4ee6a4SAndroid Build Coastguard Worker             Ok(s) => Ok(s),
1831*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
1832*bb4ee6a4SAndroid Build Coastguard Worker                 error!("fail to convert u8 slice to string: {}", e);
1833*bb4ee6a4SAndroid Build Coastguard Worker                 Err(io::Error::from_raw_os_error(libc::EINVAL))
1834*bb4ee6a4SAndroid Build Coastguard Worker             }
1835*bb4ee6a4SAndroid Build Coastguard Worker         }
1836*bb4ee6a4SAndroid Build Coastguard Worker     }
1837*bb4ee6a4SAndroid Build Coastguard Worker 
1838*bb4ee6a4SAndroid Build Coastguard Worker     /// Set permission according to path
set_permission(&self, st: &mut libc::stat64, path: &str)1839*bb4ee6a4SAndroid Build Coastguard Worker     fn set_permission(&self, st: &mut libc::stat64, path: &str) {
1840*bb4ee6a4SAndroid Build Coastguard Worker         for perm_data in self
1841*bb4ee6a4SAndroid Build Coastguard Worker             .permission_paths
1842*bb4ee6a4SAndroid Build Coastguard Worker             .read()
1843*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire permission_paths read lock")
1844*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1845*bb4ee6a4SAndroid Build Coastguard Worker         {
1846*bb4ee6a4SAndroid Build Coastguard Worker             if perm_data.need_set_permission(path) {
1847*bb4ee6a4SAndroid Build Coastguard Worker                 st.st_uid = perm_data.guest_uid;
1848*bb4ee6a4SAndroid Build Coastguard Worker                 st.st_gid = perm_data.guest_gid;
1849*bb4ee6a4SAndroid Build Coastguard Worker                 st.st_mode = (st.st_mode & libc::S_IFMT) | (0o777 & !perm_data.umask);
1850*bb4ee6a4SAndroid Build Coastguard Worker             }
1851*bb4ee6a4SAndroid Build Coastguard Worker         }
1852*bb4ee6a4SAndroid Build Coastguard Worker     }
1853*bb4ee6a4SAndroid Build Coastguard Worker 
1854*bb4ee6a4SAndroid Build Coastguard Worker     /// Set host uid/gid to configured value according to path
change_creds(&self, ctx: &Context, parent_data: &InodeData, name: &CStr) -> (u32, u32)1855*bb4ee6a4SAndroid Build Coastguard Worker     fn change_creds(&self, ctx: &Context, parent_data: &InodeData, name: &CStr) -> (u32, u32) {
1856*bb4ee6a4SAndroid Build Coastguard Worker         let path = format!(
1857*bb4ee6a4SAndroid Build Coastguard Worker             "{}/{}",
1858*bb4ee6a4SAndroid Build Coastguard Worker             parent_data.path.clone(),
1859*bb4ee6a4SAndroid Build Coastguard Worker             name.to_str().unwrap_or("<non UTF-8 str>")
1860*bb4ee6a4SAndroid Build Coastguard Worker         );
1861*bb4ee6a4SAndroid Build Coastguard Worker 
1862*bb4ee6a4SAndroid Build Coastguard Worker         for perm_data in self
1863*bb4ee6a4SAndroid Build Coastguard Worker             .permission_paths
1864*bb4ee6a4SAndroid Build Coastguard Worker             .read()
1865*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire permission_paths read lock")
1866*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1867*bb4ee6a4SAndroid Build Coastguard Worker         {
1868*bb4ee6a4SAndroid Build Coastguard Worker             if perm_data.need_set_permission(&path) {
1869*bb4ee6a4SAndroid Build Coastguard Worker                 return (perm_data.host_uid, perm_data.host_gid);
1870*bb4ee6a4SAndroid Build Coastguard Worker             }
1871*bb4ee6a4SAndroid Build Coastguard Worker         }
1872*bb4ee6a4SAndroid Build Coastguard Worker 
1873*bb4ee6a4SAndroid Build Coastguard Worker         (ctx.uid, ctx.gid)
1874*bb4ee6a4SAndroid Build Coastguard Worker     }
1875*bb4ee6a4SAndroid Build Coastguard Worker 
read_permission_data<R: io::Read>(&self, mut r: R) -> io::Result<PermissionData>1876*bb4ee6a4SAndroid Build Coastguard Worker     fn read_permission_data<R: io::Read>(&self, mut r: R) -> io::Result<PermissionData> {
1877*bb4ee6a4SAndroid Build Coastguard Worker         let mut fs_permission_data = FsPermissionDataBuffer::new_zeroed();
1878*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(fs_permission_data.as_bytes_mut())?;
1879*bb4ee6a4SAndroid Build Coastguard Worker 
1880*bb4ee6a4SAndroid Build Coastguard Worker         let perm_path = self.string_from_u8_slice(&fs_permission_data.perm_path)?;
1881*bb4ee6a4SAndroid Build Coastguard Worker         if !perm_path.starts_with('/') {
1882*bb4ee6a4SAndroid Build Coastguard Worker             error!("FS_IOC_SETPERMISSION: perm path must start with '/'");
1883*bb4ee6a4SAndroid Build Coastguard Worker             return Err(io::Error::from_raw_os_error(libc::EINVAL));
1884*bb4ee6a4SAndroid Build Coastguard Worker         }
1885*bb4ee6a4SAndroid Build Coastguard Worker         Ok(PermissionData {
1886*bb4ee6a4SAndroid Build Coastguard Worker             guest_uid: fs_permission_data.guest_uid,
1887*bb4ee6a4SAndroid Build Coastguard Worker             guest_gid: fs_permission_data.guest_gid,
1888*bb4ee6a4SAndroid Build Coastguard Worker             host_uid: fs_permission_data.host_uid,
1889*bb4ee6a4SAndroid Build Coastguard Worker             host_gid: fs_permission_data.host_gid,
1890*bb4ee6a4SAndroid Build Coastguard Worker             umask: fs_permission_data.umask,
1891*bb4ee6a4SAndroid Build Coastguard Worker             perm_path,
1892*bb4ee6a4SAndroid Build Coastguard Worker         })
1893*bb4ee6a4SAndroid Build Coastguard Worker     }
1894*bb4ee6a4SAndroid Build Coastguard Worker 
1895*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets uid/gid/umask for all files and directories under a specific path.
1896*bb4ee6a4SAndroid Build Coastguard Worker     ///
1897*bb4ee6a4SAndroid Build Coastguard Worker     /// This ioctl does not correspond to any upstream FUSE feature. It is used for arcvm
1898*bb4ee6a4SAndroid Build Coastguard Worker     /// It associates the specified path with the provide uid, gid, and umask values within the
1899*bb4ee6a4SAndroid Build Coastguard Worker     /// filesystem metadata.
1900*bb4ee6a4SAndroid Build Coastguard Worker     ///
1901*bb4ee6a4SAndroid Build Coastguard Worker     /// During subsequent lookup operations, the stored uid/gid/umask values are retrieved and
1902*bb4ee6a4SAndroid Build Coastguard Worker     /// applied to all files and directories found under the registered path. Before sending
1903*bb4ee6a4SAndroid Build Coastguard Worker     /// file stat information to the client, the uid and gid are substituted by `guest_uid` and
1904*bb4ee6a4SAndroid Build Coastguard Worker     /// `guest_gid` if the file falls under the registered path. The file mode is masked by the
1905*bb4ee6a4SAndroid Build Coastguard Worker     ///  umask.
1906*bb4ee6a4SAndroid Build Coastguard Worker     ///
1907*bb4ee6a4SAndroid Build Coastguard Worker     /// When the guest creates a file within the specified path, the file gid/uid stat in host
1908*bb4ee6a4SAndroid Build Coastguard Worker     /// will be overwritten to `host_uid` and `host_gid` values.
1909*bb4ee6a4SAndroid Build Coastguard Worker     ///
1910*bb4ee6a4SAndroid Build Coastguard Worker     /// This functionality enables dynamic configuration of ownership and permissions for a
1911*bb4ee6a4SAndroid Build Coastguard Worker     /// specific directory hierarchy within the filesystem.
1912*bb4ee6a4SAndroid Build Coastguard Worker     ///
1913*bb4ee6a4SAndroid Build Coastguard Worker     /// # Notes
1914*bb4ee6a4SAndroid Build Coastguard Worker     /// - This method affects all existing and future files under the registered path.
1915*bb4ee6a4SAndroid Build Coastguard Worker     /// - The original file ownership and permissions are overridden by the provided values.
1916*bb4ee6a4SAndroid Build Coastguard Worker     /// - The registered path should not be renamed
1917*bb4ee6a4SAndroid Build Coastguard Worker     /// - Refer go/remove-mount-passthrough-fuse for more design details
set_permission_by_path<R: io::Read>(&self, r: R) -> IoctlReply1918*bb4ee6a4SAndroid Build Coastguard Worker     fn set_permission_by_path<R: io::Read>(&self, r: R) -> IoctlReply {
1919*bb4ee6a4SAndroid Build Coastguard Worker         if self
1920*bb4ee6a4SAndroid Build Coastguard Worker             .permission_paths
1921*bb4ee6a4SAndroid Build Coastguard Worker             .read()
1922*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire permission_paths read lock")
1923*bb4ee6a4SAndroid Build Coastguard Worker             .len()
1924*bb4ee6a4SAndroid Build Coastguard Worker             >= self.cfg.max_dynamic_perm
1925*bb4ee6a4SAndroid Build Coastguard Worker         {
1926*bb4ee6a4SAndroid Build Coastguard Worker             error!(
1927*bb4ee6a4SAndroid Build Coastguard Worker                 "FS_IOC_SETPERMISSION exceeds limits of max_dynamic_perm: {}",
1928*bb4ee6a4SAndroid Build Coastguard Worker                 self.cfg.max_dynamic_perm
1929*bb4ee6a4SAndroid Build Coastguard Worker             );
1930*bb4ee6a4SAndroid Build Coastguard Worker             return IoctlReply::Done(Err(io::Error::from_raw_os_error(libc::EPERM)));
1931*bb4ee6a4SAndroid Build Coastguard Worker         }
1932*bb4ee6a4SAndroid Build Coastguard Worker 
1933*bb4ee6a4SAndroid Build Coastguard Worker         let perm_data = match self.read_permission_data(r) {
1934*bb4ee6a4SAndroid Build Coastguard Worker             Ok(data) => data,
1935*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
1936*bb4ee6a4SAndroid Build Coastguard Worker                 error!("fail to read permission data: {}", e);
1937*bb4ee6a4SAndroid Build Coastguard Worker                 return IoctlReply::Done(Err(e));
1938*bb4ee6a4SAndroid Build Coastguard Worker             }
1939*bb4ee6a4SAndroid Build Coastguard Worker         };
1940*bb4ee6a4SAndroid Build Coastguard Worker 
1941*bb4ee6a4SAndroid Build Coastguard Worker         self.permission_paths
1942*bb4ee6a4SAndroid Build Coastguard Worker             .write()
1943*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire permission_paths write lock")
1944*bb4ee6a4SAndroid Build Coastguard Worker             .push(perm_data);
1945*bb4ee6a4SAndroid Build Coastguard Worker 
1946*bb4ee6a4SAndroid Build Coastguard Worker         IoctlReply::Done(Ok(Vec::new()))
1947*bb4ee6a4SAndroid Build Coastguard Worker     }
1948*bb4ee6a4SAndroid Build Coastguard Worker 
1949*bb4ee6a4SAndroid Build Coastguard Worker     // Get xattr value according to path and name
get_xattr_by_path(&self, path: &str, name: &str) -> Option<String>1950*bb4ee6a4SAndroid Build Coastguard Worker     fn get_xattr_by_path(&self, path: &str, name: &str) -> Option<String> {
1951*bb4ee6a4SAndroid Build Coastguard Worker         self.xattr_paths
1952*bb4ee6a4SAndroid Build Coastguard Worker             .read()
1953*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire permission_paths read lock")
1954*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
1955*bb4ee6a4SAndroid Build Coastguard Worker             .find(|data| data.need_set_guest_xattr(path, name))
1956*bb4ee6a4SAndroid Build Coastguard Worker             .map(|data| data.xattr_value.clone())
1957*bb4ee6a4SAndroid Build Coastguard Worker     }
1958*bb4ee6a4SAndroid Build Coastguard Worker 
skip_host_set_xattr(&self, path: &str, name: &str) -> bool1959*bb4ee6a4SAndroid Build Coastguard Worker     fn skip_host_set_xattr(&self, path: &str, name: &str) -> bool {
1960*bb4ee6a4SAndroid Build Coastguard Worker         self.get_xattr_by_path(path, name).is_some()
1961*bb4ee6a4SAndroid Build Coastguard Worker     }
1962*bb4ee6a4SAndroid Build Coastguard Worker 
read_xattr_data<R: io::Read>(&self, mut r: R) -> io::Result<XattrData>1963*bb4ee6a4SAndroid Build Coastguard Worker     fn read_xattr_data<R: io::Read>(&self, mut r: R) -> io::Result<XattrData> {
1964*bb4ee6a4SAndroid Build Coastguard Worker         let mut fs_path_xattr_data = FsPathXattrDataBuffer::new_zeroed();
1965*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(fs_path_xattr_data.as_bytes_mut())?;
1966*bb4ee6a4SAndroid Build Coastguard Worker 
1967*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_path = self.string_from_u8_slice(&fs_path_xattr_data.path)?;
1968*bb4ee6a4SAndroid Build Coastguard Worker         if !xattr_path.starts_with('/') {
1969*bb4ee6a4SAndroid Build Coastguard Worker             error!("FS_IOC_SETPATHXATTR: perm path must start with '/'");
1970*bb4ee6a4SAndroid Build Coastguard Worker             return Err(io::Error::from_raw_os_error(libc::EINVAL));
1971*bb4ee6a4SAndroid Build Coastguard Worker         }
1972*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_name = self.string_from_u8_slice(&fs_path_xattr_data.xattr_name)?;
1973*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_value = self.string_from_u8_slice(&fs_path_xattr_data.xattr_value)?;
1974*bb4ee6a4SAndroid Build Coastguard Worker 
1975*bb4ee6a4SAndroid Build Coastguard Worker         Ok(XattrData {
1976*bb4ee6a4SAndroid Build Coastguard Worker             xattr_path,
1977*bb4ee6a4SAndroid Build Coastguard Worker             xattr_name,
1978*bb4ee6a4SAndroid Build Coastguard Worker             xattr_value,
1979*bb4ee6a4SAndroid Build Coastguard Worker         })
1980*bb4ee6a4SAndroid Build Coastguard Worker     }
1981*bb4ee6a4SAndroid Build Coastguard Worker 
1982*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets xattr value for all files and directories under a specific path.
1983*bb4ee6a4SAndroid Build Coastguard Worker     ///
1984*bb4ee6a4SAndroid Build Coastguard Worker     /// This ioctl does not correspond to any upstream FUSE feature. It is used for arcvm.
1985*bb4ee6a4SAndroid Build Coastguard Worker     /// It associates the specified path and xattr name with a value.
1986*bb4ee6a4SAndroid Build Coastguard Worker     ///
1987*bb4ee6a4SAndroid Build Coastguard Worker     /// When the getxattr is called for the specified path and name, the predefined
1988*bb4ee6a4SAndroid Build Coastguard Worker     /// value is returned.
1989*bb4ee6a4SAndroid Build Coastguard Worker     ///
1990*bb4ee6a4SAndroid Build Coastguard Worker     /// # Notes
1991*bb4ee6a4SAndroid Build Coastguard Worker     /// - This method affects all existing and future files under the registered path.
1992*bb4ee6a4SAndroid Build Coastguard Worker     /// - The SECURITY_CONTEXT feature will be disabled if this ioctl is enabled.
1993*bb4ee6a4SAndroid Build Coastguard Worker     /// - The registered path should not be renamed
1994*bb4ee6a4SAndroid Build Coastguard Worker     /// - Refer go/remove-mount-passthrough-fuse for more design details
set_xattr_by_path<R: io::Read>(&self, r: R) -> IoctlReply1995*bb4ee6a4SAndroid Build Coastguard Worker     fn set_xattr_by_path<R: io::Read>(&self, r: R) -> IoctlReply {
1996*bb4ee6a4SAndroid Build Coastguard Worker         if self
1997*bb4ee6a4SAndroid Build Coastguard Worker             .xattr_paths
1998*bb4ee6a4SAndroid Build Coastguard Worker             .read()
1999*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire xattr_paths read lock")
2000*bb4ee6a4SAndroid Build Coastguard Worker             .len()
2001*bb4ee6a4SAndroid Build Coastguard Worker             >= self.cfg.max_dynamic_xattr
2002*bb4ee6a4SAndroid Build Coastguard Worker         {
2003*bb4ee6a4SAndroid Build Coastguard Worker             error!(
2004*bb4ee6a4SAndroid Build Coastguard Worker                 "FS_IOC_SETPATHXATTR exceeds limits of max_dynamic_xattr: {}",
2005*bb4ee6a4SAndroid Build Coastguard Worker                 self.cfg.max_dynamic_xattr
2006*bb4ee6a4SAndroid Build Coastguard Worker             );
2007*bb4ee6a4SAndroid Build Coastguard Worker             return IoctlReply::Done(Err(io::Error::from_raw_os_error(libc::EPERM)));
2008*bb4ee6a4SAndroid Build Coastguard Worker         }
2009*bb4ee6a4SAndroid Build Coastguard Worker 
2010*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_data = match self.read_xattr_data(r) {
2011*bb4ee6a4SAndroid Build Coastguard Worker             Ok(data) => data,
2012*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
2013*bb4ee6a4SAndroid Build Coastguard Worker                 error!("fail to read xattr data: {}", e);
2014*bb4ee6a4SAndroid Build Coastguard Worker                 return IoctlReply::Done(Err(e));
2015*bb4ee6a4SAndroid Build Coastguard Worker             }
2016*bb4ee6a4SAndroid Build Coastguard Worker         };
2017*bb4ee6a4SAndroid Build Coastguard Worker 
2018*bb4ee6a4SAndroid Build Coastguard Worker         self.xattr_paths
2019*bb4ee6a4SAndroid Build Coastguard Worker             .write()
2020*bb4ee6a4SAndroid Build Coastguard Worker             .expect("acquire xattr_paths write lock")
2021*bb4ee6a4SAndroid Build Coastguard Worker             .push(xattr_data);
2022*bb4ee6a4SAndroid Build Coastguard Worker 
2023*bb4ee6a4SAndroid Build Coastguard Worker         IoctlReply::Done(Ok(Vec::new()))
2024*bb4ee6a4SAndroid Build Coastguard Worker     }
2025*bb4ee6a4SAndroid Build Coastguard Worker 
do_getxattr_with_filter( &self, data: Arc<InodeData>, name: Cow<CStr>, buf: &mut [u8], ) -> io::Result<usize>2026*bb4ee6a4SAndroid Build Coastguard Worker     fn do_getxattr_with_filter(
2027*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2028*bb4ee6a4SAndroid Build Coastguard Worker         data: Arc<InodeData>,
2029*bb4ee6a4SAndroid Build Coastguard Worker         name: Cow<CStr>,
2030*bb4ee6a4SAndroid Build Coastguard Worker         buf: &mut [u8],
2031*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<usize> {
2032*bb4ee6a4SAndroid Build Coastguard Worker         let res: usize = match self.get_xattr_by_path(&data.path, &name.to_string_lossy()) {
2033*bb4ee6a4SAndroid Build Coastguard Worker             Some(predifined_xattr) => {
2034*bb4ee6a4SAndroid Build Coastguard Worker                 let x = predifined_xattr.into_bytes();
2035*bb4ee6a4SAndroid Build Coastguard Worker                 if x.len() > buf.len() {
2036*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(io::Error::from_raw_os_error(libc::ERANGE));
2037*bb4ee6a4SAndroid Build Coastguard Worker                 }
2038*bb4ee6a4SAndroid Build Coastguard Worker                 buf[..x.len()].copy_from_slice(&x);
2039*bb4ee6a4SAndroid Build Coastguard Worker                 x.len()
2040*bb4ee6a4SAndroid Build Coastguard Worker             }
2041*bb4ee6a4SAndroid Build Coastguard Worker             None => self.do_getxattr(&data, &name, &mut buf[..])?,
2042*bb4ee6a4SAndroid Build Coastguard Worker         };
2043*bb4ee6a4SAndroid Build Coastguard Worker         Ok(res)
2044*bb4ee6a4SAndroid Build Coastguard Worker     }
2045*bb4ee6a4SAndroid Build Coastguard Worker }
2046*bb4ee6a4SAndroid Build Coastguard Worker 
2047*bb4ee6a4SAndroid Build Coastguard Worker /// Decrements the refcount of the inode.
2048*bb4ee6a4SAndroid Build Coastguard Worker /// Returns `true` if the refcount became 0.
forget_one( inodes: &mut MultikeyBTreeMap<Inode, InodeAltKey, Arc<InodeData>>, inode: Inode, count: u64, ) -> bool2049*bb4ee6a4SAndroid Build Coastguard Worker fn forget_one(
2050*bb4ee6a4SAndroid Build Coastguard Worker     inodes: &mut MultikeyBTreeMap<Inode, InodeAltKey, Arc<InodeData>>,
2051*bb4ee6a4SAndroid Build Coastguard Worker     inode: Inode,
2052*bb4ee6a4SAndroid Build Coastguard Worker     count: u64,
2053*bb4ee6a4SAndroid Build Coastguard Worker ) -> bool {
2054*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(data) = inodes.get(&inode) {
2055*bb4ee6a4SAndroid Build Coastguard Worker         // Acquiring the write lock on the inode map prevents new lookups from incrementing the
2056*bb4ee6a4SAndroid Build Coastguard Worker         // refcount but there is the possibility that a previous lookup already acquired a
2057*bb4ee6a4SAndroid Build Coastguard Worker         // reference to the inode data and is in the process of updating the refcount so we need
2058*bb4ee6a4SAndroid Build Coastguard Worker         // to loop here until we can decrement successfully.
2059*bb4ee6a4SAndroid Build Coastguard Worker         loop {
2060*bb4ee6a4SAndroid Build Coastguard Worker             let refcount = data.refcount.load(Ordering::Relaxed);
2061*bb4ee6a4SAndroid Build Coastguard Worker 
2062*bb4ee6a4SAndroid Build Coastguard Worker             // Saturating sub because it doesn't make sense for a refcount to go below zero and
2063*bb4ee6a4SAndroid Build Coastguard Worker             // we don't want misbehaving clients to cause integer overflow.
2064*bb4ee6a4SAndroid Build Coastguard Worker             let new_count = refcount.saturating_sub(count);
2065*bb4ee6a4SAndroid Build Coastguard Worker 
2066*bb4ee6a4SAndroid Build Coastguard Worker             // Synchronizes with the acquire load in `do_lookup`.
2067*bb4ee6a4SAndroid Build Coastguard Worker             if data
2068*bb4ee6a4SAndroid Build Coastguard Worker                 .refcount
2069*bb4ee6a4SAndroid Build Coastguard Worker                 .compare_exchange_weak(refcount, new_count, Ordering::Release, Ordering::Relaxed)
2070*bb4ee6a4SAndroid Build Coastguard Worker                 .is_ok()
2071*bb4ee6a4SAndroid Build Coastguard Worker             {
2072*bb4ee6a4SAndroid Build Coastguard Worker                 if new_count == 0 {
2073*bb4ee6a4SAndroid Build Coastguard Worker                     // We just removed the last refcount for this inode. There's no need for an
2074*bb4ee6a4SAndroid Build Coastguard Worker                     // acquire fence here because we hold a write lock on the inode map and any
2075*bb4ee6a4SAndroid Build Coastguard Worker                     // thread that is waiting to do a forget on the same inode will have to wait
2076*bb4ee6a4SAndroid Build Coastguard Worker                     // until we release the lock. So there's is no other release store for us to
2077*bb4ee6a4SAndroid Build Coastguard Worker                     // synchronize with before deleting the entry.
2078*bb4ee6a4SAndroid Build Coastguard Worker                     inodes.remove(&inode);
2079*bb4ee6a4SAndroid Build Coastguard Worker                     return true;
2080*bb4ee6a4SAndroid Build Coastguard Worker                 }
2081*bb4ee6a4SAndroid Build Coastguard Worker                 break;
2082*bb4ee6a4SAndroid Build Coastguard Worker             }
2083*bb4ee6a4SAndroid Build Coastguard Worker         }
2084*bb4ee6a4SAndroid Build Coastguard Worker     }
2085*bb4ee6a4SAndroid Build Coastguard Worker     false
2086*bb4ee6a4SAndroid Build Coastguard Worker }
2087*bb4ee6a4SAndroid Build Coastguard Worker 
2088*bb4ee6a4SAndroid Build Coastguard Worker // Strips any `user.virtiofs.` prefix from `buf`. If buf contains one or more nul-bytes, each
2089*bb4ee6a4SAndroid Build Coastguard Worker // nul-byte-separated slice is treated as a C string and the prefix is stripped from each one.
strip_xattr_prefix(buf: &mut Vec<u8>)2090*bb4ee6a4SAndroid Build Coastguard Worker fn strip_xattr_prefix(buf: &mut Vec<u8>) {
2091*bb4ee6a4SAndroid Build Coastguard Worker     fn next_cstr(b: &[u8], start: usize) -> Option<&[u8]> {
2092*bb4ee6a4SAndroid Build Coastguard Worker         if start >= b.len() {
2093*bb4ee6a4SAndroid Build Coastguard Worker             return None;
2094*bb4ee6a4SAndroid Build Coastguard Worker         }
2095*bb4ee6a4SAndroid Build Coastguard Worker 
2096*bb4ee6a4SAndroid Build Coastguard Worker         let end = b[start..]
2097*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
2098*bb4ee6a4SAndroid Build Coastguard Worker             .position(|&c| c == b'\0')
2099*bb4ee6a4SAndroid Build Coastguard Worker             .map(|p| start + p + 1)
2100*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap_or(b.len());
2101*bb4ee6a4SAndroid Build Coastguard Worker 
2102*bb4ee6a4SAndroid Build Coastguard Worker         Some(&b[start..end])
2103*bb4ee6a4SAndroid Build Coastguard Worker     }
2104*bb4ee6a4SAndroid Build Coastguard Worker 
2105*bb4ee6a4SAndroid Build Coastguard Worker     let mut pos = 0;
2106*bb4ee6a4SAndroid Build Coastguard Worker     while let Some(name) = next_cstr(buf, pos) {
2107*bb4ee6a4SAndroid Build Coastguard Worker         if !name.starts_with(USER_VIRTIOFS_XATTR) {
2108*bb4ee6a4SAndroid Build Coastguard Worker             pos += name.len();
2109*bb4ee6a4SAndroid Build Coastguard Worker             continue;
2110*bb4ee6a4SAndroid Build Coastguard Worker         }
2111*bb4ee6a4SAndroid Build Coastguard Worker 
2112*bb4ee6a4SAndroid Build Coastguard Worker         let newlen = name.len() - USER_VIRTIOFS_XATTR.len();
2113*bb4ee6a4SAndroid Build Coastguard Worker         buf.drain(pos..pos + USER_VIRTIOFS_XATTR.len());
2114*bb4ee6a4SAndroid Build Coastguard Worker         pos += newlen;
2115*bb4ee6a4SAndroid Build Coastguard Worker     }
2116*bb4ee6a4SAndroid Build Coastguard Worker }
2117*bb4ee6a4SAndroid Build Coastguard Worker 
2118*bb4ee6a4SAndroid Build Coastguard Worker impl FileSystem for PassthroughFs {
2119*bb4ee6a4SAndroid Build Coastguard Worker     type Inode = Inode;
2120*bb4ee6a4SAndroid Build Coastguard Worker     type Handle = Handle;
2121*bb4ee6a4SAndroid Build Coastguard Worker     type DirIter = ReadDir<Box<[u8]>>;
2122*bb4ee6a4SAndroid Build Coastguard Worker 
init(&self, capable: FsOptions) -> io::Result<FsOptions>2123*bb4ee6a4SAndroid Build Coastguard Worker     fn init(&self, capable: FsOptions) -> io::Result<FsOptions> {
2124*bb4ee6a4SAndroid Build Coastguard Worker         let root = CString::new(self.root_dir.clone())
2125*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
2126*bb4ee6a4SAndroid Build Coastguard Worker 
2127*bb4ee6a4SAndroid Build Coastguard Worker         let flags = libc::O_DIRECTORY | libc::O_NOFOLLOW | libc::O_CLOEXEC;
2128*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value.
2129*bb4ee6a4SAndroid Build Coastguard Worker         let raw_descriptor = unsafe { libc::openat64(libc::AT_FDCWD, root.as_ptr(), flags) };
2130*bb4ee6a4SAndroid Build Coastguard Worker         if raw_descriptor < 0 {
2131*bb4ee6a4SAndroid Build Coastguard Worker             return Err(io::Error::last_os_error());
2132*bb4ee6a4SAndroid Build Coastguard Worker         }
2133*bb4ee6a4SAndroid Build Coastguard Worker 
2134*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: safe because we just opened this descriptor above.
2135*bb4ee6a4SAndroid Build Coastguard Worker         let f = unsafe { File::from_raw_descriptor(raw_descriptor) };
2136*bb4ee6a4SAndroid Build Coastguard Worker 
2137*bb4ee6a4SAndroid Build Coastguard Worker         let st = stat(&f)?;
2138*bb4ee6a4SAndroid Build Coastguard Worker 
2139*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and there is no need to check the return
2140*bb4ee6a4SAndroid Build Coastguard Worker         // value because this system call always succeeds. We need to clear the umask here because
2141*bb4ee6a4SAndroid Build Coastguard Worker         // we want the client to be able to set all the bits in the mode.
2142*bb4ee6a4SAndroid Build Coastguard Worker         unsafe { libc::umask(0o000) };
2143*bb4ee6a4SAndroid Build Coastguard Worker 
2144*bb4ee6a4SAndroid Build Coastguard Worker         let mut inodes = self.inodes.lock();
2145*bb4ee6a4SAndroid Build Coastguard Worker 
2146*bb4ee6a4SAndroid Build Coastguard Worker         // Not sure why the root inode gets a refcount of 2 but that's what libfuse does.
2147*bb4ee6a4SAndroid Build Coastguard Worker         inodes.insert(
2148*bb4ee6a4SAndroid Build Coastguard Worker             ROOT_ID,
2149*bb4ee6a4SAndroid Build Coastguard Worker             InodeAltKey {
2150*bb4ee6a4SAndroid Build Coastguard Worker                 ino: st.st_ino,
2151*bb4ee6a4SAndroid Build Coastguard Worker                 dev: st.st_dev,
2152*bb4ee6a4SAndroid Build Coastguard Worker             },
2153*bb4ee6a4SAndroid Build Coastguard Worker             Arc::new(InodeData {
2154*bb4ee6a4SAndroid Build Coastguard Worker                 inode: ROOT_ID,
2155*bb4ee6a4SAndroid Build Coastguard Worker                 file: Mutex::new((f, flags)),
2156*bb4ee6a4SAndroid Build Coastguard Worker                 refcount: AtomicU64::new(2),
2157*bb4ee6a4SAndroid Build Coastguard Worker                 filetype: st.st_mode.into(),
2158*bb4ee6a4SAndroid Build Coastguard Worker                 path: "".to_string(),
2159*bb4ee6a4SAndroid Build Coastguard Worker             }),
2160*bb4ee6a4SAndroid Build Coastguard Worker         );
2161*bb4ee6a4SAndroid Build Coastguard Worker 
2162*bb4ee6a4SAndroid Build Coastguard Worker         let mut opts = FsOptions::DO_READDIRPLUS
2163*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::READDIRPLUS_AUTO
2164*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::EXPORT_SUPPORT
2165*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::DONT_MASK
2166*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::CACHE_SYMLINKS;
2167*bb4ee6a4SAndroid Build Coastguard Worker 
2168*bb4ee6a4SAndroid Build Coastguard Worker         // Device using dynamic xattr feature will have different security context in
2169*bb4ee6a4SAndroid Build Coastguard Worker         // host and guests. The SECURITY_CONTEXT feature should not be enabled in the
2170*bb4ee6a4SAndroid Build Coastguard Worker         // device.
2171*bb4ee6a4SAndroid Build Coastguard Worker         if self.cfg.max_dynamic_xattr == 0 && self.cfg.security_ctx {
2172*bb4ee6a4SAndroid Build Coastguard Worker             opts |= FsOptions::SECURITY_CONTEXT;
2173*bb4ee6a4SAndroid Build Coastguard Worker         }
2174*bb4ee6a4SAndroid Build Coastguard Worker 
2175*bb4ee6a4SAndroid Build Coastguard Worker         if self.cfg.posix_acl {
2176*bb4ee6a4SAndroid Build Coastguard Worker             opts |= FsOptions::POSIX_ACL;
2177*bb4ee6a4SAndroid Build Coastguard Worker         }
2178*bb4ee6a4SAndroid Build Coastguard Worker         if self.cfg.writeback && capable.contains(FsOptions::WRITEBACK_CACHE) {
2179*bb4ee6a4SAndroid Build Coastguard Worker             opts |= FsOptions::WRITEBACK_CACHE;
2180*bb4ee6a4SAndroid Build Coastguard Worker             self.writeback.store(true, Ordering::Relaxed);
2181*bb4ee6a4SAndroid Build Coastguard Worker         }
2182*bb4ee6a4SAndroid Build Coastguard Worker         if self.cfg.cache_policy == CachePolicy::Always {
2183*bb4ee6a4SAndroid Build Coastguard Worker             if capable.contains(FsOptions::ZERO_MESSAGE_OPEN) {
2184*bb4ee6a4SAndroid Build Coastguard Worker                 opts |= FsOptions::ZERO_MESSAGE_OPEN;
2185*bb4ee6a4SAndroid Build Coastguard Worker                 self.zero_message_open.store(true, Ordering::Relaxed);
2186*bb4ee6a4SAndroid Build Coastguard Worker             }
2187*bb4ee6a4SAndroid Build Coastguard Worker             if capable.contains(FsOptions::ZERO_MESSAGE_OPENDIR) {
2188*bb4ee6a4SAndroid Build Coastguard Worker                 opts |= FsOptions::ZERO_MESSAGE_OPENDIR;
2189*bb4ee6a4SAndroid Build Coastguard Worker                 self.zero_message_opendir.store(true, Ordering::Relaxed);
2190*bb4ee6a4SAndroid Build Coastguard Worker             }
2191*bb4ee6a4SAndroid Build Coastguard Worker         }
2192*bb4ee6a4SAndroid Build Coastguard Worker         Ok(opts)
2193*bb4ee6a4SAndroid Build Coastguard Worker     }
2194*bb4ee6a4SAndroid Build Coastguard Worker 
destroy(&self)2195*bb4ee6a4SAndroid Build Coastguard Worker     fn destroy(&self) {
2196*bb4ee6a4SAndroid Build Coastguard Worker         cros_tracing::trace_simple_print!(VirtioFs, "{:?}: destroy", self);
2197*bb4ee6a4SAndroid Build Coastguard Worker         self.handles.lock().clear();
2198*bb4ee6a4SAndroid Build Coastguard Worker         self.inodes.lock().clear();
2199*bb4ee6a4SAndroid Build Coastguard Worker     }
2200*bb4ee6a4SAndroid Build Coastguard Worker 
statfs(&self, _ctx: Context, inode: Inode) -> io::Result<libc::statvfs64>2201*bb4ee6a4SAndroid Build Coastguard Worker     fn statfs(&self, _ctx: Context, inode: Inode) -> io::Result<libc::statvfs64> {
2202*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "statfs", inode);
2203*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(inode)?;
2204*bb4ee6a4SAndroid Build Coastguard Worker 
2205*bb4ee6a4SAndroid Build Coastguard Worker         let mut out = MaybeUninit::<libc::statvfs64>::zeroed();
2206*bb4ee6a4SAndroid Build Coastguard Worker 
2207*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this will only modify `out` and we check the return value.
2208*bb4ee6a4SAndroid Build Coastguard Worker         syscall!(unsafe { libc::fstatvfs64(data.as_raw_descriptor(), out.as_mut_ptr()) })?;
2209*bb4ee6a4SAndroid Build Coastguard Worker 
2210*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: the kernel guarantees that `out` has been initialized.
2211*bb4ee6a4SAndroid Build Coastguard Worker         Ok(unsafe { out.assume_init() })
2212*bb4ee6a4SAndroid Build Coastguard Worker     }
2213*bb4ee6a4SAndroid Build Coastguard Worker 
lookup(&self, _ctx: Context, parent: Inode, name: &CStr) -> io::Result<Entry>2214*bb4ee6a4SAndroid Build Coastguard Worker     fn lookup(&self, _ctx: Context, parent: Inode, name: &CStr) -> io::Result<Entry> {
2215*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(parent)?;
2216*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(unused_variables)]
2217*bb4ee6a4SAndroid Build Coastguard Worker         let path = format!(
2218*bb4ee6a4SAndroid Build Coastguard Worker             "{}/{}",
2219*bb4ee6a4SAndroid Build Coastguard Worker             data.path,
2220*bb4ee6a4SAndroid Build Coastguard Worker             name.to_str().unwrap_or("<non UTF-8 path>")
2221*bb4ee6a4SAndroid Build Coastguard Worker         );
2222*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "lookup", parent, path);
2223*bb4ee6a4SAndroid Build Coastguard Worker 
2224*bb4ee6a4SAndroid Build Coastguard Worker         let mut res = self.do_lookup_with_casefold_fallback(&data, name);
2225*bb4ee6a4SAndroid Build Coastguard Worker 
2226*bb4ee6a4SAndroid Build Coastguard Worker         // FUSE takes a inode=0 as a request to do negative dentry cache.
2227*bb4ee6a4SAndroid Build Coastguard Worker         // So, if `negative_timeout` is set, return success with the timeout value and inode=0 as a
2228*bb4ee6a4SAndroid Build Coastguard Worker         // response.
2229*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = &res {
2230*bb4ee6a4SAndroid Build Coastguard Worker             if e.kind() == std::io::ErrorKind::NotFound && !self.cfg.negative_timeout.is_zero() {
2231*bb4ee6a4SAndroid Build Coastguard Worker                 res = Ok(Entry::new_negative(self.cfg.negative_timeout));
2232*bb4ee6a4SAndroid Build Coastguard Worker             }
2233*bb4ee6a4SAndroid Build Coastguard Worker         }
2234*bb4ee6a4SAndroid Build Coastguard Worker 
2235*bb4ee6a4SAndroid Build Coastguard Worker         res
2236*bb4ee6a4SAndroid Build Coastguard Worker     }
2237*bb4ee6a4SAndroid Build Coastguard Worker 
forget(&self, _ctx: Context, inode: Inode, count: u64)2238*bb4ee6a4SAndroid Build Coastguard Worker     fn forget(&self, _ctx: Context, inode: Inode, count: u64) {
2239*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "forget", inode, count);
2240*bb4ee6a4SAndroid Build Coastguard Worker         let mut inodes = self.inodes.lock();
2241*bb4ee6a4SAndroid Build Coastguard Worker         let caches = self.lock_casefold_lookup_caches();
2242*bb4ee6a4SAndroid Build Coastguard Worker         if forget_one(&mut inodes, inode, count) {
2243*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(mut c) = caches {
2244*bb4ee6a4SAndroid Build Coastguard Worker                 c.forget(inode);
2245*bb4ee6a4SAndroid Build Coastguard Worker             }
2246*bb4ee6a4SAndroid Build Coastguard Worker         }
2247*bb4ee6a4SAndroid Build Coastguard Worker     }
2248*bb4ee6a4SAndroid Build Coastguard Worker 
batch_forget(&self, _ctx: Context, requests: Vec<(Inode, u64)>)2249*bb4ee6a4SAndroid Build Coastguard Worker     fn batch_forget(&self, _ctx: Context, requests: Vec<(Inode, u64)>) {
2250*bb4ee6a4SAndroid Build Coastguard Worker         let mut inodes = self.inodes.lock();
2251*bb4ee6a4SAndroid Build Coastguard Worker         let mut caches = self.lock_casefold_lookup_caches();
2252*bb4ee6a4SAndroid Build Coastguard Worker         for (inode, count) in requests {
2253*bb4ee6a4SAndroid Build Coastguard Worker             if forget_one(&mut inodes, inode, count) {
2254*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(c) = caches.as_mut() {
2255*bb4ee6a4SAndroid Build Coastguard Worker                     c.forget(inode);
2256*bb4ee6a4SAndroid Build Coastguard Worker                 }
2257*bb4ee6a4SAndroid Build Coastguard Worker             }
2258*bb4ee6a4SAndroid Build Coastguard Worker         }
2259*bb4ee6a4SAndroid Build Coastguard Worker     }
2260*bb4ee6a4SAndroid Build Coastguard Worker 
opendir( &self, _ctx: Context, inode: Inode, flags: u32, ) -> io::Result<(Option<Handle>, OpenOptions)>2261*bb4ee6a4SAndroid Build Coastguard Worker     fn opendir(
2262*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2263*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2264*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2265*bb4ee6a4SAndroid Build Coastguard Worker         flags: u32,
2266*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<(Option<Handle>, OpenOptions)> {
2267*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "opendir", inode, flags);
2268*bb4ee6a4SAndroid Build Coastguard Worker         if self.zero_message_opendir.load(Ordering::Relaxed) {
2269*bb4ee6a4SAndroid Build Coastguard Worker             Err(io::Error::from_raw_os_error(libc::ENOSYS))
2270*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2271*bb4ee6a4SAndroid Build Coastguard Worker             self.do_open(inode, flags | (libc::O_DIRECTORY as u32))
2272*bb4ee6a4SAndroid Build Coastguard Worker         }
2273*bb4ee6a4SAndroid Build Coastguard Worker     }
2274*bb4ee6a4SAndroid Build Coastguard Worker 
releasedir( &self, _ctx: Context, inode: Inode, _flags: u32, handle: Handle, ) -> io::Result<()>2275*bb4ee6a4SAndroid Build Coastguard Worker     fn releasedir(
2276*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2277*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2278*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2279*bb4ee6a4SAndroid Build Coastguard Worker         _flags: u32,
2280*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
2281*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<()> {
2282*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "releasedir", inode, handle);
2283*bb4ee6a4SAndroid Build Coastguard Worker         if self.zero_message_opendir.load(Ordering::Relaxed) {
2284*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
2285*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2286*bb4ee6a4SAndroid Build Coastguard Worker             self.do_release(inode, handle)
2287*bb4ee6a4SAndroid Build Coastguard Worker         }
2288*bb4ee6a4SAndroid Build Coastguard Worker     }
2289*bb4ee6a4SAndroid Build Coastguard Worker 
mkdir( &self, ctx: Context, parent: Inode, name: &CStr, mode: u32, umask: u32, security_ctx: Option<&CStr>, ) -> io::Result<Entry>2290*bb4ee6a4SAndroid Build Coastguard Worker     fn mkdir(
2291*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2292*bb4ee6a4SAndroid Build Coastguard Worker         ctx: Context,
2293*bb4ee6a4SAndroid Build Coastguard Worker         parent: Inode,
2294*bb4ee6a4SAndroid Build Coastguard Worker         name: &CStr,
2295*bb4ee6a4SAndroid Build Coastguard Worker         mode: u32,
2296*bb4ee6a4SAndroid Build Coastguard Worker         umask: u32,
2297*bb4ee6a4SAndroid Build Coastguard Worker         security_ctx: Option<&CStr>,
2298*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<Entry> {
2299*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "mkdir", parent, name, mode, umask, security_ctx);
2300*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(parent)?;
2301*bb4ee6a4SAndroid Build Coastguard Worker 
2302*bb4ee6a4SAndroid Build Coastguard Worker         let _ctx = security_ctx
2303*bb4ee6a4SAndroid Build Coastguard Worker             .filter(|ctx| *ctx != UNLABELED_CSTR)
2304*bb4ee6a4SAndroid Build Coastguard Worker             .map(|ctx| ScopedSecurityContext::new(&self.proc, ctx))
2305*bb4ee6a4SAndroid Build Coastguard Worker             .transpose()?;
2306*bb4ee6a4SAndroid Build Coastguard Worker 
2307*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(unused_variables)]
2308*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
2309*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_creds(&ctx, &data, name);
2310*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "fs_runtime_ugid_map")]
2311*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_ugid_creds(&ctx, &data, name);
2312*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(feature = "fs_permission_translation"))]
2313*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = (ctx.uid, ctx.gid);
2314*bb4ee6a4SAndroid Build Coastguard Worker 
2315*bb4ee6a4SAndroid Build Coastguard Worker         let (_uid, _gid) = set_creds(uid, gid)?;
2316*bb4ee6a4SAndroid Build Coastguard Worker         {
2317*bb4ee6a4SAndroid Build Coastguard Worker             let casefold_cache = self.lock_casefold_lookup_caches();
2318*bb4ee6a4SAndroid Build Coastguard Worker             let _scoped_umask = ScopedUmask::new(umask);
2319*bb4ee6a4SAndroid Build Coastguard Worker 
2320*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
2321*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(unsafe { libc::mkdirat(data.as_raw_descriptor(), name.as_ptr(), mode) })?;
2322*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(mut c) = casefold_cache {
2323*bb4ee6a4SAndroid Build Coastguard Worker                 c.insert(data.inode, name);
2324*bb4ee6a4SAndroid Build Coastguard Worker             }
2325*bb4ee6a4SAndroid Build Coastguard Worker         }
2326*bb4ee6a4SAndroid Build Coastguard Worker         self.do_lookup(&data, name)
2327*bb4ee6a4SAndroid Build Coastguard Worker     }
2328*bb4ee6a4SAndroid Build Coastguard Worker 
rmdir(&self, _ctx: Context, parent: Inode, name: &CStr) -> io::Result<()>2329*bb4ee6a4SAndroid Build Coastguard Worker     fn rmdir(&self, _ctx: Context, parent: Inode, name: &CStr) -> io::Result<()> {
2330*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "rmdir", parent, name);
2331*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(parent)?;
2332*bb4ee6a4SAndroid Build Coastguard Worker         let casefold_cache = self.lock_casefold_lookup_caches();
2333*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/278691962): If ascii_casefold is enabled, we need to call
2334*bb4ee6a4SAndroid Build Coastguard Worker         // `get_case_unfolded_name()` to get the actual name to be unlinked.
2335*bb4ee6a4SAndroid Build Coastguard Worker         self.do_unlink(&data, name, libc::AT_REMOVEDIR)?;
2336*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(mut c) = casefold_cache {
2337*bb4ee6a4SAndroid Build Coastguard Worker             c.remove(data.inode, name);
2338*bb4ee6a4SAndroid Build Coastguard Worker         }
2339*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
2340*bb4ee6a4SAndroid Build Coastguard Worker     }
2341*bb4ee6a4SAndroid Build Coastguard Worker 
readdir( &self, _ctx: Context, inode: Inode, handle: Handle, size: u32, offset: u64, ) -> io::Result<Self::DirIter>2342*bb4ee6a4SAndroid Build Coastguard Worker     fn readdir(
2343*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2344*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2345*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2346*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
2347*bb4ee6a4SAndroid Build Coastguard Worker         size: u32,
2348*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
2349*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<Self::DirIter> {
2350*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "readdir", inode, handle, size, offset);
2351*bb4ee6a4SAndroid Build Coastguard Worker         let buf = vec![0; size as usize].into_boxed_slice();
2352*bb4ee6a4SAndroid Build Coastguard Worker 
2353*bb4ee6a4SAndroid Build Coastguard Worker         if self.zero_message_opendir.load(Ordering::Relaxed) {
2354*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_inode(inode)?;
2355*bb4ee6a4SAndroid Build Coastguard Worker             ReadDir::new(&*data, offset as libc::off64_t, buf)
2356*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2357*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_handle(handle, inode)?;
2358*bb4ee6a4SAndroid Build Coastguard Worker 
2359*bb4ee6a4SAndroid Build Coastguard Worker             let dir = data.file.lock();
2360*bb4ee6a4SAndroid Build Coastguard Worker 
2361*bb4ee6a4SAndroid Build Coastguard Worker             ReadDir::new(&*dir, offset as libc::off64_t, buf)
2362*bb4ee6a4SAndroid Build Coastguard Worker         }
2363*bb4ee6a4SAndroid Build Coastguard Worker     }
2364*bb4ee6a4SAndroid Build Coastguard Worker 
open( &self, _ctx: Context, inode: Inode, flags: u32, ) -> io::Result<(Option<Handle>, OpenOptions)>2365*bb4ee6a4SAndroid Build Coastguard Worker     fn open(
2366*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2367*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2368*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2369*bb4ee6a4SAndroid Build Coastguard Worker         flags: u32,
2370*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<(Option<Handle>, OpenOptions)> {
2371*bb4ee6a4SAndroid Build Coastguard Worker         if self.zero_message_open.load(Ordering::Relaxed) {
2372*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "open (zero-message)", inode, flags);
2373*bb4ee6a4SAndroid Build Coastguard Worker             Err(io::Error::from_raw_os_error(libc::ENOSYS))
2374*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2375*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "open", inode, flags);
2376*bb4ee6a4SAndroid Build Coastguard Worker             self.do_open(inode, flags)
2377*bb4ee6a4SAndroid Build Coastguard Worker         }
2378*bb4ee6a4SAndroid Build Coastguard Worker     }
2379*bb4ee6a4SAndroid Build Coastguard Worker 
release( &self, _ctx: Context, inode: Inode, _flags: u32, handle: Handle, _flush: bool, _flock_release: bool, _lock_owner: Option<u64>, ) -> io::Result<()>2380*bb4ee6a4SAndroid Build Coastguard Worker     fn release(
2381*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2382*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2383*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2384*bb4ee6a4SAndroid Build Coastguard Worker         _flags: u32,
2385*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
2386*bb4ee6a4SAndroid Build Coastguard Worker         _flush: bool,
2387*bb4ee6a4SAndroid Build Coastguard Worker         _flock_release: bool,
2388*bb4ee6a4SAndroid Build Coastguard Worker         _lock_owner: Option<u64>,
2389*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<()> {
2390*bb4ee6a4SAndroid Build Coastguard Worker         if self.zero_message_open.load(Ordering::Relaxed) {
2391*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "release (zero-message)", inode, handle);
2392*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
2393*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2394*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "release", inode, handle);
2395*bb4ee6a4SAndroid Build Coastguard Worker             self.do_release(inode, handle)
2396*bb4ee6a4SAndroid Build Coastguard Worker         }
2397*bb4ee6a4SAndroid Build Coastguard Worker     }
2398*bb4ee6a4SAndroid Build Coastguard Worker 
chromeos_tmpfile( &self, ctx: Context, parent: Self::Inode, mode: u32, umask: u32, security_ctx: Option<&CStr>, ) -> io::Result<Entry>2399*bb4ee6a4SAndroid Build Coastguard Worker     fn chromeos_tmpfile(
2400*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2401*bb4ee6a4SAndroid Build Coastguard Worker         ctx: Context,
2402*bb4ee6a4SAndroid Build Coastguard Worker         parent: Self::Inode,
2403*bb4ee6a4SAndroid Build Coastguard Worker         mode: u32,
2404*bb4ee6a4SAndroid Build Coastguard Worker         umask: u32,
2405*bb4ee6a4SAndroid Build Coastguard Worker         security_ctx: Option<&CStr>,
2406*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<Entry> {
2407*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(
2408*bb4ee6a4SAndroid Build Coastguard Worker             self.tag,
2409*bb4ee6a4SAndroid Build Coastguard Worker             "chromeos_tempfile",
2410*bb4ee6a4SAndroid Build Coastguard Worker             parent,
2411*bb4ee6a4SAndroid Build Coastguard Worker             mode,
2412*bb4ee6a4SAndroid Build Coastguard Worker             umask,
2413*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx
2414*bb4ee6a4SAndroid Build Coastguard Worker         );
2415*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(parent)?;
2416*bb4ee6a4SAndroid Build Coastguard Worker 
2417*bb4ee6a4SAndroid Build Coastguard Worker         let _ctx = security_ctx
2418*bb4ee6a4SAndroid Build Coastguard Worker             .filter(|ctx| *ctx != UNLABELED_CSTR)
2419*bb4ee6a4SAndroid Build Coastguard Worker             .map(|ctx| ScopedSecurityContext::new(&self.proc, ctx))
2420*bb4ee6a4SAndroid Build Coastguard Worker             .transpose()?;
2421*bb4ee6a4SAndroid Build Coastguard Worker 
2422*bb4ee6a4SAndroid Build Coastguard Worker         let tmpflags = libc::O_RDWR | libc::O_TMPFILE | libc::O_CLOEXEC | libc::O_NOFOLLOW;
2423*bb4ee6a4SAndroid Build Coastguard Worker 
2424*bb4ee6a4SAndroid Build Coastguard Worker         let current_dir = c".";
2425*bb4ee6a4SAndroid Build Coastguard Worker 
2426*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(unused_variables)]
2427*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
2428*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_creds(&ctx, &data, current_dir);
2429*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "fs_runtime_ugid_map")]
2430*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_ugid_creds(&ctx, &data, current_dir);
2431*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(feature = "fs_permission_translation"))]
2432*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = (ctx.uid, ctx.gid);
2433*bb4ee6a4SAndroid Build Coastguard Worker 
2434*bb4ee6a4SAndroid Build Coastguard Worker         let (_uid, _gid) = set_creds(uid, gid)?;
2435*bb4ee6a4SAndroid Build Coastguard Worker 
2436*bb4ee6a4SAndroid Build Coastguard Worker         let fd = {
2437*bb4ee6a4SAndroid Build Coastguard Worker             let _scoped_umask = ScopedUmask::new(umask);
2438*bb4ee6a4SAndroid Build Coastguard Worker 
2439*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
2440*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(unsafe {
2441*bb4ee6a4SAndroid Build Coastguard Worker                 libc::openat64(
2442*bb4ee6a4SAndroid Build Coastguard Worker                     data.as_raw_descriptor(),
2443*bb4ee6a4SAndroid Build Coastguard Worker                     current_dir.as_ptr(),
2444*bb4ee6a4SAndroid Build Coastguard Worker                     tmpflags,
2445*bb4ee6a4SAndroid Build Coastguard Worker                     mode,
2446*bb4ee6a4SAndroid Build Coastguard Worker                 )
2447*bb4ee6a4SAndroid Build Coastguard Worker             })?
2448*bb4ee6a4SAndroid Build Coastguard Worker         };
2449*bb4ee6a4SAndroid Build Coastguard Worker         // No need to add casefold_cache becuase we created an anonymous file.
2450*bb4ee6a4SAndroid Build Coastguard Worker 
2451*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: safe because we just opened this fd.
2452*bb4ee6a4SAndroid Build Coastguard Worker         let tmpfile = unsafe { File::from_raw_descriptor(fd) };
2453*bb4ee6a4SAndroid Build Coastguard Worker         let st = stat(&tmpfile)?;
2454*bb4ee6a4SAndroid Build Coastguard Worker         let path = format!(
2455*bb4ee6a4SAndroid Build Coastguard Worker             "{}/{}",
2456*bb4ee6a4SAndroid Build Coastguard Worker             data.path.clone(),
2457*bb4ee6a4SAndroid Build Coastguard Worker             current_dir.to_str().unwrap_or("<non UTF-8 str>")
2458*bb4ee6a4SAndroid Build Coastguard Worker         );
2459*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.add_entry(tmpfile, st, tmpflags, path))
2460*bb4ee6a4SAndroid Build Coastguard Worker     }
2461*bb4ee6a4SAndroid Build Coastguard Worker 
create( &self, ctx: Context, parent: Inode, name: &CStr, mode: u32, flags: u32, umask: u32, security_ctx: Option<&CStr>, ) -> io::Result<(Entry, Option<Handle>, OpenOptions)>2462*bb4ee6a4SAndroid Build Coastguard Worker     fn create(
2463*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2464*bb4ee6a4SAndroid Build Coastguard Worker         ctx: Context,
2465*bb4ee6a4SAndroid Build Coastguard Worker         parent: Inode,
2466*bb4ee6a4SAndroid Build Coastguard Worker         name: &CStr,
2467*bb4ee6a4SAndroid Build Coastguard Worker         mode: u32,
2468*bb4ee6a4SAndroid Build Coastguard Worker         flags: u32,
2469*bb4ee6a4SAndroid Build Coastguard Worker         umask: u32,
2470*bb4ee6a4SAndroid Build Coastguard Worker         security_ctx: Option<&CStr>,
2471*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<(Entry, Option<Handle>, OpenOptions)> {
2472*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(
2473*bb4ee6a4SAndroid Build Coastguard Worker             self.tag,
2474*bb4ee6a4SAndroid Build Coastguard Worker             "create",
2475*bb4ee6a4SAndroid Build Coastguard Worker             parent,
2476*bb4ee6a4SAndroid Build Coastguard Worker             name,
2477*bb4ee6a4SAndroid Build Coastguard Worker             mode,
2478*bb4ee6a4SAndroid Build Coastguard Worker             flags,
2479*bb4ee6a4SAndroid Build Coastguard Worker             umask,
2480*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx
2481*bb4ee6a4SAndroid Build Coastguard Worker         );
2482*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(parent)?;
2483*bb4ee6a4SAndroid Build Coastguard Worker 
2484*bb4ee6a4SAndroid Build Coastguard Worker         let _ctx = security_ctx
2485*bb4ee6a4SAndroid Build Coastguard Worker             .filter(|ctx| *ctx != UNLABELED_CSTR)
2486*bb4ee6a4SAndroid Build Coastguard Worker             .map(|ctx| ScopedSecurityContext::new(&self.proc, ctx))
2487*bb4ee6a4SAndroid Build Coastguard Worker             .transpose()?;
2488*bb4ee6a4SAndroid Build Coastguard Worker 
2489*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(unused_variables)]
2490*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
2491*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_creds(&ctx, &data, name);
2492*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "fs_runtime_ugid_map")]
2493*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_ugid_creds(&ctx, &data, name);
2494*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(feature = "fs_permission_translation"))]
2495*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = (ctx.uid, ctx.gid);
2496*bb4ee6a4SAndroid Build Coastguard Worker 
2497*bb4ee6a4SAndroid Build Coastguard Worker         let (_uid, _gid) = set_creds(uid, gid)?;
2498*bb4ee6a4SAndroid Build Coastguard Worker 
2499*bb4ee6a4SAndroid Build Coastguard Worker         let flags = self.update_open_flags(flags as i32);
2500*bb4ee6a4SAndroid Build Coastguard Worker         let create_flags =
2501*bb4ee6a4SAndroid Build Coastguard Worker             (flags | libc::O_CREAT | libc::O_CLOEXEC | libc::O_NOFOLLOW) & !libc::O_DIRECT;
2502*bb4ee6a4SAndroid Build Coastguard Worker 
2503*bb4ee6a4SAndroid Build Coastguard Worker         let fd = {
2504*bb4ee6a4SAndroid Build Coastguard Worker             let _scoped_umask = ScopedUmask::new(umask);
2505*bb4ee6a4SAndroid Build Coastguard Worker             let casefold_cache = self.lock_casefold_lookup_caches();
2506*bb4ee6a4SAndroid Build Coastguard Worker 
2507*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value. We don't really
2508*bb4ee6a4SAndroid Build Coastguard Worker             // check `flags` because if the kernel can't handle poorly specified flags then we have
2509*bb4ee6a4SAndroid Build Coastguard Worker             // much bigger problems.
2510*bb4ee6a4SAndroid Build Coastguard Worker             // TODO(b/278691962): If ascii_casefold is enabled, we need to call
2511*bb4ee6a4SAndroid Build Coastguard Worker             // `get_case_unfolded_name()` to get the actual name to be created.
2512*bb4ee6a4SAndroid Build Coastguard Worker             let fd = syscall!(unsafe {
2513*bb4ee6a4SAndroid Build Coastguard Worker                 libc::openat64(data.as_raw_descriptor(), name.as_ptr(), create_flags, mode)
2514*bb4ee6a4SAndroid Build Coastguard Worker             })?;
2515*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(mut c) = casefold_cache {
2516*bb4ee6a4SAndroid Build Coastguard Worker                 c.insert(parent, name);
2517*bb4ee6a4SAndroid Build Coastguard Worker             }
2518*bb4ee6a4SAndroid Build Coastguard Worker             fd
2519*bb4ee6a4SAndroid Build Coastguard Worker         };
2520*bb4ee6a4SAndroid Build Coastguard Worker 
2521*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: safe because we just opened this fd.
2522*bb4ee6a4SAndroid Build Coastguard Worker         let file = unsafe { File::from_raw_descriptor(fd) };
2523*bb4ee6a4SAndroid Build Coastguard Worker 
2524*bb4ee6a4SAndroid Build Coastguard Worker         let st = stat(&file)?;
2525*bb4ee6a4SAndroid Build Coastguard Worker         let path = format!(
2526*bb4ee6a4SAndroid Build Coastguard Worker             "{}/{}",
2527*bb4ee6a4SAndroid Build Coastguard Worker             data.path.clone(),
2528*bb4ee6a4SAndroid Build Coastguard Worker             name.to_str().unwrap_or("<non UTF-8 str>")
2529*bb4ee6a4SAndroid Build Coastguard Worker         );
2530*bb4ee6a4SAndroid Build Coastguard Worker         let entry = self.add_entry(file, st, create_flags, path);
2531*bb4ee6a4SAndroid Build Coastguard Worker 
2532*bb4ee6a4SAndroid Build Coastguard Worker         let (handle, opts) = if self.zero_message_open.load(Ordering::Relaxed) {
2533*bb4ee6a4SAndroid Build Coastguard Worker             (None, OpenOptions::KEEP_CACHE)
2534*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2535*bb4ee6a4SAndroid Build Coastguard Worker             self.do_open_at(
2536*bb4ee6a4SAndroid Build Coastguard Worker                 data,
2537*bb4ee6a4SAndroid Build Coastguard Worker                 name,
2538*bb4ee6a4SAndroid Build Coastguard Worker                 entry.inode,
2539*bb4ee6a4SAndroid Build Coastguard Worker                 flags as u32 & !((libc::O_CREAT | libc::O_EXCL | libc::O_NOCTTY) as u32),
2540*bb4ee6a4SAndroid Build Coastguard Worker             )
2541*bb4ee6a4SAndroid Build Coastguard Worker             .inspect_err(|_e| {
2542*bb4ee6a4SAndroid Build Coastguard Worker                 // Don't leak the entry.
2543*bb4ee6a4SAndroid Build Coastguard Worker                 self.forget(ctx, entry.inode, 1);
2544*bb4ee6a4SAndroid Build Coastguard Worker             })?
2545*bb4ee6a4SAndroid Build Coastguard Worker         };
2546*bb4ee6a4SAndroid Build Coastguard Worker         Ok((entry, handle, opts))
2547*bb4ee6a4SAndroid Build Coastguard Worker     }
2548*bb4ee6a4SAndroid Build Coastguard Worker 
unlink(&self, _ctx: Context, parent: Inode, name: &CStr) -> io::Result<()>2549*bb4ee6a4SAndroid Build Coastguard Worker     fn unlink(&self, _ctx: Context, parent: Inode, name: &CStr) -> io::Result<()> {
2550*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "unlink", parent, name);
2551*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(parent)?;
2552*bb4ee6a4SAndroid Build Coastguard Worker         let casefold_cache = self.lock_casefold_lookup_caches();
2553*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(b/278691962): If ascii_casefold is enabled, we need to call
2554*bb4ee6a4SAndroid Build Coastguard Worker         // `get_case_unfolded_name()` to get the actual name to be unlinked.
2555*bb4ee6a4SAndroid Build Coastguard Worker         self.do_unlink(&data, name, 0)?;
2556*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(mut c) = casefold_cache {
2557*bb4ee6a4SAndroid Build Coastguard Worker             c.remove(data.inode, name);
2558*bb4ee6a4SAndroid Build Coastguard Worker         }
2559*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
2560*bb4ee6a4SAndroid Build Coastguard Worker     }
2561*bb4ee6a4SAndroid Build Coastguard Worker 
read<W: io::Write + ZeroCopyWriter>( &self, _ctx: Context, inode: Inode, handle: Handle, mut w: W, size: u32, offset: u64, _lock_owner: Option<u64>, _flags: u32, ) -> io::Result<usize>2562*bb4ee6a4SAndroid Build Coastguard Worker     fn read<W: io::Write + ZeroCopyWriter>(
2563*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2564*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2565*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2566*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
2567*bb4ee6a4SAndroid Build Coastguard Worker         mut w: W,
2568*bb4ee6a4SAndroid Build Coastguard Worker         size: u32,
2569*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
2570*bb4ee6a4SAndroid Build Coastguard Worker         _lock_owner: Option<u64>,
2571*bb4ee6a4SAndroid Build Coastguard Worker         _flags: u32,
2572*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<usize> {
2573*bb4ee6a4SAndroid Build Coastguard Worker         if self.zero_message_open.load(Ordering::Relaxed) {
2574*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "read (zero-message)", inode, handle, size, offset);
2575*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_inode(inode)?;
2576*bb4ee6a4SAndroid Build Coastguard Worker 
2577*bb4ee6a4SAndroid Build Coastguard Worker             let mut file = data.file.lock();
2578*bb4ee6a4SAndroid Build Coastguard Worker             let mut flags = file.1;
2579*bb4ee6a4SAndroid Build Coastguard Worker             match flags & libc::O_ACCMODE {
2580*bb4ee6a4SAndroid Build Coastguard Worker                 libc::O_WRONLY => {
2581*bb4ee6a4SAndroid Build Coastguard Worker                     flags &= !libc::O_WRONLY;
2582*bb4ee6a4SAndroid Build Coastguard Worker                     flags |= libc::O_RDWR;
2583*bb4ee6a4SAndroid Build Coastguard Worker 
2584*bb4ee6a4SAndroid Build Coastguard Worker                     // We need to get a readable handle for this file.
2585*bb4ee6a4SAndroid Build Coastguard Worker                     let newfile = self.open_fd(file.0.as_raw_descriptor(), libc::O_RDWR)?;
2586*bb4ee6a4SAndroid Build Coastguard Worker                     *file = (newfile, flags);
2587*bb4ee6a4SAndroid Build Coastguard Worker                 }
2588*bb4ee6a4SAndroid Build Coastguard Worker                 libc::O_RDONLY | libc::O_RDWR => {}
2589*bb4ee6a4SAndroid Build Coastguard Worker                 _ => panic!("Unexpected flags: {:#x}", flags),
2590*bb4ee6a4SAndroid Build Coastguard Worker             }
2591*bb4ee6a4SAndroid Build Coastguard Worker 
2592*bb4ee6a4SAndroid Build Coastguard Worker             w.write_from(&mut file.0, size as usize, offset)
2593*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2594*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "read", inode, handle, size, offset);
2595*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_handle(handle, inode)?;
2596*bb4ee6a4SAndroid Build Coastguard Worker 
2597*bb4ee6a4SAndroid Build Coastguard Worker             let mut f = data.file.lock();
2598*bb4ee6a4SAndroid Build Coastguard Worker             w.write_from(&mut f, size as usize, offset)
2599*bb4ee6a4SAndroid Build Coastguard Worker         }
2600*bb4ee6a4SAndroid Build Coastguard Worker     }
2601*bb4ee6a4SAndroid Build Coastguard Worker 
write<R: io::Read + ZeroCopyReader>( &self, _ctx: Context, inode: Inode, handle: Handle, mut r: R, size: u32, offset: u64, _lock_owner: Option<u64>, _delayed_write: bool, flags: u32, ) -> io::Result<usize>2602*bb4ee6a4SAndroid Build Coastguard Worker     fn write<R: io::Read + ZeroCopyReader>(
2603*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2604*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2605*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2606*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
2607*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
2608*bb4ee6a4SAndroid Build Coastguard Worker         size: u32,
2609*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
2610*bb4ee6a4SAndroid Build Coastguard Worker         _lock_owner: Option<u64>,
2611*bb4ee6a4SAndroid Build Coastguard Worker         _delayed_write: bool,
2612*bb4ee6a4SAndroid Build Coastguard Worker         flags: u32,
2613*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<usize> {
2614*bb4ee6a4SAndroid Build Coastguard Worker         // When the WRITE_KILL_PRIV flag is set, drop CAP_FSETID so that the kernel will
2615*bb4ee6a4SAndroid Build Coastguard Worker         // automatically clear the setuid and setgid bits for us.
2616*bb4ee6a4SAndroid Build Coastguard Worker         let _fsetid = if flags & WRITE_KILL_PRIV != 0 {
2617*bb4ee6a4SAndroid Build Coastguard Worker             Some(drop_cap_fsetid()?)
2618*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2619*bb4ee6a4SAndroid Build Coastguard Worker             None
2620*bb4ee6a4SAndroid Build Coastguard Worker         };
2621*bb4ee6a4SAndroid Build Coastguard Worker 
2622*bb4ee6a4SAndroid Build Coastguard Worker         if self.zero_message_open.load(Ordering::Relaxed) {
2623*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(
2624*bb4ee6a4SAndroid Build Coastguard Worker                 self.tag,
2625*bb4ee6a4SAndroid Build Coastguard Worker                 "write (zero-message)",
2626*bb4ee6a4SAndroid Build Coastguard Worker                 inode,
2627*bb4ee6a4SAndroid Build Coastguard Worker                 handle,
2628*bb4ee6a4SAndroid Build Coastguard Worker                 size,
2629*bb4ee6a4SAndroid Build Coastguard Worker                 offset
2630*bb4ee6a4SAndroid Build Coastguard Worker             );
2631*bb4ee6a4SAndroid Build Coastguard Worker 
2632*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_inode(inode)?;
2633*bb4ee6a4SAndroid Build Coastguard Worker 
2634*bb4ee6a4SAndroid Build Coastguard Worker             let mut file = data.file.lock();
2635*bb4ee6a4SAndroid Build Coastguard Worker             let mut flags = file.1;
2636*bb4ee6a4SAndroid Build Coastguard Worker             match flags & libc::O_ACCMODE {
2637*bb4ee6a4SAndroid Build Coastguard Worker                 libc::O_RDONLY => {
2638*bb4ee6a4SAndroid Build Coastguard Worker                     flags &= !libc::O_RDONLY;
2639*bb4ee6a4SAndroid Build Coastguard Worker                     flags |= libc::O_RDWR;
2640*bb4ee6a4SAndroid Build Coastguard Worker 
2641*bb4ee6a4SAndroid Build Coastguard Worker                     // We need to get a writable handle for this file.
2642*bb4ee6a4SAndroid Build Coastguard Worker                     let newfile = self.open_fd(file.0.as_raw_descriptor(), libc::O_RDWR)?;
2643*bb4ee6a4SAndroid Build Coastguard Worker                     *file = (newfile, flags);
2644*bb4ee6a4SAndroid Build Coastguard Worker                 }
2645*bb4ee6a4SAndroid Build Coastguard Worker                 libc::O_WRONLY | libc::O_RDWR => {}
2646*bb4ee6a4SAndroid Build Coastguard Worker                 _ => panic!("Unexpected flags: {:#x}", flags),
2647*bb4ee6a4SAndroid Build Coastguard Worker             }
2648*bb4ee6a4SAndroid Build Coastguard Worker 
2649*bb4ee6a4SAndroid Build Coastguard Worker             r.read_to(&mut file.0, size as usize, offset)
2650*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2651*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "write", inode, handle, size, offset);
2652*bb4ee6a4SAndroid Build Coastguard Worker 
2653*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_handle(handle, inode)?;
2654*bb4ee6a4SAndroid Build Coastguard Worker 
2655*bb4ee6a4SAndroid Build Coastguard Worker             let mut f = data.file.lock();
2656*bb4ee6a4SAndroid Build Coastguard Worker             r.read_to(&mut f, size as usize, offset)
2657*bb4ee6a4SAndroid Build Coastguard Worker         }
2658*bb4ee6a4SAndroid Build Coastguard Worker     }
2659*bb4ee6a4SAndroid Build Coastguard Worker 
getattr( &self, _ctx: Context, inode: Inode, _handle: Option<Handle>, ) -> io::Result<(libc::stat64, Duration)>2660*bb4ee6a4SAndroid Build Coastguard Worker     fn getattr(
2661*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2662*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2663*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2664*bb4ee6a4SAndroid Build Coastguard Worker         _handle: Option<Handle>,
2665*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<(libc::stat64, Duration)> {
2666*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "getattr", inode, _handle);
2667*bb4ee6a4SAndroid Build Coastguard Worker 
2668*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(inode)?;
2669*bb4ee6a4SAndroid Build Coastguard Worker         self.do_getattr(&data)
2670*bb4ee6a4SAndroid Build Coastguard Worker     }
2671*bb4ee6a4SAndroid Build Coastguard Worker 
setattr( &self, _ctx: Context, inode: Inode, attr: libc::stat64, handle: Option<Handle>, valid: SetattrValid, ) -> io::Result<(libc::stat64, Duration)>2672*bb4ee6a4SAndroid Build Coastguard Worker     fn setattr(
2673*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2674*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2675*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2676*bb4ee6a4SAndroid Build Coastguard Worker         attr: libc::stat64,
2677*bb4ee6a4SAndroid Build Coastguard Worker         handle: Option<Handle>,
2678*bb4ee6a4SAndroid Build Coastguard Worker         valid: SetattrValid,
2679*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<(libc::stat64, Duration)> {
2680*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "setattr", inode, handle);
2681*bb4ee6a4SAndroid Build Coastguard Worker         let inode_data = self.find_inode(inode)?;
2682*bb4ee6a4SAndroid Build Coastguard Worker 
2683*bb4ee6a4SAndroid Build Coastguard Worker         enum Data<'a> {
2684*bb4ee6a4SAndroid Build Coastguard Worker             Handle(MutexGuard<'a, File>),
2685*bb4ee6a4SAndroid Build Coastguard Worker             ProcPath(CString),
2686*bb4ee6a4SAndroid Build Coastguard Worker         }
2687*bb4ee6a4SAndroid Build Coastguard Worker 
2688*bb4ee6a4SAndroid Build Coastguard Worker         // If we have a handle then use it otherwise get a new fd from the inode.
2689*bb4ee6a4SAndroid Build Coastguard Worker         let hd;
2690*bb4ee6a4SAndroid Build Coastguard Worker         let data = if let Some(handle) = handle.filter(|&h| h != 0) {
2691*bb4ee6a4SAndroid Build Coastguard Worker             hd = self.find_handle(handle, inode)?;
2692*bb4ee6a4SAndroid Build Coastguard Worker             Data::Handle(hd.file.lock())
2693*bb4ee6a4SAndroid Build Coastguard Worker         } else {
2694*bb4ee6a4SAndroid Build Coastguard Worker             let pathname = CString::new(format!("self/fd/{}", inode_data.as_raw_descriptor()))
2695*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
2696*bb4ee6a4SAndroid Build Coastguard Worker             Data::ProcPath(pathname)
2697*bb4ee6a4SAndroid Build Coastguard Worker         };
2698*bb4ee6a4SAndroid Build Coastguard Worker 
2699*bb4ee6a4SAndroid Build Coastguard Worker         if valid.contains(SetattrValid::MODE) {
2700*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
2701*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(unsafe {
2702*bb4ee6a4SAndroid Build Coastguard Worker                 match data {
2703*bb4ee6a4SAndroid Build Coastguard Worker                     Data::Handle(ref fd) => libc::fchmod(fd.as_raw_descriptor(), attr.st_mode),
2704*bb4ee6a4SAndroid Build Coastguard Worker                     Data::ProcPath(ref p) => {
2705*bb4ee6a4SAndroid Build Coastguard Worker                         libc::fchmodat(self.proc.as_raw_descriptor(), p.as_ptr(), attr.st_mode, 0)
2706*bb4ee6a4SAndroid Build Coastguard Worker                     }
2707*bb4ee6a4SAndroid Build Coastguard Worker                 }
2708*bb4ee6a4SAndroid Build Coastguard Worker             })?;
2709*bb4ee6a4SAndroid Build Coastguard Worker         }
2710*bb4ee6a4SAndroid Build Coastguard Worker 
2711*bb4ee6a4SAndroid Build Coastguard Worker         if valid.intersects(SetattrValid::UID | SetattrValid::GID) {
2712*bb4ee6a4SAndroid Build Coastguard Worker             let uid = if valid.contains(SetattrValid::UID) {
2713*bb4ee6a4SAndroid Build Coastguard Worker                 attr.st_uid
2714*bb4ee6a4SAndroid Build Coastguard Worker             } else {
2715*bb4ee6a4SAndroid Build Coastguard Worker                 // Cannot use -1 here because these are unsigned values.
2716*bb4ee6a4SAndroid Build Coastguard Worker                 u32::MAX
2717*bb4ee6a4SAndroid Build Coastguard Worker             };
2718*bb4ee6a4SAndroid Build Coastguard Worker             let gid = if valid.contains(SetattrValid::GID) {
2719*bb4ee6a4SAndroid Build Coastguard Worker                 attr.st_gid
2720*bb4ee6a4SAndroid Build Coastguard Worker             } else {
2721*bb4ee6a4SAndroid Build Coastguard Worker                 // Cannot use -1 here because these are unsigned values.
2722*bb4ee6a4SAndroid Build Coastguard Worker                 u32::MAX
2723*bb4ee6a4SAndroid Build Coastguard Worker             };
2724*bb4ee6a4SAndroid Build Coastguard Worker 
2725*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
2726*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(unsafe {
2727*bb4ee6a4SAndroid Build Coastguard Worker                 libc::fchownat(
2728*bb4ee6a4SAndroid Build Coastguard Worker                     inode_data.as_raw_descriptor(),
2729*bb4ee6a4SAndroid Build Coastguard Worker                     EMPTY_CSTR.as_ptr(),
2730*bb4ee6a4SAndroid Build Coastguard Worker                     uid,
2731*bb4ee6a4SAndroid Build Coastguard Worker                     gid,
2732*bb4ee6a4SAndroid Build Coastguard Worker                     libc::AT_EMPTY_PATH | libc::AT_SYMLINK_NOFOLLOW,
2733*bb4ee6a4SAndroid Build Coastguard Worker                 )
2734*bb4ee6a4SAndroid Build Coastguard Worker             })?;
2735*bb4ee6a4SAndroid Build Coastguard Worker         }
2736*bb4ee6a4SAndroid Build Coastguard Worker 
2737*bb4ee6a4SAndroid Build Coastguard Worker         if valid.contains(SetattrValid::SIZE) {
2738*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(match data {
2739*bb4ee6a4SAndroid Build Coastguard Worker                 Data::Handle(ref fd) => {
2740*bb4ee6a4SAndroid Build Coastguard Worker                     // SAFETY: this doesn't modify any memory and we check the return value.
2741*bb4ee6a4SAndroid Build Coastguard Worker                     unsafe { libc::ftruncate64(fd.as_raw_descriptor(), attr.st_size) }
2742*bb4ee6a4SAndroid Build Coastguard Worker                 }
2743*bb4ee6a4SAndroid Build Coastguard Worker                 _ => {
2744*bb4ee6a4SAndroid Build Coastguard Worker                     // There is no `ftruncateat` so we need to get a new fd and truncate it.
2745*bb4ee6a4SAndroid Build Coastguard Worker                     let f = self.open_inode(&inode_data, libc::O_NONBLOCK | libc::O_RDWR)?;
2746*bb4ee6a4SAndroid Build Coastguard Worker                     // SAFETY: this doesn't modify any memory and we check the return value.
2747*bb4ee6a4SAndroid Build Coastguard Worker                     unsafe { libc::ftruncate64(f.as_raw_descriptor(), attr.st_size) }
2748*bb4ee6a4SAndroid Build Coastguard Worker                 }
2749*bb4ee6a4SAndroid Build Coastguard Worker             })?;
2750*bb4ee6a4SAndroid Build Coastguard Worker         }
2751*bb4ee6a4SAndroid Build Coastguard Worker 
2752*bb4ee6a4SAndroid Build Coastguard Worker         if valid.intersects(SetattrValid::ATIME | SetattrValid::MTIME) {
2753*bb4ee6a4SAndroid Build Coastguard Worker             let mut tvs = [
2754*bb4ee6a4SAndroid Build Coastguard Worker                 libc::timespec {
2755*bb4ee6a4SAndroid Build Coastguard Worker                     tv_sec: 0,
2756*bb4ee6a4SAndroid Build Coastguard Worker                     tv_nsec: libc::UTIME_OMIT,
2757*bb4ee6a4SAndroid Build Coastguard Worker                 },
2758*bb4ee6a4SAndroid Build Coastguard Worker                 libc::timespec {
2759*bb4ee6a4SAndroid Build Coastguard Worker                     tv_sec: 0,
2760*bb4ee6a4SAndroid Build Coastguard Worker                     tv_nsec: libc::UTIME_OMIT,
2761*bb4ee6a4SAndroid Build Coastguard Worker                 },
2762*bb4ee6a4SAndroid Build Coastguard Worker             ];
2763*bb4ee6a4SAndroid Build Coastguard Worker 
2764*bb4ee6a4SAndroid Build Coastguard Worker             if valid.contains(SetattrValid::ATIME_NOW) {
2765*bb4ee6a4SAndroid Build Coastguard Worker                 tvs[0].tv_nsec = libc::UTIME_NOW;
2766*bb4ee6a4SAndroid Build Coastguard Worker             } else if valid.contains(SetattrValid::ATIME) {
2767*bb4ee6a4SAndroid Build Coastguard Worker                 tvs[0].tv_sec = attr.st_atime;
2768*bb4ee6a4SAndroid Build Coastguard Worker                 tvs[0].tv_nsec = attr.st_atime_nsec;
2769*bb4ee6a4SAndroid Build Coastguard Worker             }
2770*bb4ee6a4SAndroid Build Coastguard Worker 
2771*bb4ee6a4SAndroid Build Coastguard Worker             if valid.contains(SetattrValid::MTIME_NOW) {
2772*bb4ee6a4SAndroid Build Coastguard Worker                 tvs[1].tv_nsec = libc::UTIME_NOW;
2773*bb4ee6a4SAndroid Build Coastguard Worker             } else if valid.contains(SetattrValid::MTIME) {
2774*bb4ee6a4SAndroid Build Coastguard Worker                 tvs[1].tv_sec = attr.st_mtime;
2775*bb4ee6a4SAndroid Build Coastguard Worker                 tvs[1].tv_nsec = attr.st_mtime_nsec;
2776*bb4ee6a4SAndroid Build Coastguard Worker             }
2777*bb4ee6a4SAndroid Build Coastguard Worker 
2778*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
2779*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(unsafe {
2780*bb4ee6a4SAndroid Build Coastguard Worker                 match data {
2781*bb4ee6a4SAndroid Build Coastguard Worker                     Data::Handle(ref fd) => libc::futimens(fd.as_raw_descriptor(), tvs.as_ptr()),
2782*bb4ee6a4SAndroid Build Coastguard Worker                     Data::ProcPath(ref p) => {
2783*bb4ee6a4SAndroid Build Coastguard Worker                         libc::utimensat(self.proc.as_raw_descriptor(), p.as_ptr(), tvs.as_ptr(), 0)
2784*bb4ee6a4SAndroid Build Coastguard Worker                     }
2785*bb4ee6a4SAndroid Build Coastguard Worker                 }
2786*bb4ee6a4SAndroid Build Coastguard Worker             })?;
2787*bb4ee6a4SAndroid Build Coastguard Worker         }
2788*bb4ee6a4SAndroid Build Coastguard Worker 
2789*bb4ee6a4SAndroid Build Coastguard Worker         self.do_getattr(&inode_data)
2790*bb4ee6a4SAndroid Build Coastguard Worker     }
2791*bb4ee6a4SAndroid Build Coastguard Worker 
rename( &self, _ctx: Context, olddir: Inode, oldname: &CStr, newdir: Inode, newname: &CStr, flags: u32, ) -> io::Result<()>2792*bb4ee6a4SAndroid Build Coastguard Worker     fn rename(
2793*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2794*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2795*bb4ee6a4SAndroid Build Coastguard Worker         olddir: Inode,
2796*bb4ee6a4SAndroid Build Coastguard Worker         oldname: &CStr,
2797*bb4ee6a4SAndroid Build Coastguard Worker         newdir: Inode,
2798*bb4ee6a4SAndroid Build Coastguard Worker         newname: &CStr,
2799*bb4ee6a4SAndroid Build Coastguard Worker         flags: u32,
2800*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<()> {
2801*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "rename", olddir, oldname, newdir, newname, flags);
2802*bb4ee6a4SAndroid Build Coastguard Worker 
2803*bb4ee6a4SAndroid Build Coastguard Worker         let old_inode = self.find_inode(olddir)?;
2804*bb4ee6a4SAndroid Build Coastguard Worker         let new_inode = self.find_inode(newdir)?;
2805*bb4ee6a4SAndroid Build Coastguard Worker         {
2806*bb4ee6a4SAndroid Build Coastguard Worker             let casefold_cache = self.lock_casefold_lookup_caches();
2807*bb4ee6a4SAndroid Build Coastguard Worker 
2808*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
2809*bb4ee6a4SAndroid Build Coastguard Worker             // TODO: Switch to libc::renameat2 once https://github.com/rust-lang/libc/pull/1508 lands
2810*bb4ee6a4SAndroid Build Coastguard Worker             // and we have glibc 2.28.
2811*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(unsafe {
2812*bb4ee6a4SAndroid Build Coastguard Worker                 libc::syscall(
2813*bb4ee6a4SAndroid Build Coastguard Worker                     libc::SYS_renameat2,
2814*bb4ee6a4SAndroid Build Coastguard Worker                     old_inode.as_raw_descriptor(),
2815*bb4ee6a4SAndroid Build Coastguard Worker                     oldname.as_ptr(),
2816*bb4ee6a4SAndroid Build Coastguard Worker                     new_inode.as_raw_descriptor(),
2817*bb4ee6a4SAndroid Build Coastguard Worker                     newname.as_ptr(),
2818*bb4ee6a4SAndroid Build Coastguard Worker                     flags,
2819*bb4ee6a4SAndroid Build Coastguard Worker                 )
2820*bb4ee6a4SAndroid Build Coastguard Worker             })?;
2821*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(mut c) = casefold_cache {
2822*bb4ee6a4SAndroid Build Coastguard Worker                 c.remove(olddir, oldname);
2823*bb4ee6a4SAndroid Build Coastguard Worker                 c.insert(newdir, newname);
2824*bb4ee6a4SAndroid Build Coastguard Worker             }
2825*bb4ee6a4SAndroid Build Coastguard Worker         }
2826*bb4ee6a4SAndroid Build Coastguard Worker 
2827*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
2828*bb4ee6a4SAndroid Build Coastguard Worker     }
2829*bb4ee6a4SAndroid Build Coastguard Worker 
mknod( &self, ctx: Context, parent: Inode, name: &CStr, mode: u32, rdev: u32, umask: u32, security_ctx: Option<&CStr>, ) -> io::Result<Entry>2830*bb4ee6a4SAndroid Build Coastguard Worker     fn mknod(
2831*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2832*bb4ee6a4SAndroid Build Coastguard Worker         ctx: Context,
2833*bb4ee6a4SAndroid Build Coastguard Worker         parent: Inode,
2834*bb4ee6a4SAndroid Build Coastguard Worker         name: &CStr,
2835*bb4ee6a4SAndroid Build Coastguard Worker         mode: u32,
2836*bb4ee6a4SAndroid Build Coastguard Worker         rdev: u32,
2837*bb4ee6a4SAndroid Build Coastguard Worker         umask: u32,
2838*bb4ee6a4SAndroid Build Coastguard Worker         security_ctx: Option<&CStr>,
2839*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<Entry> {
2840*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(
2841*bb4ee6a4SAndroid Build Coastguard Worker             self.tag,
2842*bb4ee6a4SAndroid Build Coastguard Worker             "mknod",
2843*bb4ee6a4SAndroid Build Coastguard Worker             parent,
2844*bb4ee6a4SAndroid Build Coastguard Worker             name,
2845*bb4ee6a4SAndroid Build Coastguard Worker             mode,
2846*bb4ee6a4SAndroid Build Coastguard Worker             rdev,
2847*bb4ee6a4SAndroid Build Coastguard Worker             umask,
2848*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx
2849*bb4ee6a4SAndroid Build Coastguard Worker         );
2850*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(parent)?;
2851*bb4ee6a4SAndroid Build Coastguard Worker 
2852*bb4ee6a4SAndroid Build Coastguard Worker         let _ctx = security_ctx
2853*bb4ee6a4SAndroid Build Coastguard Worker             .filter(|ctx| *ctx != UNLABELED_CSTR)
2854*bb4ee6a4SAndroid Build Coastguard Worker             .map(|ctx| ScopedSecurityContext::new(&self.proc, ctx))
2855*bb4ee6a4SAndroid Build Coastguard Worker             .transpose()?;
2856*bb4ee6a4SAndroid Build Coastguard Worker 
2857*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(unused_variables)]
2858*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
2859*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_creds(&ctx, &data, name);
2860*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "fs_runtime_ugid_map")]
2861*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_ugid_creds(&ctx, &data, name);
2862*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(feature = "fs_permission_translation"))]
2863*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = (ctx.uid, ctx.gid);
2864*bb4ee6a4SAndroid Build Coastguard Worker 
2865*bb4ee6a4SAndroid Build Coastguard Worker         let (_uid, _gid) = set_creds(uid, gid)?;
2866*bb4ee6a4SAndroid Build Coastguard Worker         {
2867*bb4ee6a4SAndroid Build Coastguard Worker             let _scoped_umask = ScopedUmask::new(umask);
2868*bb4ee6a4SAndroid Build Coastguard Worker             let casefold_cache = self.lock_casefold_lookup_caches();
2869*bb4ee6a4SAndroid Build Coastguard Worker 
2870*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
2871*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(unsafe {
2872*bb4ee6a4SAndroid Build Coastguard Worker                 libc::mknodat(
2873*bb4ee6a4SAndroid Build Coastguard Worker                     data.as_raw_descriptor(),
2874*bb4ee6a4SAndroid Build Coastguard Worker                     name.as_ptr(),
2875*bb4ee6a4SAndroid Build Coastguard Worker                     mode as libc::mode_t,
2876*bb4ee6a4SAndroid Build Coastguard Worker                     rdev as libc::dev_t,
2877*bb4ee6a4SAndroid Build Coastguard Worker                 )
2878*bb4ee6a4SAndroid Build Coastguard Worker             })?;
2879*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(mut c) = casefold_cache {
2880*bb4ee6a4SAndroid Build Coastguard Worker                 c.insert(parent, name);
2881*bb4ee6a4SAndroid Build Coastguard Worker             }
2882*bb4ee6a4SAndroid Build Coastguard Worker         }
2883*bb4ee6a4SAndroid Build Coastguard Worker 
2884*bb4ee6a4SAndroid Build Coastguard Worker         self.do_lookup(&data, name)
2885*bb4ee6a4SAndroid Build Coastguard Worker     }
2886*bb4ee6a4SAndroid Build Coastguard Worker 
link( &self, _ctx: Context, inode: Inode, newparent: Inode, newname: &CStr, ) -> io::Result<Entry>2887*bb4ee6a4SAndroid Build Coastguard Worker     fn link(
2888*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2889*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2890*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2891*bb4ee6a4SAndroid Build Coastguard Worker         newparent: Inode,
2892*bb4ee6a4SAndroid Build Coastguard Worker         newname: &CStr,
2893*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<Entry> {
2894*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "link", inode, newparent, newname);
2895*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(inode)?;
2896*bb4ee6a4SAndroid Build Coastguard Worker         let new_inode = self.find_inode(newparent)?;
2897*bb4ee6a4SAndroid Build Coastguard Worker 
2898*bb4ee6a4SAndroid Build Coastguard Worker         let path = CString::new(format!("self/fd/{}", data.as_raw_descriptor()))
2899*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
2900*bb4ee6a4SAndroid Build Coastguard Worker 
2901*bb4ee6a4SAndroid Build Coastguard Worker         {
2902*bb4ee6a4SAndroid Build Coastguard Worker             let casefold_cache = self.lock_casefold_lookup_caches();
2903*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
2904*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(unsafe {
2905*bb4ee6a4SAndroid Build Coastguard Worker                 libc::linkat(
2906*bb4ee6a4SAndroid Build Coastguard Worker                     self.proc.as_raw_descriptor(),
2907*bb4ee6a4SAndroid Build Coastguard Worker                     path.as_ptr(),
2908*bb4ee6a4SAndroid Build Coastguard Worker                     new_inode.as_raw_descriptor(),
2909*bb4ee6a4SAndroid Build Coastguard Worker                     newname.as_ptr(),
2910*bb4ee6a4SAndroid Build Coastguard Worker                     libc::AT_SYMLINK_FOLLOW,
2911*bb4ee6a4SAndroid Build Coastguard Worker                 )
2912*bb4ee6a4SAndroid Build Coastguard Worker             })?;
2913*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(mut c) = casefold_cache {
2914*bb4ee6a4SAndroid Build Coastguard Worker                 c.insert(newparent, newname);
2915*bb4ee6a4SAndroid Build Coastguard Worker             }
2916*bb4ee6a4SAndroid Build Coastguard Worker         }
2917*bb4ee6a4SAndroid Build Coastguard Worker 
2918*bb4ee6a4SAndroid Build Coastguard Worker         self.do_lookup(&new_inode, newname)
2919*bb4ee6a4SAndroid Build Coastguard Worker     }
2920*bb4ee6a4SAndroid Build Coastguard Worker 
symlink( &self, ctx: Context, linkname: &CStr, parent: Inode, name: &CStr, security_ctx: Option<&CStr>, ) -> io::Result<Entry>2921*bb4ee6a4SAndroid Build Coastguard Worker     fn symlink(
2922*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2923*bb4ee6a4SAndroid Build Coastguard Worker         ctx: Context,
2924*bb4ee6a4SAndroid Build Coastguard Worker         linkname: &CStr,
2925*bb4ee6a4SAndroid Build Coastguard Worker         parent: Inode,
2926*bb4ee6a4SAndroid Build Coastguard Worker         name: &CStr,
2927*bb4ee6a4SAndroid Build Coastguard Worker         security_ctx: Option<&CStr>,
2928*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<Entry> {
2929*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "symlink", parent, linkname, name, security_ctx);
2930*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(parent)?;
2931*bb4ee6a4SAndroid Build Coastguard Worker 
2932*bb4ee6a4SAndroid Build Coastguard Worker         let _ctx = security_ctx
2933*bb4ee6a4SAndroid Build Coastguard Worker             .filter(|ctx| *ctx != UNLABELED_CSTR)
2934*bb4ee6a4SAndroid Build Coastguard Worker             .map(|ctx| ScopedSecurityContext::new(&self.proc, ctx))
2935*bb4ee6a4SAndroid Build Coastguard Worker             .transpose()?;
2936*bb4ee6a4SAndroid Build Coastguard Worker 
2937*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(unused_variables)]
2938*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
2939*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_creds(&ctx, &data, name);
2940*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "fs_runtime_ugid_map")]
2941*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_ugid_creds(&ctx, &data, name);
2942*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(feature = "fs_permission_translation"))]
2943*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = (ctx.uid, ctx.gid);
2944*bb4ee6a4SAndroid Build Coastguard Worker 
2945*bb4ee6a4SAndroid Build Coastguard Worker         let (_uid, _gid) = set_creds(uid, gid)?;
2946*bb4ee6a4SAndroid Build Coastguard Worker         {
2947*bb4ee6a4SAndroid Build Coastguard Worker             let casefold_cache = self.lock_casefold_lookup_caches();
2948*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this doesn't modify any memory and we check the return value.
2949*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(unsafe {
2950*bb4ee6a4SAndroid Build Coastguard Worker                 libc::symlinkat(linkname.as_ptr(), data.as_raw_descriptor(), name.as_ptr())
2951*bb4ee6a4SAndroid Build Coastguard Worker             })?;
2952*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(mut c) = casefold_cache {
2953*bb4ee6a4SAndroid Build Coastguard Worker                 c.insert(parent, name);
2954*bb4ee6a4SAndroid Build Coastguard Worker             }
2955*bb4ee6a4SAndroid Build Coastguard Worker         }
2956*bb4ee6a4SAndroid Build Coastguard Worker 
2957*bb4ee6a4SAndroid Build Coastguard Worker         self.do_lookup(&data, name)
2958*bb4ee6a4SAndroid Build Coastguard Worker     }
2959*bb4ee6a4SAndroid Build Coastguard Worker 
readlink(&self, _ctx: Context, inode: Inode) -> io::Result<Vec<u8>>2960*bb4ee6a4SAndroid Build Coastguard Worker     fn readlink(&self, _ctx: Context, inode: Inode) -> io::Result<Vec<u8>> {
2961*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "readlink", inode);
2962*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(inode)?;
2963*bb4ee6a4SAndroid Build Coastguard Worker 
2964*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; libc::PATH_MAX as usize];
2965*bb4ee6a4SAndroid Build Coastguard Worker 
2966*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this will only modify the contents of `buf` and we check the return value.
2967*bb4ee6a4SAndroid Build Coastguard Worker         let res = syscall!(unsafe {
2968*bb4ee6a4SAndroid Build Coastguard Worker             libc::readlinkat(
2969*bb4ee6a4SAndroid Build Coastguard Worker                 data.as_raw_descriptor(),
2970*bb4ee6a4SAndroid Build Coastguard Worker                 EMPTY_CSTR.as_ptr(),
2971*bb4ee6a4SAndroid Build Coastguard Worker                 buf.as_mut_ptr() as *mut libc::c_char,
2972*bb4ee6a4SAndroid Build Coastguard Worker                 buf.len(),
2973*bb4ee6a4SAndroid Build Coastguard Worker             )
2974*bb4ee6a4SAndroid Build Coastguard Worker         })?;
2975*bb4ee6a4SAndroid Build Coastguard Worker 
2976*bb4ee6a4SAndroid Build Coastguard Worker         buf.resize(res as usize, 0);
2977*bb4ee6a4SAndroid Build Coastguard Worker 
2978*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "fs_runtime_ugid_map")]
2979*bb4ee6a4SAndroid Build Coastguard Worker         {
2980*bb4ee6a4SAndroid Build Coastguard Worker             let link_target = Path::new(OsStr::from_bytes(&buf[..res as usize]));
2981*bb4ee6a4SAndroid Build Coastguard Worker             if !link_target.starts_with(&self.root_dir) {
2982*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(io::Error::new(
2983*bb4ee6a4SAndroid Build Coastguard Worker                     io::ErrorKind::InvalidInput,
2984*bb4ee6a4SAndroid Build Coastguard Worker                     "Symbolic link points outside of root_dir",
2985*bb4ee6a4SAndroid Build Coastguard Worker                 ));
2986*bb4ee6a4SAndroid Build Coastguard Worker             }
2987*bb4ee6a4SAndroid Build Coastguard Worker         }
2988*bb4ee6a4SAndroid Build Coastguard Worker         Ok(buf)
2989*bb4ee6a4SAndroid Build Coastguard Worker     }
2990*bb4ee6a4SAndroid Build Coastguard Worker 
flush( &self, _ctx: Context, inode: Inode, handle: Handle, _lock_owner: u64, ) -> io::Result<()>2991*bb4ee6a4SAndroid Build Coastguard Worker     fn flush(
2992*bb4ee6a4SAndroid Build Coastguard Worker         &self,
2993*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
2994*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
2995*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
2996*bb4ee6a4SAndroid Build Coastguard Worker         _lock_owner: u64,
2997*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<()> {
2998*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "flush", inode, handle);
2999*bb4ee6a4SAndroid Build Coastguard Worker         let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
3000*bb4ee6a4SAndroid Build Coastguard Worker             self.find_inode(inode)?
3001*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3002*bb4ee6a4SAndroid Build Coastguard Worker             self.find_handle(handle, inode)?
3003*bb4ee6a4SAndroid Build Coastguard Worker         };
3004*bb4ee6a4SAndroid Build Coastguard Worker 
3005*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
3006*bb4ee6a4SAndroid Build Coastguard Worker         // Since this method is called whenever an fd is closed in the client, we can emulate that
3007*bb4ee6a4SAndroid Build Coastguard Worker         // behavior by doing the same thing (dup-ing the fd and then immediately closing it). Safe
3008*bb4ee6a4SAndroid Build Coastguard Worker         // because this doesn't modify any memory and we check the return values.
3009*bb4ee6a4SAndroid Build Coastguard Worker         unsafe {
3010*bb4ee6a4SAndroid Build Coastguard Worker             let newfd = syscall!(libc::fcntl(
3011*bb4ee6a4SAndroid Build Coastguard Worker                 data.as_raw_descriptor(),
3012*bb4ee6a4SAndroid Build Coastguard Worker                 libc::F_DUPFD_CLOEXEC,
3013*bb4ee6a4SAndroid Build Coastguard Worker                 0
3014*bb4ee6a4SAndroid Build Coastguard Worker             ))?;
3015*bb4ee6a4SAndroid Build Coastguard Worker 
3016*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(libc::close(newfd))?;
3017*bb4ee6a4SAndroid Build Coastguard Worker         }
3018*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
3019*bb4ee6a4SAndroid Build Coastguard Worker     }
3020*bb4ee6a4SAndroid Build Coastguard Worker 
fsync(&self, _ctx: Context, inode: Inode, datasync: bool, handle: Handle) -> io::Result<()>3021*bb4ee6a4SAndroid Build Coastguard Worker     fn fsync(&self, _ctx: Context, inode: Inode, datasync: bool, handle: Handle) -> io::Result<()> {
3022*bb4ee6a4SAndroid Build Coastguard Worker         if self.zero_message_open.load(Ordering::Relaxed) {
3023*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "fsync (zero-message)", inode, datasync, handle);
3024*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_inode(inode)?;
3025*bb4ee6a4SAndroid Build Coastguard Worker             self.do_fsync(&*data, datasync)
3026*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3027*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "fsync", inode, datasync, handle);
3028*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_handle(handle, inode)?;
3029*bb4ee6a4SAndroid Build Coastguard Worker 
3030*bb4ee6a4SAndroid Build Coastguard Worker             let file = data.file.lock();
3031*bb4ee6a4SAndroid Build Coastguard Worker             self.do_fsync(&*file, datasync)
3032*bb4ee6a4SAndroid Build Coastguard Worker         }
3033*bb4ee6a4SAndroid Build Coastguard Worker     }
3034*bb4ee6a4SAndroid Build Coastguard Worker 
fsyncdir( &self, _ctx: Context, inode: Inode, datasync: bool, handle: Handle, ) -> io::Result<()>3035*bb4ee6a4SAndroid Build Coastguard Worker     fn fsyncdir(
3036*bb4ee6a4SAndroid Build Coastguard Worker         &self,
3037*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
3038*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
3039*bb4ee6a4SAndroid Build Coastguard Worker         datasync: bool,
3040*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
3041*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<()> {
3042*bb4ee6a4SAndroid Build Coastguard Worker         if self.zero_message_opendir.load(Ordering::Relaxed) {
3043*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "fsyncdir (zero-message)", inode, datasync, handle);
3044*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_inode(inode)?;
3045*bb4ee6a4SAndroid Build Coastguard Worker             self.do_fsync(&*data, datasync)
3046*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3047*bb4ee6a4SAndroid Build Coastguard Worker             let _trace = fs_trace!(self.tag, "fsyncdir", inode, datasync, handle);
3048*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_handle(handle, inode)?;
3049*bb4ee6a4SAndroid Build Coastguard Worker 
3050*bb4ee6a4SAndroid Build Coastguard Worker             let file = data.file.lock();
3051*bb4ee6a4SAndroid Build Coastguard Worker             self.do_fsync(&*file, datasync)
3052*bb4ee6a4SAndroid Build Coastguard Worker         }
3053*bb4ee6a4SAndroid Build Coastguard Worker     }
3054*bb4ee6a4SAndroid Build Coastguard Worker 
access(&self, ctx: Context, inode: Inode, mask: u32) -> io::Result<()>3055*bb4ee6a4SAndroid Build Coastguard Worker     fn access(&self, ctx: Context, inode: Inode, mask: u32) -> io::Result<()> {
3056*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "access", inode, mask);
3057*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(inode)?;
3058*bb4ee6a4SAndroid Build Coastguard Worker 
3059*bb4ee6a4SAndroid Build Coastguard Worker         let st = stat(&*data)?;
3060*bb4ee6a4SAndroid Build Coastguard Worker         let mode = mask as i32 & (libc::R_OK | libc::W_OK | libc::X_OK);
3061*bb4ee6a4SAndroid Build Coastguard Worker 
3062*bb4ee6a4SAndroid Build Coastguard Worker         if mode == libc::F_OK {
3063*bb4ee6a4SAndroid Build Coastguard Worker             // The file exists since we were able to call `stat(2)` on it.
3064*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(());
3065*bb4ee6a4SAndroid Build Coastguard Worker         }
3066*bb4ee6a4SAndroid Build Coastguard Worker 
3067*bb4ee6a4SAndroid Build Coastguard Worker         if (mode & libc::R_OK) != 0 {
3068*bb4ee6a4SAndroid Build Coastguard Worker             if ctx.uid != 0
3069*bb4ee6a4SAndroid Build Coastguard Worker                 && (st.st_uid != ctx.uid || st.st_mode & 0o400 == 0)
3070*bb4ee6a4SAndroid Build Coastguard Worker                 && (st.st_gid != ctx.gid || st.st_mode & 0o040 == 0)
3071*bb4ee6a4SAndroid Build Coastguard Worker                 && st.st_mode & 0o004 == 0
3072*bb4ee6a4SAndroid Build Coastguard Worker             {
3073*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(io::Error::from_raw_os_error(libc::EACCES));
3074*bb4ee6a4SAndroid Build Coastguard Worker             }
3075*bb4ee6a4SAndroid Build Coastguard Worker         }
3076*bb4ee6a4SAndroid Build Coastguard Worker 
3077*bb4ee6a4SAndroid Build Coastguard Worker         if (mode & libc::W_OK) != 0 {
3078*bb4ee6a4SAndroid Build Coastguard Worker             if ctx.uid != 0
3079*bb4ee6a4SAndroid Build Coastguard Worker                 && (st.st_uid != ctx.uid || st.st_mode & 0o200 == 0)
3080*bb4ee6a4SAndroid Build Coastguard Worker                 && (st.st_gid != ctx.gid || st.st_mode & 0o020 == 0)
3081*bb4ee6a4SAndroid Build Coastguard Worker                 && st.st_mode & 0o002 == 0
3082*bb4ee6a4SAndroid Build Coastguard Worker             {
3083*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(io::Error::from_raw_os_error(libc::EACCES));
3084*bb4ee6a4SAndroid Build Coastguard Worker             }
3085*bb4ee6a4SAndroid Build Coastguard Worker         }
3086*bb4ee6a4SAndroid Build Coastguard Worker 
3087*bb4ee6a4SAndroid Build Coastguard Worker         // root can only execute something if it is executable by one of the owner, the group, or
3088*bb4ee6a4SAndroid Build Coastguard Worker         // everyone.
3089*bb4ee6a4SAndroid Build Coastguard Worker         if (mode & libc::X_OK) != 0 {
3090*bb4ee6a4SAndroid Build Coastguard Worker             if (ctx.uid != 0 || st.st_mode & 0o111 == 0)
3091*bb4ee6a4SAndroid Build Coastguard Worker                 && (st.st_uid != ctx.uid || st.st_mode & 0o100 == 0)
3092*bb4ee6a4SAndroid Build Coastguard Worker                 && (st.st_gid != ctx.gid || st.st_mode & 0o010 == 0)
3093*bb4ee6a4SAndroid Build Coastguard Worker                 && st.st_mode & 0o001 == 0
3094*bb4ee6a4SAndroid Build Coastguard Worker             {
3095*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(io::Error::from_raw_os_error(libc::EACCES));
3096*bb4ee6a4SAndroid Build Coastguard Worker             }
3097*bb4ee6a4SAndroid Build Coastguard Worker         }
3098*bb4ee6a4SAndroid Build Coastguard Worker 
3099*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
3100*bb4ee6a4SAndroid Build Coastguard Worker     }
3101*bb4ee6a4SAndroid Build Coastguard Worker 
setxattr( &self, _ctx: Context, inode: Inode, name: &CStr, value: &[u8], flags: u32, ) -> io::Result<()>3102*bb4ee6a4SAndroid Build Coastguard Worker     fn setxattr(
3103*bb4ee6a4SAndroid Build Coastguard Worker         &self,
3104*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
3105*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
3106*bb4ee6a4SAndroid Build Coastguard Worker         name: &CStr,
3107*bb4ee6a4SAndroid Build Coastguard Worker         value: &[u8],
3108*bb4ee6a4SAndroid Build Coastguard Worker         flags: u32,
3109*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<()> {
3110*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "setxattr", inode, name, flags);
3111*bb4ee6a4SAndroid Build Coastguard Worker         // We can't allow the VM to set this xattr because an unprivileged process may use it to set
3112*bb4ee6a4SAndroid Build Coastguard Worker         // a privileged xattr.
3113*bb4ee6a4SAndroid Build Coastguard Worker         if self.cfg.rewrite_security_xattrs && name.to_bytes().starts_with(USER_VIRTIOFS_XATTR) {
3114*bb4ee6a4SAndroid Build Coastguard Worker             return Err(io::Error::from_raw_os_error(libc::EPERM));
3115*bb4ee6a4SAndroid Build Coastguard Worker         }
3116*bb4ee6a4SAndroid Build Coastguard Worker 
3117*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(inode)?;
3118*bb4ee6a4SAndroid Build Coastguard Worker         let name = self.rewrite_xattr_name(name);
3119*bb4ee6a4SAndroid Build Coastguard Worker 
3120*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
3121*bb4ee6a4SAndroid Build Coastguard Worker         if self.skip_host_set_xattr(&data.path, &name.to_string_lossy()) {
3122*bb4ee6a4SAndroid Build Coastguard Worker             debug!(
3123*bb4ee6a4SAndroid Build Coastguard Worker                 "ignore setxattr for path:{} xattr_name:{}",
3124*bb4ee6a4SAndroid Build Coastguard Worker                 &data.path,
3125*bb4ee6a4SAndroid Build Coastguard Worker                 &name.to_string_lossy()
3126*bb4ee6a4SAndroid Build Coastguard Worker             );
3127*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(());
3128*bb4ee6a4SAndroid Build Coastguard Worker         }
3129*bb4ee6a4SAndroid Build Coastguard Worker 
3130*bb4ee6a4SAndroid Build Coastguard Worker         let file = data.file.lock();
3131*bb4ee6a4SAndroid Build Coastguard Worker         let o_path_file = (file.1 & libc::O_PATH) != 0;
3132*bb4ee6a4SAndroid Build Coastguard Worker         if o_path_file {
3133*bb4ee6a4SAndroid Build Coastguard Worker             // For FDs opened with `O_PATH`, we cannot call `fsetxattr` normally. Instead we emulate
3134*bb4ee6a4SAndroid Build Coastguard Worker             // an _at syscall by changing the CWD to /proc, running the path based syscall, and then
3135*bb4ee6a4SAndroid Build Coastguard Worker             // setting the CWD back to the root directory.
3136*bb4ee6a4SAndroid Build Coastguard Worker             let path = CString::new(format!("self/fd/{}", file.0.as_raw_descriptor()))
3137*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
3138*bb4ee6a4SAndroid Build Coastguard Worker 
3139*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(self.with_proc_chdir(|| {
3140*bb4ee6a4SAndroid Build Coastguard Worker                 // SAFETY: this doesn't modify any memory and we check the return value.
3141*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe {
3142*bb4ee6a4SAndroid Build Coastguard Worker                     libc::setxattr(
3143*bb4ee6a4SAndroid Build Coastguard Worker                         path.as_ptr(),
3144*bb4ee6a4SAndroid Build Coastguard Worker                         name.as_ptr(),
3145*bb4ee6a4SAndroid Build Coastguard Worker                         value.as_ptr() as *const libc::c_void,
3146*bb4ee6a4SAndroid Build Coastguard Worker                         value.len() as libc::size_t,
3147*bb4ee6a4SAndroid Build Coastguard Worker                         flags as c_int,
3148*bb4ee6a4SAndroid Build Coastguard Worker                     )
3149*bb4ee6a4SAndroid Build Coastguard Worker                 }
3150*bb4ee6a4SAndroid Build Coastguard Worker             }))?;
3151*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3152*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(
3153*bb4ee6a4SAndroid Build Coastguard Worker                 // For regular files and directories, we can just use fsetxattr.
3154*bb4ee6a4SAndroid Build Coastguard Worker                 // SAFETY: this doesn't modify any memory and we check the return value.
3155*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe {
3156*bb4ee6a4SAndroid Build Coastguard Worker                     libc::fsetxattr(
3157*bb4ee6a4SAndroid Build Coastguard Worker                         file.0.as_raw_descriptor(),
3158*bb4ee6a4SAndroid Build Coastguard Worker                         name.as_ptr(),
3159*bb4ee6a4SAndroid Build Coastguard Worker                         value.as_ptr() as *const libc::c_void,
3160*bb4ee6a4SAndroid Build Coastguard Worker                         value.len() as libc::size_t,
3161*bb4ee6a4SAndroid Build Coastguard Worker                         flags as c_int,
3162*bb4ee6a4SAndroid Build Coastguard Worker                     )
3163*bb4ee6a4SAndroid Build Coastguard Worker                 }
3164*bb4ee6a4SAndroid Build Coastguard Worker             )?;
3165*bb4ee6a4SAndroid Build Coastguard Worker         }
3166*bb4ee6a4SAndroid Build Coastguard Worker 
3167*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
3168*bb4ee6a4SAndroid Build Coastguard Worker     }
3169*bb4ee6a4SAndroid Build Coastguard Worker 
getxattr( &self, _ctx: Context, inode: Inode, name: &CStr, size: u32, ) -> io::Result<GetxattrReply>3170*bb4ee6a4SAndroid Build Coastguard Worker     fn getxattr(
3171*bb4ee6a4SAndroid Build Coastguard Worker         &self,
3172*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
3173*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
3174*bb4ee6a4SAndroid Build Coastguard Worker         name: &CStr,
3175*bb4ee6a4SAndroid Build Coastguard Worker         size: u32,
3176*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<GetxattrReply> {
3177*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "getxattr", inode, name, size);
3178*bb4ee6a4SAndroid Build Coastguard Worker         // We don't allow the VM to set this xattr so we also pretend there is no value associated
3179*bb4ee6a4SAndroid Build Coastguard Worker         // with it.
3180*bb4ee6a4SAndroid Build Coastguard Worker         if self.cfg.rewrite_security_xattrs && name.to_bytes().starts_with(USER_VIRTIOFS_XATTR) {
3181*bb4ee6a4SAndroid Build Coastguard Worker             return Err(io::Error::from_raw_os_error(libc::ENODATA));
3182*bb4ee6a4SAndroid Build Coastguard Worker         }
3183*bb4ee6a4SAndroid Build Coastguard Worker 
3184*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(inode)?;
3185*bb4ee6a4SAndroid Build Coastguard Worker         let name = self.rewrite_xattr_name(name);
3186*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0u8; size as usize];
3187*bb4ee6a4SAndroid Build Coastguard Worker 
3188*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
3189*bb4ee6a4SAndroid Build Coastguard Worker         let res = self.do_getxattr_with_filter(data, name, &mut buf)?;
3190*bb4ee6a4SAndroid Build Coastguard Worker 
3191*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(feature = "arc_quota"))]
3192*bb4ee6a4SAndroid Build Coastguard Worker         let res = self.do_getxattr(&data, &name, &mut buf[..])?;
3193*bb4ee6a4SAndroid Build Coastguard Worker 
3194*bb4ee6a4SAndroid Build Coastguard Worker         if size == 0 {
3195*bb4ee6a4SAndroid Build Coastguard Worker             Ok(GetxattrReply::Count(res as u32))
3196*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3197*bb4ee6a4SAndroid Build Coastguard Worker             buf.truncate(res);
3198*bb4ee6a4SAndroid Build Coastguard Worker             Ok(GetxattrReply::Value(buf))
3199*bb4ee6a4SAndroid Build Coastguard Worker         }
3200*bb4ee6a4SAndroid Build Coastguard Worker     }
3201*bb4ee6a4SAndroid Build Coastguard Worker 
listxattr(&self, _ctx: Context, inode: Inode, size: u32) -> io::Result<ListxattrReply>3202*bb4ee6a4SAndroid Build Coastguard Worker     fn listxattr(&self, _ctx: Context, inode: Inode, size: u32) -> io::Result<ListxattrReply> {
3203*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "listxattr", inode, size);
3204*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(inode)?;
3205*bb4ee6a4SAndroid Build Coastguard Worker 
3206*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0u8; size as usize];
3207*bb4ee6a4SAndroid Build Coastguard Worker 
3208*bb4ee6a4SAndroid Build Coastguard Worker         let file = data.file.lock();
3209*bb4ee6a4SAndroid Build Coastguard Worker         let o_path_file = (file.1 & libc::O_PATH) != 0;
3210*bb4ee6a4SAndroid Build Coastguard Worker         let res = if o_path_file {
3211*bb4ee6a4SAndroid Build Coastguard Worker             // For FDs opened with `O_PATH`, we cannot call `flistxattr` normally. Instead we
3212*bb4ee6a4SAndroid Build Coastguard Worker             // emulate an _at syscall by changing the CWD to /proc, running the path based syscall,
3213*bb4ee6a4SAndroid Build Coastguard Worker             // and then setting the CWD back to the root directory.
3214*bb4ee6a4SAndroid Build Coastguard Worker             let path = CString::new(format!("self/fd/{}", file.0.as_raw_descriptor()))
3215*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
3216*bb4ee6a4SAndroid Build Coastguard Worker 
3217*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this will only modify `buf` and we check the return value.
3218*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(self.with_proc_chdir(|| unsafe {
3219*bb4ee6a4SAndroid Build Coastguard Worker                 libc::listxattr(
3220*bb4ee6a4SAndroid Build Coastguard Worker                     path.as_ptr(),
3221*bb4ee6a4SAndroid Build Coastguard Worker                     buf.as_mut_ptr() as *mut libc::c_char,
3222*bb4ee6a4SAndroid Build Coastguard Worker                     buf.len() as libc::size_t,
3223*bb4ee6a4SAndroid Build Coastguard Worker                 )
3224*bb4ee6a4SAndroid Build Coastguard Worker             }))?
3225*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3226*bb4ee6a4SAndroid Build Coastguard Worker             // For regular files and directories, we can just flistxattr.
3227*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this will only write to `buf` and we check the return value.
3228*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(unsafe {
3229*bb4ee6a4SAndroid Build Coastguard Worker                 libc::flistxattr(
3230*bb4ee6a4SAndroid Build Coastguard Worker                     file.0.as_raw_descriptor(),
3231*bb4ee6a4SAndroid Build Coastguard Worker                     buf.as_mut_ptr() as *mut libc::c_char,
3232*bb4ee6a4SAndroid Build Coastguard Worker                     buf.len() as libc::size_t,
3233*bb4ee6a4SAndroid Build Coastguard Worker                 )
3234*bb4ee6a4SAndroid Build Coastguard Worker             })?
3235*bb4ee6a4SAndroid Build Coastguard Worker         };
3236*bb4ee6a4SAndroid Build Coastguard Worker 
3237*bb4ee6a4SAndroid Build Coastguard Worker         if size == 0 {
3238*bb4ee6a4SAndroid Build Coastguard Worker             Ok(ListxattrReply::Count(res as u32))
3239*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3240*bb4ee6a4SAndroid Build Coastguard Worker             buf.truncate(res as usize);
3241*bb4ee6a4SAndroid Build Coastguard Worker 
3242*bb4ee6a4SAndroid Build Coastguard Worker             if self.cfg.rewrite_security_xattrs {
3243*bb4ee6a4SAndroid Build Coastguard Worker                 strip_xattr_prefix(&mut buf);
3244*bb4ee6a4SAndroid Build Coastguard Worker             }
3245*bb4ee6a4SAndroid Build Coastguard Worker             Ok(ListxattrReply::Names(buf))
3246*bb4ee6a4SAndroid Build Coastguard Worker         }
3247*bb4ee6a4SAndroid Build Coastguard Worker     }
3248*bb4ee6a4SAndroid Build Coastguard Worker 
removexattr(&self, _ctx: Context, inode: Inode, name: &CStr) -> io::Result<()>3249*bb4ee6a4SAndroid Build Coastguard Worker     fn removexattr(&self, _ctx: Context, inode: Inode, name: &CStr) -> io::Result<()> {
3250*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "removexattr", inode, name);
3251*bb4ee6a4SAndroid Build Coastguard Worker         // We don't allow the VM to set this xattr so we also pretend there is no value associated
3252*bb4ee6a4SAndroid Build Coastguard Worker         // with it.
3253*bb4ee6a4SAndroid Build Coastguard Worker         if self.cfg.rewrite_security_xattrs && name.to_bytes().starts_with(USER_VIRTIOFS_XATTR) {
3254*bb4ee6a4SAndroid Build Coastguard Worker             return Err(io::Error::from_raw_os_error(libc::ENODATA));
3255*bb4ee6a4SAndroid Build Coastguard Worker         }
3256*bb4ee6a4SAndroid Build Coastguard Worker 
3257*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(inode)?;
3258*bb4ee6a4SAndroid Build Coastguard Worker         let name = self.rewrite_xattr_name(name);
3259*bb4ee6a4SAndroid Build Coastguard Worker 
3260*bb4ee6a4SAndroid Build Coastguard Worker         let file = data.file.lock();
3261*bb4ee6a4SAndroid Build Coastguard Worker         let o_path_file = (file.1 & libc::O_PATH) != 0;
3262*bb4ee6a4SAndroid Build Coastguard Worker         if o_path_file {
3263*bb4ee6a4SAndroid Build Coastguard Worker             // For files opened with `O_PATH`, we cannot call `fremovexattr` normally. Instead we
3264*bb4ee6a4SAndroid Build Coastguard Worker             // emulate an _at syscall by changing the CWD to /proc, running the path based syscall,
3265*bb4ee6a4SAndroid Build Coastguard Worker             // and then setting the CWD back to the root directory.
3266*bb4ee6a4SAndroid Build Coastguard Worker             let path = CString::new(format!("self/fd/{}", file.0.as_raw_descriptor()))
3267*bb4ee6a4SAndroid Build Coastguard Worker                 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
3268*bb4ee6a4SAndroid Build Coastguard Worker 
3269*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(self.with_proc_chdir(||
3270*bb4ee6a4SAndroid Build Coastguard Worker                     // SAFETY: this doesn't modify any memory and we check the return value.
3271*bb4ee6a4SAndroid Build Coastguard Worker                     unsafe { libc::removexattr(path.as_ptr(), name.as_ptr()) }))?;
3272*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3273*bb4ee6a4SAndroid Build Coastguard Worker             // For regular files and directories, we can just use fremovexattr.
3274*bb4ee6a4SAndroid Build Coastguard Worker             syscall!(
3275*bb4ee6a4SAndroid Build Coastguard Worker                 // SAFETY: this doesn't modify any memory and we check the return value.
3276*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe { libc::fremovexattr(file.0.as_raw_descriptor(), name.as_ptr()) }
3277*bb4ee6a4SAndroid Build Coastguard Worker             )?;
3278*bb4ee6a4SAndroid Build Coastguard Worker         }
3279*bb4ee6a4SAndroid Build Coastguard Worker 
3280*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
3281*bb4ee6a4SAndroid Build Coastguard Worker     }
3282*bb4ee6a4SAndroid Build Coastguard Worker 
fallocate( &self, _ctx: Context, inode: Inode, handle: Handle, mode: u32, offset: u64, length: u64, ) -> io::Result<()>3283*bb4ee6a4SAndroid Build Coastguard Worker     fn fallocate(
3284*bb4ee6a4SAndroid Build Coastguard Worker         &self,
3285*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
3286*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
3287*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
3288*bb4ee6a4SAndroid Build Coastguard Worker         mode: u32,
3289*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
3290*bb4ee6a4SAndroid Build Coastguard Worker         length: u64,
3291*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<()> {
3292*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "fallocate", inode, handle, mode, offset, length);
3293*bb4ee6a4SAndroid Build Coastguard Worker 
3294*bb4ee6a4SAndroid Build Coastguard Worker         let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
3295*bb4ee6a4SAndroid Build Coastguard Worker             let data = self.find_inode(inode)?;
3296*bb4ee6a4SAndroid Build Coastguard Worker 
3297*bb4ee6a4SAndroid Build Coastguard Worker             {
3298*bb4ee6a4SAndroid Build Coastguard Worker                 // fallocate needs a writable fd
3299*bb4ee6a4SAndroid Build Coastguard Worker                 let mut file = data.file.lock();
3300*bb4ee6a4SAndroid Build Coastguard Worker                 let mut flags = file.1;
3301*bb4ee6a4SAndroid Build Coastguard Worker                 match flags & libc::O_ACCMODE {
3302*bb4ee6a4SAndroid Build Coastguard Worker                     libc::O_RDONLY => {
3303*bb4ee6a4SAndroid Build Coastguard Worker                         flags &= !libc::O_RDONLY;
3304*bb4ee6a4SAndroid Build Coastguard Worker                         flags |= libc::O_RDWR;
3305*bb4ee6a4SAndroid Build Coastguard Worker 
3306*bb4ee6a4SAndroid Build Coastguard Worker                         // We need to get a writable handle for this file.
3307*bb4ee6a4SAndroid Build Coastguard Worker                         let newfile = self.open_fd(file.0.as_raw_descriptor(), libc::O_RDWR)?;
3308*bb4ee6a4SAndroid Build Coastguard Worker                         *file = (newfile, flags);
3309*bb4ee6a4SAndroid Build Coastguard Worker                     }
3310*bb4ee6a4SAndroid Build Coastguard Worker                     libc::O_WRONLY | libc::O_RDWR => {}
3311*bb4ee6a4SAndroid Build Coastguard Worker                     _ => panic!("Unexpected flags: {:#x}", flags),
3312*bb4ee6a4SAndroid Build Coastguard Worker                 }
3313*bb4ee6a4SAndroid Build Coastguard Worker             }
3314*bb4ee6a4SAndroid Build Coastguard Worker 
3315*bb4ee6a4SAndroid Build Coastguard Worker             data
3316*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3317*bb4ee6a4SAndroid Build Coastguard Worker             self.find_handle(handle, inode)?
3318*bb4ee6a4SAndroid Build Coastguard Worker         };
3319*bb4ee6a4SAndroid Build Coastguard Worker 
3320*bb4ee6a4SAndroid Build Coastguard Worker         let fd = data.as_raw_descriptor();
3321*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: this doesn't modify any memory and we check the return value.
3322*bb4ee6a4SAndroid Build Coastguard Worker         syscall!(unsafe {
3323*bb4ee6a4SAndroid Build Coastguard Worker             libc::fallocate64(
3324*bb4ee6a4SAndroid Build Coastguard Worker                 fd,
3325*bb4ee6a4SAndroid Build Coastguard Worker                 mode as libc::c_int,
3326*bb4ee6a4SAndroid Build Coastguard Worker                 offset as libc::off64_t,
3327*bb4ee6a4SAndroid Build Coastguard Worker                 length as libc::off64_t,
3328*bb4ee6a4SAndroid Build Coastguard Worker             )
3329*bb4ee6a4SAndroid Build Coastguard Worker         })?;
3330*bb4ee6a4SAndroid Build Coastguard Worker 
3331*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
3332*bb4ee6a4SAndroid Build Coastguard Worker     }
3333*bb4ee6a4SAndroid Build Coastguard Worker 
3334*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(clippy::unnecessary_cast)]
ioctl<R: io::Read>( &self, ctx: Context, inode: Inode, handle: Handle, _flags: IoctlFlags, cmd: u32, _arg: u64, in_size: u32, out_size: u32, r: R, ) -> io::Result<IoctlReply>3335*bb4ee6a4SAndroid Build Coastguard Worker     fn ioctl<R: io::Read>(
3336*bb4ee6a4SAndroid Build Coastguard Worker         &self,
3337*bb4ee6a4SAndroid Build Coastguard Worker         ctx: Context,
3338*bb4ee6a4SAndroid Build Coastguard Worker         inode: Inode,
3339*bb4ee6a4SAndroid Build Coastguard Worker         handle: Handle,
3340*bb4ee6a4SAndroid Build Coastguard Worker         _flags: IoctlFlags,
3341*bb4ee6a4SAndroid Build Coastguard Worker         cmd: u32,
3342*bb4ee6a4SAndroid Build Coastguard Worker         _arg: u64,
3343*bb4ee6a4SAndroid Build Coastguard Worker         in_size: u32,
3344*bb4ee6a4SAndroid Build Coastguard Worker         out_size: u32,
3345*bb4ee6a4SAndroid Build Coastguard Worker         r: R,
3346*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<IoctlReply> {
3347*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "ioctl", inode, handle, cmd, in_size, out_size);
3348*bb4ee6a4SAndroid Build Coastguard Worker 
3349*bb4ee6a4SAndroid Build Coastguard Worker         match cmd as IoctlNr {
3350*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC_GET_ENCRYPTION_POLICY_EX => self.get_encryption_policy_ex(inode, handle, r),
3351*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC_FSGETXATTR => {
3352*bb4ee6a4SAndroid Build Coastguard Worker                 if out_size < size_of::<fsxattr>() as u32 {
3353*bb4ee6a4SAndroid Build Coastguard Worker                     Err(io::Error::from_raw_os_error(libc::ENOMEM))
3354*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
3355*bb4ee6a4SAndroid Build Coastguard Worker                     self.get_fsxattr(inode, handle)
3356*bb4ee6a4SAndroid Build Coastguard Worker                 }
3357*bb4ee6a4SAndroid Build Coastguard Worker             }
3358*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC_FSSETXATTR => {
3359*bb4ee6a4SAndroid Build Coastguard Worker                 if in_size < size_of::<fsxattr>() as u32 {
3360*bb4ee6a4SAndroid Build Coastguard Worker                     Err(io::Error::from_raw_os_error(libc::EINVAL))
3361*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
3362*bb4ee6a4SAndroid Build Coastguard Worker                     self.set_fsxattr(ctx, inode, handle, r)
3363*bb4ee6a4SAndroid Build Coastguard Worker                 }
3364*bb4ee6a4SAndroid Build Coastguard Worker             }
3365*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC32_GETFLAGS | FS_IOC64_GETFLAGS => {
3366*bb4ee6a4SAndroid Build Coastguard Worker                 if out_size < size_of::<c_int>() as u32 {
3367*bb4ee6a4SAndroid Build Coastguard Worker                     Err(io::Error::from_raw_os_error(libc::ENOMEM))
3368*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
3369*bb4ee6a4SAndroid Build Coastguard Worker                     self.get_flags(inode, handle)
3370*bb4ee6a4SAndroid Build Coastguard Worker                 }
3371*bb4ee6a4SAndroid Build Coastguard Worker             }
3372*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC32_SETFLAGS | FS_IOC64_SETFLAGS => {
3373*bb4ee6a4SAndroid Build Coastguard Worker                 if in_size < size_of::<c_int>() as u32 {
3374*bb4ee6a4SAndroid Build Coastguard Worker                     Err(io::Error::from_raw_os_error(libc::ENOMEM))
3375*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
3376*bb4ee6a4SAndroid Build Coastguard Worker                     self.set_flags(ctx, inode, handle, r)
3377*bb4ee6a4SAndroid Build Coastguard Worker                 }
3378*bb4ee6a4SAndroid Build Coastguard Worker             }
3379*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC_ENABLE_VERITY => {
3380*bb4ee6a4SAndroid Build Coastguard Worker                 if in_size < size_of::<fsverity_enable_arg>() as u32 {
3381*bb4ee6a4SAndroid Build Coastguard Worker                     Err(io::Error::from_raw_os_error(libc::ENOMEM))
3382*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
3383*bb4ee6a4SAndroid Build Coastguard Worker                     self.enable_verity(inode, handle, r)
3384*bb4ee6a4SAndroid Build Coastguard Worker                 }
3385*bb4ee6a4SAndroid Build Coastguard Worker             }
3386*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC_MEASURE_VERITY => {
3387*bb4ee6a4SAndroid Build Coastguard Worker                 if in_size < size_of::<fsverity_digest>() as u32
3388*bb4ee6a4SAndroid Build Coastguard Worker                     || out_size < size_of::<fsverity_digest>() as u32
3389*bb4ee6a4SAndroid Build Coastguard Worker                 {
3390*bb4ee6a4SAndroid Build Coastguard Worker                     Err(io::Error::from_raw_os_error(libc::ENOMEM))
3391*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
3392*bb4ee6a4SAndroid Build Coastguard Worker                     self.measure_verity(inode, handle, r, out_size)
3393*bb4ee6a4SAndroid Build Coastguard Worker                 }
3394*bb4ee6a4SAndroid Build Coastguard Worker             }
3395*bb4ee6a4SAndroid Build Coastguard Worker             // The following is ARCVM-specific ioctl
3396*bb4ee6a4SAndroid Build Coastguard Worker             // Refer go/remove-mount-passthrough-fuse for more design details
3397*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "arc_quota")]
3398*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC_SETPERMISSION => {
3399*bb4ee6a4SAndroid Build Coastguard Worker                 if in_size != size_of::<FsPermissionDataBuffer>() as u32 {
3400*bb4ee6a4SAndroid Build Coastguard Worker                     Err(io::Error::from_raw_os_error(libc::EINVAL))
3401*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
3402*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(self.set_permission_by_path(r))
3403*bb4ee6a4SAndroid Build Coastguard Worker                 }
3404*bb4ee6a4SAndroid Build Coastguard Worker             }
3405*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(feature = "arc_quota")]
3406*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC_SETPATHXATTR => {
3407*bb4ee6a4SAndroid Build Coastguard Worker                 if in_size != size_of::<FsPathXattrDataBuffer>() as u32 {
3408*bb4ee6a4SAndroid Build Coastguard Worker                     Err(io::Error::from_raw_os_error(libc::EINVAL))
3409*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
3410*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(self.set_xattr_by_path(r))
3411*bb4ee6a4SAndroid Build Coastguard Worker                 }
3412*bb4ee6a4SAndroid Build Coastguard Worker             }
3413*bb4ee6a4SAndroid Build Coastguard Worker             _ => Err(io::Error::from_raw_os_error(libc::ENOTTY)),
3414*bb4ee6a4SAndroid Build Coastguard Worker         }
3415*bb4ee6a4SAndroid Build Coastguard Worker     }
3416*bb4ee6a4SAndroid Build Coastguard Worker 
copy_file_range( &self, ctx: Context, inode_src: Inode, handle_src: Handle, offset_src: u64, inode_dst: Inode, handle_dst: Handle, offset_dst: u64, length: u64, flags: u64, ) -> io::Result<usize>3417*bb4ee6a4SAndroid Build Coastguard Worker     fn copy_file_range(
3418*bb4ee6a4SAndroid Build Coastguard Worker         &self,
3419*bb4ee6a4SAndroid Build Coastguard Worker         ctx: Context,
3420*bb4ee6a4SAndroid Build Coastguard Worker         inode_src: Inode,
3421*bb4ee6a4SAndroid Build Coastguard Worker         handle_src: Handle,
3422*bb4ee6a4SAndroid Build Coastguard Worker         offset_src: u64,
3423*bb4ee6a4SAndroid Build Coastguard Worker         inode_dst: Inode,
3424*bb4ee6a4SAndroid Build Coastguard Worker         handle_dst: Handle,
3425*bb4ee6a4SAndroid Build Coastguard Worker         offset_dst: u64,
3426*bb4ee6a4SAndroid Build Coastguard Worker         length: u64,
3427*bb4ee6a4SAndroid Build Coastguard Worker         flags: u64,
3428*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<usize> {
3429*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(
3430*bb4ee6a4SAndroid Build Coastguard Worker             self.tag,
3431*bb4ee6a4SAndroid Build Coastguard Worker             "copy_file_range",
3432*bb4ee6a4SAndroid Build Coastguard Worker             inode_src,
3433*bb4ee6a4SAndroid Build Coastguard Worker             handle_src,
3434*bb4ee6a4SAndroid Build Coastguard Worker             offset_src,
3435*bb4ee6a4SAndroid Build Coastguard Worker             inode_dst,
3436*bb4ee6a4SAndroid Build Coastguard Worker             handle_dst,
3437*bb4ee6a4SAndroid Build Coastguard Worker             offset_dst,
3438*bb4ee6a4SAndroid Build Coastguard Worker             length,
3439*bb4ee6a4SAndroid Build Coastguard Worker             flags
3440*bb4ee6a4SAndroid Build Coastguard Worker         );
3441*bb4ee6a4SAndroid Build Coastguard Worker         // We need to change credentials during a write so that the kernel will remove setuid or
3442*bb4ee6a4SAndroid Build Coastguard Worker         // setgid bits from the file if it was written to by someone other than the owner.
3443*bb4ee6a4SAndroid Build Coastguard Worker         let (_uid, _gid) = set_creds(ctx.uid, ctx.gid)?;
3444*bb4ee6a4SAndroid Build Coastguard Worker         let (src_data, dst_data): (Arc<dyn AsRawDescriptor>, Arc<dyn AsRawDescriptor>) =
3445*bb4ee6a4SAndroid Build Coastguard Worker             if self.zero_message_open.load(Ordering::Relaxed) {
3446*bb4ee6a4SAndroid Build Coastguard Worker                 (self.find_inode(inode_src)?, self.find_inode(inode_dst)?)
3447*bb4ee6a4SAndroid Build Coastguard Worker             } else {
3448*bb4ee6a4SAndroid Build Coastguard Worker                 (
3449*bb4ee6a4SAndroid Build Coastguard Worker                     self.find_handle(handle_src, inode_src)?,
3450*bb4ee6a4SAndroid Build Coastguard Worker                     self.find_handle(handle_dst, inode_dst)?,
3451*bb4ee6a4SAndroid Build Coastguard Worker                 )
3452*bb4ee6a4SAndroid Build Coastguard Worker             };
3453*bb4ee6a4SAndroid Build Coastguard Worker 
3454*bb4ee6a4SAndroid Build Coastguard Worker         let src = src_data.as_raw_descriptor();
3455*bb4ee6a4SAndroid Build Coastguard Worker         let dst = dst_data.as_raw_descriptor();
3456*bb4ee6a4SAndroid Build Coastguard Worker 
3457*bb4ee6a4SAndroid Build Coastguard Worker         Ok(syscall!(
3458*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: this call is safe because it doesn't modify any memory and we
3459*bb4ee6a4SAndroid Build Coastguard Worker             // check the return value.
3460*bb4ee6a4SAndroid Build Coastguard Worker             unsafe {
3461*bb4ee6a4SAndroid Build Coastguard Worker                 libc::syscall(
3462*bb4ee6a4SAndroid Build Coastguard Worker                     libc::SYS_copy_file_range,
3463*bb4ee6a4SAndroid Build Coastguard Worker                     src,
3464*bb4ee6a4SAndroid Build Coastguard Worker                     &offset_src,
3465*bb4ee6a4SAndroid Build Coastguard Worker                     dst,
3466*bb4ee6a4SAndroid Build Coastguard Worker                     &offset_dst,
3467*bb4ee6a4SAndroid Build Coastguard Worker                     length,
3468*bb4ee6a4SAndroid Build Coastguard Worker                     flags,
3469*bb4ee6a4SAndroid Build Coastguard Worker                 )
3470*bb4ee6a4SAndroid Build Coastguard Worker             }
3471*bb4ee6a4SAndroid Build Coastguard Worker         )? as usize)
3472*bb4ee6a4SAndroid Build Coastguard Worker     }
3473*bb4ee6a4SAndroid Build Coastguard Worker 
set_up_mapping<M: Mapper>( &self, _ctx: Context, inode: Self::Inode, _handle: Self::Handle, file_offset: u64, mem_offset: u64, size: usize, prot: u32, mapper: M, ) -> io::Result<()>3474*bb4ee6a4SAndroid Build Coastguard Worker     fn set_up_mapping<M: Mapper>(
3475*bb4ee6a4SAndroid Build Coastguard Worker         &self,
3476*bb4ee6a4SAndroid Build Coastguard Worker         _ctx: Context,
3477*bb4ee6a4SAndroid Build Coastguard Worker         inode: Self::Inode,
3478*bb4ee6a4SAndroid Build Coastguard Worker         _handle: Self::Handle,
3479*bb4ee6a4SAndroid Build Coastguard Worker         file_offset: u64,
3480*bb4ee6a4SAndroid Build Coastguard Worker         mem_offset: u64,
3481*bb4ee6a4SAndroid Build Coastguard Worker         size: usize,
3482*bb4ee6a4SAndroid Build Coastguard Worker         prot: u32,
3483*bb4ee6a4SAndroid Build Coastguard Worker         mapper: M,
3484*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<()> {
3485*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(
3486*bb4ee6a4SAndroid Build Coastguard Worker             self.tag,
3487*bb4ee6a4SAndroid Build Coastguard Worker             "set_up_mapping",
3488*bb4ee6a4SAndroid Build Coastguard Worker             inode,
3489*bb4ee6a4SAndroid Build Coastguard Worker             file_offset,
3490*bb4ee6a4SAndroid Build Coastguard Worker             mem_offset,
3491*bb4ee6a4SAndroid Build Coastguard Worker             size,
3492*bb4ee6a4SAndroid Build Coastguard Worker             prot
3493*bb4ee6a4SAndroid Build Coastguard Worker         );
3494*bb4ee6a4SAndroid Build Coastguard Worker         if !self.cfg.use_dax {
3495*bb4ee6a4SAndroid Build Coastguard Worker             return Err(io::Error::from_raw_os_error(libc::ENOSYS));
3496*bb4ee6a4SAndroid Build Coastguard Worker         }
3497*bb4ee6a4SAndroid Build Coastguard Worker 
3498*bb4ee6a4SAndroid Build Coastguard Worker         let read = prot & libc::PROT_READ as u32 != 0;
3499*bb4ee6a4SAndroid Build Coastguard Worker         let write = prot & libc::PROT_WRITE as u32 != 0;
3500*bb4ee6a4SAndroid Build Coastguard Worker         let (mmap_flags, prot) = match (read, write) {
3501*bb4ee6a4SAndroid Build Coastguard Worker             (true, true) => (libc::O_RDWR, Protection::read_write()),
3502*bb4ee6a4SAndroid Build Coastguard Worker             (true, false) => (libc::O_RDONLY, Protection::read()),
3503*bb4ee6a4SAndroid Build Coastguard Worker             // Write-only is mapped to O_RDWR since mmap always requires an fd opened for reading.
3504*bb4ee6a4SAndroid Build Coastguard Worker             (false, true) => (libc::O_RDWR, Protection::write()),
3505*bb4ee6a4SAndroid Build Coastguard Worker             (false, false) => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
3506*bb4ee6a4SAndroid Build Coastguard Worker         };
3507*bb4ee6a4SAndroid Build Coastguard Worker 
3508*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(inode)?;
3509*bb4ee6a4SAndroid Build Coastguard Worker 
3510*bb4ee6a4SAndroid Build Coastguard Worker         if self.zero_message_open.load(Ordering::Relaxed) {
3511*bb4ee6a4SAndroid Build Coastguard Worker             let mut file = data.file.lock();
3512*bb4ee6a4SAndroid Build Coastguard Worker             let mut open_flags = file.1;
3513*bb4ee6a4SAndroid Build Coastguard Worker             match (mmap_flags, open_flags & libc::O_ACCMODE) {
3514*bb4ee6a4SAndroid Build Coastguard Worker                 (libc::O_RDONLY, libc::O_WRONLY)
3515*bb4ee6a4SAndroid Build Coastguard Worker                 | (libc::O_RDWR, libc::O_RDONLY)
3516*bb4ee6a4SAndroid Build Coastguard Worker                 | (libc::O_RDWR, libc::O_WRONLY) => {
3517*bb4ee6a4SAndroid Build Coastguard Worker                     // We have a read-only or write-only fd and we need to upgrade it.
3518*bb4ee6a4SAndroid Build Coastguard Worker                     open_flags &= !libc::O_ACCMODE;
3519*bb4ee6a4SAndroid Build Coastguard Worker                     open_flags |= libc::O_RDWR;
3520*bb4ee6a4SAndroid Build Coastguard Worker 
3521*bb4ee6a4SAndroid Build Coastguard Worker                     let newfile = self.open_fd(file.0.as_raw_descriptor(), libc::O_RDWR)?;
3522*bb4ee6a4SAndroid Build Coastguard Worker                     *file = (newfile, open_flags);
3523*bb4ee6a4SAndroid Build Coastguard Worker                 }
3524*bb4ee6a4SAndroid Build Coastguard Worker                 (libc::O_RDONLY, libc::O_RDONLY)
3525*bb4ee6a4SAndroid Build Coastguard Worker                 | (libc::O_RDONLY, libc::O_RDWR)
3526*bb4ee6a4SAndroid Build Coastguard Worker                 | (libc::O_RDWR, libc::O_RDWR) => {}
3527*bb4ee6a4SAndroid Build Coastguard Worker                 (m, o) => panic!(
3528*bb4ee6a4SAndroid Build Coastguard Worker                     "Unexpected combination of access flags: ({:#x}, {:#x})",
3529*bb4ee6a4SAndroid Build Coastguard Worker                     m, o
3530*bb4ee6a4SAndroid Build Coastguard Worker                 ),
3531*bb4ee6a4SAndroid Build Coastguard Worker             }
3532*bb4ee6a4SAndroid Build Coastguard Worker             mapper.map(mem_offset, size, &file.0, file_offset, prot)
3533*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3534*bb4ee6a4SAndroid Build Coastguard Worker             let file = self.open_inode(&data, mmap_flags | libc::O_NONBLOCK)?;
3535*bb4ee6a4SAndroid Build Coastguard Worker             mapper.map(mem_offset, size, &file, file_offset, prot)
3536*bb4ee6a4SAndroid Build Coastguard Worker         }
3537*bb4ee6a4SAndroid Build Coastguard Worker     }
3538*bb4ee6a4SAndroid Build Coastguard Worker 
remove_mapping<M: Mapper>(&self, msgs: &[RemoveMappingOne], mapper: M) -> io::Result<()>3539*bb4ee6a4SAndroid Build Coastguard Worker     fn remove_mapping<M: Mapper>(&self, msgs: &[RemoveMappingOne], mapper: M) -> io::Result<()> {
3540*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(self.tag, "remove_mapping", msgs);
3541*bb4ee6a4SAndroid Build Coastguard Worker         if !self.cfg.use_dax {
3542*bb4ee6a4SAndroid Build Coastguard Worker             return Err(io::Error::from_raw_os_error(libc::ENOSYS));
3543*bb4ee6a4SAndroid Build Coastguard Worker         }
3544*bb4ee6a4SAndroid Build Coastguard Worker 
3545*bb4ee6a4SAndroid Build Coastguard Worker         for RemoveMappingOne { moffset, len } in msgs {
3546*bb4ee6a4SAndroid Build Coastguard Worker             mapper.unmap(*moffset, *len)?;
3547*bb4ee6a4SAndroid Build Coastguard Worker         }
3548*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
3549*bb4ee6a4SAndroid Build Coastguard Worker     }
3550*bb4ee6a4SAndroid Build Coastguard Worker 
atomic_open( &self, ctx: Context, parent: Self::Inode, name: &CStr, mode: u32, flags: u32, umask: u32, security_ctx: Option<&CStr>, ) -> io::Result<(Entry, Option<Self::Handle>, OpenOptions)>3551*bb4ee6a4SAndroid Build Coastguard Worker     fn atomic_open(
3552*bb4ee6a4SAndroid Build Coastguard Worker         &self,
3553*bb4ee6a4SAndroid Build Coastguard Worker         ctx: Context,
3554*bb4ee6a4SAndroid Build Coastguard Worker         parent: Self::Inode,
3555*bb4ee6a4SAndroid Build Coastguard Worker         name: &CStr,
3556*bb4ee6a4SAndroid Build Coastguard Worker         mode: u32,
3557*bb4ee6a4SAndroid Build Coastguard Worker         flags: u32,
3558*bb4ee6a4SAndroid Build Coastguard Worker         umask: u32,
3559*bb4ee6a4SAndroid Build Coastguard Worker         security_ctx: Option<&CStr>,
3560*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<(Entry, Option<Self::Handle>, OpenOptions)> {
3561*bb4ee6a4SAndroid Build Coastguard Worker         let _trace = fs_trace!(
3562*bb4ee6a4SAndroid Build Coastguard Worker             self.tag,
3563*bb4ee6a4SAndroid Build Coastguard Worker             "atomic_open",
3564*bb4ee6a4SAndroid Build Coastguard Worker             parent,
3565*bb4ee6a4SAndroid Build Coastguard Worker             name,
3566*bb4ee6a4SAndroid Build Coastguard Worker             mode,
3567*bb4ee6a4SAndroid Build Coastguard Worker             flags,
3568*bb4ee6a4SAndroid Build Coastguard Worker             umask,
3569*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx
3570*bb4ee6a4SAndroid Build Coastguard Worker         );
3571*bb4ee6a4SAndroid Build Coastguard Worker         // Perform lookup but not create negative dentry
3572*bb4ee6a4SAndroid Build Coastguard Worker         let data = self.find_inode(parent)?;
3573*bb4ee6a4SAndroid Build Coastguard Worker 
3574*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(unused_variables)]
3575*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "arc_quota")]
3576*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_creds(&ctx, &data, name);
3577*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "fs_runtime_ugid_map")]
3578*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = self.change_ugid_creds(&ctx, &data, name);
3579*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(feature = "fs_permission_translation"))]
3580*bb4ee6a4SAndroid Build Coastguard Worker         let (uid, gid) = (ctx.uid, ctx.gid);
3581*bb4ee6a4SAndroid Build Coastguard Worker 
3582*bb4ee6a4SAndroid Build Coastguard Worker         let (_uid, _gid) = set_creds(uid, gid)?;
3583*bb4ee6a4SAndroid Build Coastguard Worker 
3584*bb4ee6a4SAndroid Build Coastguard Worker         // This lookup serves two purposes:
3585*bb4ee6a4SAndroid Build Coastguard Worker         // 1. If the O_CREATE flag is not set, it retrieves the d_entry for the file.
3586*bb4ee6a4SAndroid Build Coastguard Worker         // 2. If the O_CREATE flag is set, it checks whether the file exists.
3587*bb4ee6a4SAndroid Build Coastguard Worker         let res = self.do_lookup_with_casefold_fallback(&data, name);
3588*bb4ee6a4SAndroid Build Coastguard Worker 
3589*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = res {
3590*bb4ee6a4SAndroid Build Coastguard Worker             if e.kind() == std::io::ErrorKind::NotFound && (flags as i32 & libc::O_CREAT) != 0 {
3591*bb4ee6a4SAndroid Build Coastguard Worker                 // If the file did not exist & O_CREAT is set,
3592*bb4ee6a4SAndroid Build Coastguard Worker                 // create file & set FILE_CREATED bits in open options
3593*bb4ee6a4SAndroid Build Coastguard Worker                 let (entry, handler, mut opts) =
3594*bb4ee6a4SAndroid Build Coastguard Worker                     self.create(ctx, parent, name, mode, flags, umask, security_ctx)?;
3595*bb4ee6a4SAndroid Build Coastguard Worker                 opts |= OpenOptions::FILE_CREATED;
3596*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok((entry, handler, opts));
3597*bb4ee6a4SAndroid Build Coastguard Worker             } else if e.kind() == std::io::ErrorKind::NotFound
3598*bb4ee6a4SAndroid Build Coastguard Worker                 && !self.cfg.negative_timeout.is_zero()
3599*bb4ee6a4SAndroid Build Coastguard Worker             {
3600*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok((
3601*bb4ee6a4SAndroid Build Coastguard Worker                     Entry::new_negative(self.cfg.negative_timeout),
3602*bb4ee6a4SAndroid Build Coastguard Worker                     None,
3603*bb4ee6a4SAndroid Build Coastguard Worker                     OpenOptions::empty(),
3604*bb4ee6a4SAndroid Build Coastguard Worker                 ));
3605*bb4ee6a4SAndroid Build Coastguard Worker             }
3606*bb4ee6a4SAndroid Build Coastguard Worker             return Err(e);
3607*bb4ee6a4SAndroid Build Coastguard Worker         }
3608*bb4ee6a4SAndroid Build Coastguard Worker 
3609*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: checked res is not error before
3610*bb4ee6a4SAndroid Build Coastguard Worker         let entry = res.unwrap();
3611*bb4ee6a4SAndroid Build Coastguard Worker 
3612*bb4ee6a4SAndroid Build Coastguard Worker         if entry.attr.st_mode & libc::S_IFMT == libc::S_IFLNK {
3613*bb4ee6a4SAndroid Build Coastguard Worker             return Ok((entry, None, OpenOptions::empty()));
3614*bb4ee6a4SAndroid Build Coastguard Worker         }
3615*bb4ee6a4SAndroid Build Coastguard Worker 
3616*bb4ee6a4SAndroid Build Coastguard Worker         if (flags as i32 & (libc::O_CREAT | libc::O_EXCL)) == (libc::O_CREAT | libc::O_EXCL) {
3617*bb4ee6a4SAndroid Build Coastguard Worker             return Err(eexist());
3618*bb4ee6a4SAndroid Build Coastguard Worker         }
3619*bb4ee6a4SAndroid Build Coastguard Worker 
3620*bb4ee6a4SAndroid Build Coastguard Worker         let (handler, opts) = if self.zero_message_open.load(Ordering::Relaxed) {
3621*bb4ee6a4SAndroid Build Coastguard Worker             (None, OpenOptions::KEEP_CACHE)
3622*bb4ee6a4SAndroid Build Coastguard Worker         } else {
3623*bb4ee6a4SAndroid Build Coastguard Worker             let (handler, opts) = self.do_open(entry.inode, flags)?;
3624*bb4ee6a4SAndroid Build Coastguard Worker             (handler, opts)
3625*bb4ee6a4SAndroid Build Coastguard Worker         };
3626*bb4ee6a4SAndroid Build Coastguard Worker         Ok((entry, handler, opts))
3627*bb4ee6a4SAndroid Build Coastguard Worker     }
3628*bb4ee6a4SAndroid Build Coastguard Worker }
3629*bb4ee6a4SAndroid Build Coastguard Worker 
3630*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
3631*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
3632*bb4ee6a4SAndroid Build Coastguard Worker     use std::path::Path;
3633*bb4ee6a4SAndroid Build Coastguard Worker 
3634*bb4ee6a4SAndroid Build Coastguard Worker     use named_lock::NamedLock;
3635*bb4ee6a4SAndroid Build Coastguard Worker     use tempfile::TempDir;
3636*bb4ee6a4SAndroid Build Coastguard Worker 
3637*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
3638*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
3639*bb4ee6a4SAndroid Build Coastguard Worker     use crate::virtio::fs::arc_ioctl::FS_IOCTL_PATH_MAX_LEN;
3640*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
3641*bb4ee6a4SAndroid Build Coastguard Worker     use crate::virtio::fs::arc_ioctl::FS_IOCTL_XATTR_NAME_MAX_LEN;
3642*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
3643*bb4ee6a4SAndroid Build Coastguard Worker     use crate::virtio::fs::arc_ioctl::FS_IOCTL_XATTR_VALUE_MAX_LEN;
3644*bb4ee6a4SAndroid Build Coastguard Worker 
3645*bb4ee6a4SAndroid Build Coastguard Worker     const UNITTEST_LOCK_NAME: &str = "passthroughfs_unittest_lock";
3646*bb4ee6a4SAndroid Build Coastguard Worker 
3647*bb4ee6a4SAndroid Build Coastguard Worker     // Create an instance of `Context` with valid uid, gid, and pid.
3648*bb4ee6a4SAndroid Build Coastguard Worker     // The correct ids are necessary for test cases where new files are created.
get_context() -> Context3649*bb4ee6a4SAndroid Build Coastguard Worker     fn get_context() -> Context {
3650*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: both calls take no parameters and only return an integer value. The kernel also
3651*bb4ee6a4SAndroid Build Coastguard Worker         // guarantees that they can never fail.
3652*bb4ee6a4SAndroid Build Coastguard Worker         let uid = unsafe { libc::syscall(SYS_GETEUID) as libc::uid_t };
3653*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: both calls take no parameters and only return an integer value. The kernel also
3654*bb4ee6a4SAndroid Build Coastguard Worker         // guarantees that they can never fail.
3655*bb4ee6a4SAndroid Build Coastguard Worker         let gid = unsafe { libc::syscall(SYS_GETEGID) as libc::gid_t };
3656*bb4ee6a4SAndroid Build Coastguard Worker         let pid = std::process::id() as libc::pid_t;
3657*bb4ee6a4SAndroid Build Coastguard Worker         Context { uid, gid, pid }
3658*bb4ee6a4SAndroid Build Coastguard Worker     }
3659*bb4ee6a4SAndroid Build Coastguard Worker 
3660*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates the given directories and files under `temp_dir`.
create_test_data(temp_dir: &TempDir, dirs: &[&str], files: &[&str])3661*bb4ee6a4SAndroid Build Coastguard Worker     fn create_test_data(temp_dir: &TempDir, dirs: &[&str], files: &[&str]) {
3662*bb4ee6a4SAndroid Build Coastguard Worker         let path = temp_dir.path();
3663*bb4ee6a4SAndroid Build Coastguard Worker 
3664*bb4ee6a4SAndroid Build Coastguard Worker         for d in dirs {
3665*bb4ee6a4SAndroid Build Coastguard Worker             std::fs::create_dir_all(path.join(d)).unwrap();
3666*bb4ee6a4SAndroid Build Coastguard Worker         }
3667*bb4ee6a4SAndroid Build Coastguard Worker 
3668*bb4ee6a4SAndroid Build Coastguard Worker         for f in files {
3669*bb4ee6a4SAndroid Build Coastguard Worker             File::create(path.join(f)).unwrap();
3670*bb4ee6a4SAndroid Build Coastguard Worker         }
3671*bb4ee6a4SAndroid Build Coastguard Worker     }
3672*bb4ee6a4SAndroid Build Coastguard Worker 
3673*bb4ee6a4SAndroid Build Coastguard Worker     /// Looks up the given `path` in `fs`.
lookup(fs: &PassthroughFs, path: &Path) -> io::Result<Inode>3674*bb4ee6a4SAndroid Build Coastguard Worker     fn lookup(fs: &PassthroughFs, path: &Path) -> io::Result<Inode> {
3675*bb4ee6a4SAndroid Build Coastguard Worker         let mut inode = 1;
3676*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
3677*bb4ee6a4SAndroid Build Coastguard Worker         for name in path.iter() {
3678*bb4ee6a4SAndroid Build Coastguard Worker             let name = CString::new(name.to_str().unwrap()).unwrap();
3679*bb4ee6a4SAndroid Build Coastguard Worker             let ent = match fs.lookup(ctx, inode, &name) {
3680*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(ent) => ent,
3681*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => {
3682*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(e);
3683*bb4ee6a4SAndroid Build Coastguard Worker                 }
3684*bb4ee6a4SAndroid Build Coastguard Worker             };
3685*bb4ee6a4SAndroid Build Coastguard Worker             inode = ent.inode;
3686*bb4ee6a4SAndroid Build Coastguard Worker         }
3687*bb4ee6a4SAndroid Build Coastguard Worker         Ok(inode)
3688*bb4ee6a4SAndroid Build Coastguard Worker     }
3689*bb4ee6a4SAndroid Build Coastguard Worker 
3690*bb4ee6a4SAndroid Build Coastguard Worker     /// Looks up the given `path` in `fs`.
3691*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
lookup_ent(fs: &PassthroughFs, path: &Path) -> io::Result<Entry>3692*bb4ee6a4SAndroid Build Coastguard Worker     fn lookup_ent(fs: &PassthroughFs, path: &Path) -> io::Result<Entry> {
3693*bb4ee6a4SAndroid Build Coastguard Worker         let mut inode = 1;
3694*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
3695*bb4ee6a4SAndroid Build Coastguard Worker         let mut entry = Entry::new_negative(Duration::from_secs(10));
3696*bb4ee6a4SAndroid Build Coastguard Worker         for name in path.iter() {
3697*bb4ee6a4SAndroid Build Coastguard Worker             let name = CString::new(name.to_str().unwrap()).unwrap();
3698*bb4ee6a4SAndroid Build Coastguard Worker             entry = match fs.lookup(ctx, inode, &name) {
3699*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(ent) => ent,
3700*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => {
3701*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(e);
3702*bb4ee6a4SAndroid Build Coastguard Worker                 }
3703*bb4ee6a4SAndroid Build Coastguard Worker             };
3704*bb4ee6a4SAndroid Build Coastguard Worker             inode = entry.inode;
3705*bb4ee6a4SAndroid Build Coastguard Worker         }
3706*bb4ee6a4SAndroid Build Coastguard Worker         Ok(entry)
3707*bb4ee6a4SAndroid Build Coastguard Worker     }
3708*bb4ee6a4SAndroid Build Coastguard Worker 
3709*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a file at the given `path`.
create(fs: &PassthroughFs, path: &Path) -> io::Result<Entry>3710*bb4ee6a4SAndroid Build Coastguard Worker     fn create(fs: &PassthroughFs, path: &Path) -> io::Result<Entry> {
3711*bb4ee6a4SAndroid Build Coastguard Worker         let parent = path.parent().unwrap();
3712*bb4ee6a4SAndroid Build Coastguard Worker         let filename = CString::new(path.file_name().unwrap().to_str().unwrap()).unwrap();
3713*bb4ee6a4SAndroid Build Coastguard Worker         let parent_inode = lookup(fs, parent)?;
3714*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
3715*bb4ee6a4SAndroid Build Coastguard Worker         let security_ctx = None;
3716*bb4ee6a4SAndroid Build Coastguard Worker         fs.create(
3717*bb4ee6a4SAndroid Build Coastguard Worker             ctx,
3718*bb4ee6a4SAndroid Build Coastguard Worker             parent_inode,
3719*bb4ee6a4SAndroid Build Coastguard Worker             &filename,
3720*bb4ee6a4SAndroid Build Coastguard Worker             0o666,
3721*bb4ee6a4SAndroid Build Coastguard Worker             libc::O_RDWR as u32,
3722*bb4ee6a4SAndroid Build Coastguard Worker             0,
3723*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx,
3724*bb4ee6a4SAndroid Build Coastguard Worker         )
3725*bb4ee6a4SAndroid Build Coastguard Worker         .map(|(entry, _, _)| entry)
3726*bb4ee6a4SAndroid Build Coastguard Worker     }
3727*bb4ee6a4SAndroid Build Coastguard Worker 
3728*bb4ee6a4SAndroid Build Coastguard Worker     /// Removes a file at the given `path`.
unlink(fs: &PassthroughFs, path: &Path) -> io::Result<()>3729*bb4ee6a4SAndroid Build Coastguard Worker     fn unlink(fs: &PassthroughFs, path: &Path) -> io::Result<()> {
3730*bb4ee6a4SAndroid Build Coastguard Worker         let parent = path.parent().unwrap();
3731*bb4ee6a4SAndroid Build Coastguard Worker         let filename = CString::new(path.file_name().unwrap().to_str().unwrap()).unwrap();
3732*bb4ee6a4SAndroid Build Coastguard Worker         let parent_inode = lookup(fs, parent)?;
3733*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
3734*bb4ee6a4SAndroid Build Coastguard Worker         fs.unlink(ctx, parent_inode, &filename)
3735*bb4ee6a4SAndroid Build Coastguard Worker     }
3736*bb4ee6a4SAndroid Build Coastguard Worker 
3737*bb4ee6a4SAndroid Build Coastguard Worker     /// Forgets cache.
forget(fs: &PassthroughFs, path: &Path) -> io::Result<()>3738*bb4ee6a4SAndroid Build Coastguard Worker     fn forget(fs: &PassthroughFs, path: &Path) -> io::Result<()> {
3739*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
3740*bb4ee6a4SAndroid Build Coastguard Worker         let inode = lookup(fs, path)?;
3741*bb4ee6a4SAndroid Build Coastguard Worker         // Pass `u64::MAX` to ensure that the refcount goes to 0 and we forget inode.
3742*bb4ee6a4SAndroid Build Coastguard Worker         fs.forget(ctx, inode, u64::MAX);
3743*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
3744*bb4ee6a4SAndroid Build Coastguard Worker     }
3745*bb4ee6a4SAndroid Build Coastguard Worker 
3746*bb4ee6a4SAndroid Build Coastguard Worker     /// Looks up and open the given `path` in `fs`.
atomic_open( fs: &PassthroughFs, path: &Path, mode: u32, flags: u32, umask: u32, security_ctx: Option<&CStr>, ) -> io::Result<(Entry, Option<Handle>, OpenOptions)>3747*bb4ee6a4SAndroid Build Coastguard Worker     fn atomic_open(
3748*bb4ee6a4SAndroid Build Coastguard Worker         fs: &PassthroughFs,
3749*bb4ee6a4SAndroid Build Coastguard Worker         path: &Path,
3750*bb4ee6a4SAndroid Build Coastguard Worker         mode: u32,
3751*bb4ee6a4SAndroid Build Coastguard Worker         flags: u32,
3752*bb4ee6a4SAndroid Build Coastguard Worker         umask: u32,
3753*bb4ee6a4SAndroid Build Coastguard Worker         security_ctx: Option<&CStr>,
3754*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<(Entry, Option<Handle>, OpenOptions)> {
3755*bb4ee6a4SAndroid Build Coastguard Worker         let mut inode = 1;
3756*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
3757*bb4ee6a4SAndroid Build Coastguard Worker 
3758*bb4ee6a4SAndroid Build Coastguard Worker         let path_vec: Vec<_> = path.iter().collect();
3759*bb4ee6a4SAndroid Build Coastguard Worker         let vec_len = path_vec.len();
3760*bb4ee6a4SAndroid Build Coastguard Worker 
3761*bb4ee6a4SAndroid Build Coastguard Worker         // Do lookup before util (vec_len-1)-th pathname, this operation is to simulate
3762*bb4ee6a4SAndroid Build Coastguard Worker         // the behavior of VFS, since when VFS call atomic_open only at last look up.
3763*bb4ee6a4SAndroid Build Coastguard Worker         for name in &path_vec[0..vec_len - 1] {
3764*bb4ee6a4SAndroid Build Coastguard Worker             let name = CString::new(name.to_str().unwrap()).unwrap();
3765*bb4ee6a4SAndroid Build Coastguard Worker             let ent = fs.lookup(ctx, inode, &name)?;
3766*bb4ee6a4SAndroid Build Coastguard Worker             inode = ent.inode;
3767*bb4ee6a4SAndroid Build Coastguard Worker         }
3768*bb4ee6a4SAndroid Build Coastguard Worker 
3769*bb4ee6a4SAndroid Build Coastguard Worker         let name = CString::new(path_vec[vec_len - 1].to_str().unwrap()).unwrap();
3770*bb4ee6a4SAndroid Build Coastguard Worker 
3771*bb4ee6a4SAndroid Build Coastguard Worker         fs.atomic_open(ctx, inode, &name, mode, flags, umask, security_ctx)
3772*bb4ee6a4SAndroid Build Coastguard Worker     }
3773*bb4ee6a4SAndroid Build Coastguard Worker 
symlink( fs: &PassthroughFs, linkname: &Path, name: &Path, security_ctx: Option<&CStr>, ) -> io::Result<Entry>3774*bb4ee6a4SAndroid Build Coastguard Worker     fn symlink(
3775*bb4ee6a4SAndroid Build Coastguard Worker         fs: &PassthroughFs,
3776*bb4ee6a4SAndroid Build Coastguard Worker         linkname: &Path,
3777*bb4ee6a4SAndroid Build Coastguard Worker         name: &Path,
3778*bb4ee6a4SAndroid Build Coastguard Worker         security_ctx: Option<&CStr>,
3779*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<Entry> {
3780*bb4ee6a4SAndroid Build Coastguard Worker         let inode = 1;
3781*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
3782*bb4ee6a4SAndroid Build Coastguard Worker         let name = CString::new(name.to_str().unwrap()).unwrap();
3783*bb4ee6a4SAndroid Build Coastguard Worker         let linkname = CString::new(linkname.to_str().unwrap()).unwrap();
3784*bb4ee6a4SAndroid Build Coastguard Worker         fs.symlink(ctx, &linkname, inode, &name, security_ctx)
3785*bb4ee6a4SAndroid Build Coastguard Worker     }
3786*bb4ee6a4SAndroid Build Coastguard Worker 
3787*bb4ee6a4SAndroid Build Coastguard Worker     // In this ioctl inode,handle,flags,arg and out_size is irrelavant, set to empty value.
3788*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
fs_ioc_setpermission<R: io::Read>( fs: &PassthroughFs, in_size: u32, r: R, ) -> io::Result<IoctlReply>3789*bb4ee6a4SAndroid Build Coastguard Worker     fn fs_ioc_setpermission<R: io::Read>(
3790*bb4ee6a4SAndroid Build Coastguard Worker         fs: &PassthroughFs,
3791*bb4ee6a4SAndroid Build Coastguard Worker         in_size: u32,
3792*bb4ee6a4SAndroid Build Coastguard Worker         r: R,
3793*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<IoctlReply> {
3794*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
3795*bb4ee6a4SAndroid Build Coastguard Worker         fs.ioctl(
3796*bb4ee6a4SAndroid Build Coastguard Worker             ctx,
3797*bb4ee6a4SAndroid Build Coastguard Worker             0,
3798*bb4ee6a4SAndroid Build Coastguard Worker             0,
3799*bb4ee6a4SAndroid Build Coastguard Worker             IoctlFlags::empty(),
3800*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC_SETPERMISSION as u32,
3801*bb4ee6a4SAndroid Build Coastguard Worker             0,
3802*bb4ee6a4SAndroid Build Coastguard Worker             in_size,
3803*bb4ee6a4SAndroid Build Coastguard Worker             0,
3804*bb4ee6a4SAndroid Build Coastguard Worker             r,
3805*bb4ee6a4SAndroid Build Coastguard Worker         )
3806*bb4ee6a4SAndroid Build Coastguard Worker     }
3807*bb4ee6a4SAndroid Build Coastguard Worker 
3808*bb4ee6a4SAndroid Build Coastguard Worker     // In this ioctl inode,handle,flags,arg and out_size is irrelavant, set to empty value.
3809*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
fs_ioc_setpathxattr<R: io::Read>( fs: &PassthroughFs, in_size: u32, r: R, ) -> io::Result<IoctlReply>3810*bb4ee6a4SAndroid Build Coastguard Worker     fn fs_ioc_setpathxattr<R: io::Read>(
3811*bb4ee6a4SAndroid Build Coastguard Worker         fs: &PassthroughFs,
3812*bb4ee6a4SAndroid Build Coastguard Worker         in_size: u32,
3813*bb4ee6a4SAndroid Build Coastguard Worker         r: R,
3814*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<IoctlReply> {
3815*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
3816*bb4ee6a4SAndroid Build Coastguard Worker         fs.ioctl(
3817*bb4ee6a4SAndroid Build Coastguard Worker             ctx,
3818*bb4ee6a4SAndroid Build Coastguard Worker             0,
3819*bb4ee6a4SAndroid Build Coastguard Worker             0,
3820*bb4ee6a4SAndroid Build Coastguard Worker             IoctlFlags::empty(),
3821*bb4ee6a4SAndroid Build Coastguard Worker             FS_IOC_SETPATHXATTR as u32,
3822*bb4ee6a4SAndroid Build Coastguard Worker             0,
3823*bb4ee6a4SAndroid Build Coastguard Worker             in_size,
3824*bb4ee6a4SAndroid Build Coastguard Worker             0,
3825*bb4ee6a4SAndroid Build Coastguard Worker             r,
3826*bb4ee6a4SAndroid Build Coastguard Worker         )
3827*bb4ee6a4SAndroid Build Coastguard Worker     }
3828*bb4ee6a4SAndroid Build Coastguard Worker 
3829*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
rewrite_xattr_names()3830*bb4ee6a4SAndroid Build Coastguard Worker     fn rewrite_xattr_names() {
3831*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
3832*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
3833*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
3834*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
3835*bb4ee6a4SAndroid Build Coastguard Worker 
3836*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
3837*bb4ee6a4SAndroid Build Coastguard Worker             rewrite_security_xattrs: true,
3838*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
3839*bb4ee6a4SAndroid Build Coastguard Worker         };
3840*bb4ee6a4SAndroid Build Coastguard Worker 
3841*bb4ee6a4SAndroid Build Coastguard Worker         let p = PassthroughFs::new("tag", cfg).expect("Failed to create PassthroughFs");
3842*bb4ee6a4SAndroid Build Coastguard Worker 
3843*bb4ee6a4SAndroid Build Coastguard Worker         // Selinux shouldn't get overwritten.
3844*bb4ee6a4SAndroid Build Coastguard Worker         let selinux = c"security.selinux";
3845*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(p.rewrite_xattr_name(selinux).to_bytes(), selinux.to_bytes());
3846*bb4ee6a4SAndroid Build Coastguard Worker 
3847*bb4ee6a4SAndroid Build Coastguard Worker         // user, trusted, and system should not be changed either.
3848*bb4ee6a4SAndroid Build Coastguard Worker         let user = c"user.foobar";
3849*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(p.rewrite_xattr_name(user).to_bytes(), user.to_bytes());
3850*bb4ee6a4SAndroid Build Coastguard Worker         let trusted = c"trusted.foobar";
3851*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(p.rewrite_xattr_name(trusted).to_bytes(), trusted.to_bytes());
3852*bb4ee6a4SAndroid Build Coastguard Worker         let system = c"system.foobar";
3853*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(p.rewrite_xattr_name(system).to_bytes(), system.to_bytes());
3854*bb4ee6a4SAndroid Build Coastguard Worker 
3855*bb4ee6a4SAndroid Build Coastguard Worker         // sehash should be re-written.
3856*bb4ee6a4SAndroid Build Coastguard Worker         let sehash = c"security.sehash";
3857*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
3858*bb4ee6a4SAndroid Build Coastguard Worker             p.rewrite_xattr_name(sehash).to_bytes(),
3859*bb4ee6a4SAndroid Build Coastguard Worker             b"user.virtiofs.security.sehash"
3860*bb4ee6a4SAndroid Build Coastguard Worker         );
3861*bb4ee6a4SAndroid Build Coastguard Worker     }
3862*bb4ee6a4SAndroid Build Coastguard Worker 
3863*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
strip_xattr_names()3864*bb4ee6a4SAndroid Build Coastguard Worker     fn strip_xattr_names() {
3865*bb4ee6a4SAndroid Build Coastguard Worker         let only_nuls = b"\0\0\0\0\0";
3866*bb4ee6a4SAndroid Build Coastguard Worker         let mut actual = only_nuls.to_vec();
3867*bb4ee6a4SAndroid Build Coastguard Worker         strip_xattr_prefix(&mut actual);
3868*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&actual[..], &only_nuls[..]);
3869*bb4ee6a4SAndroid Build Coastguard Worker 
3870*bb4ee6a4SAndroid Build Coastguard Worker         let no_nuls = b"security.sehashuser.virtiofs";
3871*bb4ee6a4SAndroid Build Coastguard Worker         let mut actual = no_nuls.to_vec();
3872*bb4ee6a4SAndroid Build Coastguard Worker         strip_xattr_prefix(&mut actual);
3873*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&actual[..], &no_nuls[..]);
3874*bb4ee6a4SAndroid Build Coastguard Worker 
3875*bb4ee6a4SAndroid Build Coastguard Worker         let empty = b"";
3876*bb4ee6a4SAndroid Build Coastguard Worker         let mut actual = empty.to_vec();
3877*bb4ee6a4SAndroid Build Coastguard Worker         strip_xattr_prefix(&mut actual);
3878*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&actual[..], &empty[..]);
3879*bb4ee6a4SAndroid Build Coastguard Worker 
3880*bb4ee6a4SAndroid Build Coastguard Worker         let no_strippable_names = b"security.selinux\0user.foobar\0system.test\0";
3881*bb4ee6a4SAndroid Build Coastguard Worker         let mut actual = no_strippable_names.to_vec();
3882*bb4ee6a4SAndroid Build Coastguard Worker         strip_xattr_prefix(&mut actual);
3883*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&actual[..], &no_strippable_names[..]);
3884*bb4ee6a4SAndroid Build Coastguard Worker 
3885*bb4ee6a4SAndroid Build Coastguard Worker         let only_strippable_names = b"user.virtiofs.security.sehash\0user.virtiofs.security.wat\0";
3886*bb4ee6a4SAndroid Build Coastguard Worker         let mut actual = only_strippable_names.to_vec();
3887*bb4ee6a4SAndroid Build Coastguard Worker         strip_xattr_prefix(&mut actual);
3888*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&actual[..], b"security.sehash\0security.wat\0");
3889*bb4ee6a4SAndroid Build Coastguard Worker 
3890*bb4ee6a4SAndroid Build Coastguard Worker         let mixed_names = b"user.virtiofs.security.sehash\0security.selinux\0user.virtiofs.security.wat\0user.foobar\0";
3891*bb4ee6a4SAndroid Build Coastguard Worker         let mut actual = mixed_names.to_vec();
3892*bb4ee6a4SAndroid Build Coastguard Worker         strip_xattr_prefix(&mut actual);
3893*bb4ee6a4SAndroid Build Coastguard Worker         let expected = b"security.sehash\0security.selinux\0security.wat\0user.foobar\0";
3894*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&actual[..], &expected[..]);
3895*bb4ee6a4SAndroid Build Coastguard Worker 
3896*bb4ee6a4SAndroid Build Coastguard Worker         let no_nul_with_prefix = b"user.virtiofs.security.sehash";
3897*bb4ee6a4SAndroid Build Coastguard Worker         let mut actual = no_nul_with_prefix.to_vec();
3898*bb4ee6a4SAndroid Build Coastguard Worker         strip_xattr_prefix(&mut actual);
3899*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&actual[..], b"security.sehash");
3900*bb4ee6a4SAndroid Build Coastguard Worker     }
3901*bb4ee6a4SAndroid Build Coastguard Worker 
3902*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
lookup_files()3903*bb4ee6a4SAndroid Build Coastguard Worker     fn lookup_files() {
3904*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
3905*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
3906*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
3907*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
3908*bb4ee6a4SAndroid Build Coastguard Worker 
3909*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
3910*bb4ee6a4SAndroid Build Coastguard Worker         create_test_data(&temp_dir, &["dir"], &["a.txt", "dir/b.txt"]);
3911*bb4ee6a4SAndroid Build Coastguard Worker 
3912*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Default::default();
3913*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
3914*bb4ee6a4SAndroid Build Coastguard Worker 
3915*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::empty();
3916*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
3917*bb4ee6a4SAndroid Build Coastguard Worker 
3918*bb4ee6a4SAndroid Build Coastguard Worker         assert!(lookup(&fs, &temp_dir.path().join("a.txt")).is_ok());
3919*bb4ee6a4SAndroid Build Coastguard Worker         assert!(lookup(&fs, &temp_dir.path().join("dir")).is_ok());
3920*bb4ee6a4SAndroid Build Coastguard Worker         assert!(lookup(&fs, &temp_dir.path().join("dir/b.txt")).is_ok());
3921*bb4ee6a4SAndroid Build Coastguard Worker 
3922*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
3923*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &temp_dir.path().join("nonexistent-file"))
3924*bb4ee6a4SAndroid Build Coastguard Worker                 .expect_err("file must not exist")
3925*bb4ee6a4SAndroid Build Coastguard Worker                 .kind(),
3926*bb4ee6a4SAndroid Build Coastguard Worker             io::ErrorKind::NotFound
3927*bb4ee6a4SAndroid Build Coastguard Worker         );
3928*bb4ee6a4SAndroid Build Coastguard Worker         // "A.txt" is different from "a.txt".
3929*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
3930*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &temp_dir.path().join("A.txt"))
3931*bb4ee6a4SAndroid Build Coastguard Worker                 .expect_err("file must not exist")
3932*bb4ee6a4SAndroid Build Coastguard Worker                 .kind(),
3933*bb4ee6a4SAndroid Build Coastguard Worker             io::ErrorKind::NotFound
3934*bb4ee6a4SAndroid Build Coastguard Worker         );
3935*bb4ee6a4SAndroid Build Coastguard Worker     }
3936*bb4ee6a4SAndroid Build Coastguard Worker 
3937*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
lookup_files_ascii_casefold()3938*bb4ee6a4SAndroid Build Coastguard Worker     fn lookup_files_ascii_casefold() {
3939*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
3940*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
3941*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
3942*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
3943*bb4ee6a4SAndroid Build Coastguard Worker 
3944*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
3945*bb4ee6a4SAndroid Build Coastguard Worker         create_test_data(&temp_dir, &["dir"], &["a.txt", "dir/b.txt"]);
3946*bb4ee6a4SAndroid Build Coastguard Worker 
3947*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
3948*bb4ee6a4SAndroid Build Coastguard Worker             ascii_casefold: true,
3949*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
3950*bb4ee6a4SAndroid Build Coastguard Worker         };
3951*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
3952*bb4ee6a4SAndroid Build Coastguard Worker 
3953*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::empty();
3954*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
3955*bb4ee6a4SAndroid Build Coastguard Worker 
3956*bb4ee6a4SAndroid Build Coastguard Worker         // Ensure that "A.txt" is equated with "a.txt".
3957*bb4ee6a4SAndroid Build Coastguard Worker         let a_inode = lookup(&fs, &temp_dir.path().join("a.txt")).expect("a.txt must be found");
3958*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
3959*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &temp_dir.path().join("A.txt")).expect("A.txt must exist"),
3960*bb4ee6a4SAndroid Build Coastguard Worker             a_inode
3961*bb4ee6a4SAndroid Build Coastguard Worker         );
3962*bb4ee6a4SAndroid Build Coastguard Worker 
3963*bb4ee6a4SAndroid Build Coastguard Worker         let dir_inode = lookup(&fs, &temp_dir.path().join("dir")).expect("dir must be found");
3964*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
3965*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &temp_dir.path().join("DiR")).expect("DiR must exist"),
3966*bb4ee6a4SAndroid Build Coastguard Worker             dir_inode
3967*bb4ee6a4SAndroid Build Coastguard Worker         );
3968*bb4ee6a4SAndroid Build Coastguard Worker 
3969*bb4ee6a4SAndroid Build Coastguard Worker         let b_inode =
3970*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &temp_dir.path().join("dir/b.txt")).expect("dir/b.txt must be found");
3971*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
3972*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &temp_dir.path().join("dIr/B.TxT")).expect("dIr/B.TxT must exist"),
3973*bb4ee6a4SAndroid Build Coastguard Worker             b_inode
3974*bb4ee6a4SAndroid Build Coastguard Worker         );
3975*bb4ee6a4SAndroid Build Coastguard Worker 
3976*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
3977*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &temp_dir.path().join("nonexistent-file"))
3978*bb4ee6a4SAndroid Build Coastguard Worker                 .expect_err("file must not exist")
3979*bb4ee6a4SAndroid Build Coastguard Worker                 .kind(),
3980*bb4ee6a4SAndroid Build Coastguard Worker             io::ErrorKind::NotFound
3981*bb4ee6a4SAndroid Build Coastguard Worker         );
3982*bb4ee6a4SAndroid Build Coastguard Worker     }
3983*bb4ee6a4SAndroid Build Coastguard Worker 
test_create_and_remove(ascii_casefold: bool)3984*bb4ee6a4SAndroid Build Coastguard Worker     fn test_create_and_remove(ascii_casefold: bool) {
3985*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
3986*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
3987*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
3988*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
3989*bb4ee6a4SAndroid Build Coastguard Worker 
3990*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
3991*bb4ee6a4SAndroid Build Coastguard Worker         let timeout = Duration::from_millis(10);
3992*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
3993*bb4ee6a4SAndroid Build Coastguard Worker             timeout,
3994*bb4ee6a4SAndroid Build Coastguard Worker             cache_policy: CachePolicy::Auto,
3995*bb4ee6a4SAndroid Build Coastguard Worker             ascii_casefold,
3996*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
3997*bb4ee6a4SAndroid Build Coastguard Worker         };
3998*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
3999*bb4ee6a4SAndroid Build Coastguard Worker 
4000*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::empty();
4001*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
4002*bb4ee6a4SAndroid Build Coastguard Worker 
4003*bb4ee6a4SAndroid Build Coastguard Worker         // Create a.txt and b.txt.
4004*bb4ee6a4SAndroid Build Coastguard Worker         let a_path = temp_dir.path().join("a.txt");
4005*bb4ee6a4SAndroid Build Coastguard Worker         let b_path = temp_dir.path().join("b.txt");
4006*bb4ee6a4SAndroid Build Coastguard Worker         let a_entry = create(&fs, &a_path).expect("create a.txt");
4007*bb4ee6a4SAndroid Build Coastguard Worker         let b_entry = create(&fs, &b_path).expect("create b.txt");
4008*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
4009*bb4ee6a4SAndroid Build Coastguard Worker             a_entry.inode,
4010*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &a_path).expect("lookup a.txt"),
4011*bb4ee6a4SAndroid Build Coastguard Worker             "Created file 'a.txt' must be looked up"
4012*bb4ee6a4SAndroid Build Coastguard Worker         );
4013*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
4014*bb4ee6a4SAndroid Build Coastguard Worker             b_entry.inode,
4015*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &b_path).expect("lookup b.txt"),
4016*bb4ee6a4SAndroid Build Coastguard Worker             "Created file 'b.txt' must be looked up"
4017*bb4ee6a4SAndroid Build Coastguard Worker         );
4018*bb4ee6a4SAndroid Build Coastguard Worker 
4019*bb4ee6a4SAndroid Build Coastguard Worker         // Remove a.txt only
4020*bb4ee6a4SAndroid Build Coastguard Worker         unlink(&fs, &a_path).expect("Remove");
4021*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
4022*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &a_path)
4023*bb4ee6a4SAndroid Build Coastguard Worker                 .expect_err("file must not exist")
4024*bb4ee6a4SAndroid Build Coastguard Worker                 .kind(),
4025*bb4ee6a4SAndroid Build Coastguard Worker             io::ErrorKind::NotFound,
4026*bb4ee6a4SAndroid Build Coastguard Worker             "a.txt must be removed"
4027*bb4ee6a4SAndroid Build Coastguard Worker         );
4028*bb4ee6a4SAndroid Build Coastguard Worker         // "A.TXT" must not be found regardless of whether casefold is enabled or not.
4029*bb4ee6a4SAndroid Build Coastguard Worker         let upper_a_path = temp_dir.path().join("A.TXT");
4030*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
4031*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &upper_a_path)
4032*bb4ee6a4SAndroid Build Coastguard Worker                 .expect_err("file must not exist")
4033*bb4ee6a4SAndroid Build Coastguard Worker                 .kind(),
4034*bb4ee6a4SAndroid Build Coastguard Worker             io::ErrorKind::NotFound,
4035*bb4ee6a4SAndroid Build Coastguard Worker             "A.txt must be removed"
4036*bb4ee6a4SAndroid Build Coastguard Worker         );
4037*bb4ee6a4SAndroid Build Coastguard Worker 
4038*bb4ee6a4SAndroid Build Coastguard Worker         // Check if the host file system doesn't have a.txt but does b.txt.
4039*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!a_path.exists(), "a.txt must be removed");
4040*bb4ee6a4SAndroid Build Coastguard Worker         assert!(b_path.exists(), "b.txt must exist");
4041*bb4ee6a4SAndroid Build Coastguard Worker     }
4042*bb4ee6a4SAndroid Build Coastguard Worker 
4043*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
create_and_remove()4044*bb4ee6a4SAndroid Build Coastguard Worker     fn create_and_remove() {
4045*bb4ee6a4SAndroid Build Coastguard Worker         test_create_and_remove(false /* casefold */);
4046*bb4ee6a4SAndroid Build Coastguard Worker     }
4047*bb4ee6a4SAndroid Build Coastguard Worker 
4048*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
create_and_remove_casefold()4049*bb4ee6a4SAndroid Build Coastguard Worker     fn create_and_remove_casefold() {
4050*bb4ee6a4SAndroid Build Coastguard Worker         test_create_and_remove(true /* casefold */);
4051*bb4ee6a4SAndroid Build Coastguard Worker     }
4052*bb4ee6a4SAndroid Build Coastguard Worker 
test_create_and_forget(ascii_casefold: bool)4053*bb4ee6a4SAndroid Build Coastguard Worker     fn test_create_and_forget(ascii_casefold: bool) {
4054*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
4055*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
4056*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
4057*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
4058*bb4ee6a4SAndroid Build Coastguard Worker 
4059*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
4060*bb4ee6a4SAndroid Build Coastguard Worker         let timeout = Duration::from_millis(10);
4061*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
4062*bb4ee6a4SAndroid Build Coastguard Worker             timeout,
4063*bb4ee6a4SAndroid Build Coastguard Worker             cache_policy: CachePolicy::Auto,
4064*bb4ee6a4SAndroid Build Coastguard Worker             ascii_casefold,
4065*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4066*bb4ee6a4SAndroid Build Coastguard Worker         };
4067*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
4068*bb4ee6a4SAndroid Build Coastguard Worker 
4069*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::empty();
4070*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
4071*bb4ee6a4SAndroid Build Coastguard Worker 
4072*bb4ee6a4SAndroid Build Coastguard Worker         // Create a.txt.
4073*bb4ee6a4SAndroid Build Coastguard Worker         let a_path = temp_dir.path().join("a.txt");
4074*bb4ee6a4SAndroid Build Coastguard Worker         let a_entry = create(&fs, &a_path).expect("create a.txt");
4075*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
4076*bb4ee6a4SAndroid Build Coastguard Worker             a_entry.inode,
4077*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &a_path).expect("lookup a.txt"),
4078*bb4ee6a4SAndroid Build Coastguard Worker             "Created file 'a.txt' must be looked up"
4079*bb4ee6a4SAndroid Build Coastguard Worker         );
4080*bb4ee6a4SAndroid Build Coastguard Worker 
4081*bb4ee6a4SAndroid Build Coastguard Worker         // Forget a.txt's inode from PassthroughFs's internal cache.
4082*bb4ee6a4SAndroid Build Coastguard Worker         forget(&fs, &a_path).expect("forget a.txt");
4083*bb4ee6a4SAndroid Build Coastguard Worker 
4084*bb4ee6a4SAndroid Build Coastguard Worker         if ascii_casefold {
4085*bb4ee6a4SAndroid Build Coastguard Worker             let upper_a_path = temp_dir.path().join("A.TXT");
4086*bb4ee6a4SAndroid Build Coastguard Worker             let new_a_inode = lookup(&fs, &upper_a_path).expect("lookup a.txt");
4087*bb4ee6a4SAndroid Build Coastguard Worker             assert_ne!(
4088*bb4ee6a4SAndroid Build Coastguard Worker                 a_entry.inode, new_a_inode,
4089*bb4ee6a4SAndroid Build Coastguard Worker                 "inode must be changed after forget()"
4090*bb4ee6a4SAndroid Build Coastguard Worker             );
4091*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(
4092*bb4ee6a4SAndroid Build Coastguard Worker                 new_a_inode,
4093*bb4ee6a4SAndroid Build Coastguard Worker                 lookup(&fs, &a_path).expect("lookup a.txt"),
4094*bb4ee6a4SAndroid Build Coastguard Worker                 "inode must be same for a.txt and A.TXT"
4095*bb4ee6a4SAndroid Build Coastguard Worker             );
4096*bb4ee6a4SAndroid Build Coastguard Worker         } else {
4097*bb4ee6a4SAndroid Build Coastguard Worker             assert_ne!(
4098*bb4ee6a4SAndroid Build Coastguard Worker                 a_entry.inode,
4099*bb4ee6a4SAndroid Build Coastguard Worker                 lookup(&fs, &a_path).expect("lookup a.txt"),
4100*bb4ee6a4SAndroid Build Coastguard Worker                 "inode must be changed after forget()"
4101*bb4ee6a4SAndroid Build Coastguard Worker             );
4102*bb4ee6a4SAndroid Build Coastguard Worker         }
4103*bb4ee6a4SAndroid Build Coastguard Worker     }
4104*bb4ee6a4SAndroid Build Coastguard Worker 
4105*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
create_and_forget()4106*bb4ee6a4SAndroid Build Coastguard Worker     fn create_and_forget() {
4107*bb4ee6a4SAndroid Build Coastguard Worker         test_create_and_forget(false /* ascii_casefold */);
4108*bb4ee6a4SAndroid Build Coastguard Worker     }
4109*bb4ee6a4SAndroid Build Coastguard Worker 
4110*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
create_and_forget_casefold()4111*bb4ee6a4SAndroid Build Coastguard Worker     fn create_and_forget_casefold() {
4112*bb4ee6a4SAndroid Build Coastguard Worker         test_create_and_forget(true /* ascii_casefold */);
4113*bb4ee6a4SAndroid Build Coastguard Worker     }
4114*bb4ee6a4SAndroid Build Coastguard Worker 
4115*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
casefold_lookup_cache()4116*bb4ee6a4SAndroid Build Coastguard Worker     fn casefold_lookup_cache() {
4117*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
4118*bb4ee6a4SAndroid Build Coastguard Worker         // Prepare `a.txt` before starting the test.
4119*bb4ee6a4SAndroid Build Coastguard Worker         create_test_data(&temp_dir, &[], &["a.txt"]);
4120*bb4ee6a4SAndroid Build Coastguard Worker 
4121*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
4122*bb4ee6a4SAndroid Build Coastguard Worker             ascii_casefold: true,
4123*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4124*bb4ee6a4SAndroid Build Coastguard Worker         };
4125*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
4126*bb4ee6a4SAndroid Build Coastguard Worker 
4127*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::empty();
4128*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
4129*bb4ee6a4SAndroid Build Coastguard Worker 
4130*bb4ee6a4SAndroid Build Coastguard Worker         let parent = lookup(&fs, temp_dir.path()).expect("lookup temp_dir");
4131*bb4ee6a4SAndroid Build Coastguard Worker 
4132*bb4ee6a4SAndroid Build Coastguard Worker         // Since `a.txt` exists, "A.TXT" must exist.
4133*bb4ee6a4SAndroid Build Coastguard Worker         let large_a_path = temp_dir.path().join("A.TXT");
4134*bb4ee6a4SAndroid Build Coastguard Worker         // Looking up "A.TXT" must create a CasefoldCache entry.
4135*bb4ee6a4SAndroid Build Coastguard Worker         lookup(&fs, &large_a_path).expect("A.TXT must exist");
4136*bb4ee6a4SAndroid Build Coastguard Worker         assert!(fs.exists_in_casefold_cache(parent, &CString::new("A.TXT").unwrap()));
4137*bb4ee6a4SAndroid Build Coastguard Worker 
4138*bb4ee6a4SAndroid Build Coastguard Worker         // Create b.txt.
4139*bb4ee6a4SAndroid Build Coastguard Worker         let b_path = temp_dir.path().join("b.txt");
4140*bb4ee6a4SAndroid Build Coastguard Worker         create(&fs, &b_path).expect("create b.txt");
4141*bb4ee6a4SAndroid Build Coastguard Worker         // Then, b.txt must exists in the cache.
4142*bb4ee6a4SAndroid Build Coastguard Worker         assert!(fs.exists_in_casefold_cache(parent, &CString::new("B.TXT").unwrap()));
4143*bb4ee6a4SAndroid Build Coastguard Worker         // When removing b.txt, it must be removed from the cache as well.
4144*bb4ee6a4SAndroid Build Coastguard Worker         unlink(&fs, &b_path).expect("remove b.txt");
4145*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!fs.exists_in_casefold_cache(parent, &CString::new("B.TXT").unwrap()));
4146*bb4ee6a4SAndroid Build Coastguard Worker     }
4147*bb4ee6a4SAndroid Build Coastguard Worker 
4148*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
lookup_negative_cache()4149*bb4ee6a4SAndroid Build Coastguard Worker     fn lookup_negative_cache() {
4150*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
4151*bb4ee6a4SAndroid Build Coastguard Worker         // Prepare `a.txt` before starting the test.
4152*bb4ee6a4SAndroid Build Coastguard Worker         create_test_data(&temp_dir, &[], &[]);
4153*bb4ee6a4SAndroid Build Coastguard Worker 
4154*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
4155*bb4ee6a4SAndroid Build Coastguard Worker             negative_timeout: Duration::from_secs(5),
4156*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4157*bb4ee6a4SAndroid Build Coastguard Worker         };
4158*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
4159*bb4ee6a4SAndroid Build Coastguard Worker 
4160*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::empty();
4161*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
4162*bb4ee6a4SAndroid Build Coastguard Worker 
4163*bb4ee6a4SAndroid Build Coastguard Worker         let a_path = temp_dir.path().join("a.txt");
4164*bb4ee6a4SAndroid Build Coastguard Worker         // a.txt hasn't existed yet.
4165*bb4ee6a4SAndroid Build Coastguard Worker         // Since negative_timeout is enabled, success with inode=0 is expected.
4166*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
4167*bb4ee6a4SAndroid Build Coastguard Worker             0,
4168*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &a_path).expect("lookup a.txt"),
4169*bb4ee6a4SAndroid Build Coastguard Worker             "Entry with inode=0 is expected for non-existing file 'a.txt'"
4170*bb4ee6a4SAndroid Build Coastguard Worker         );
4171*bb4ee6a4SAndroid Build Coastguard Worker         // Create a.txt
4172*bb4ee6a4SAndroid Build Coastguard Worker         let a_entry = create(&fs, &a_path).expect("create a.txt");
4173*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
4174*bb4ee6a4SAndroid Build Coastguard Worker             a_entry.inode,
4175*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &a_path).expect("lookup a.txt"),
4176*bb4ee6a4SAndroid Build Coastguard Worker             "Created file 'a.txt' must be looked up"
4177*bb4ee6a4SAndroid Build Coastguard Worker         );
4178*bb4ee6a4SAndroid Build Coastguard Worker         // Remove a.txt
4179*bb4ee6a4SAndroid Build Coastguard Worker         unlink(&fs, &a_path).expect("Remove");
4180*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
4181*bb4ee6a4SAndroid Build Coastguard Worker             0,
4182*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &a_path).expect("lookup a.txt"),
4183*bb4ee6a4SAndroid Build Coastguard Worker             "Entry with inode=0 is expected for the removed file 'a.txt'"
4184*bb4ee6a4SAndroid Build Coastguard Worker         );
4185*bb4ee6a4SAndroid Build Coastguard Worker     }
4186*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
test_atomic_open_existing_file()4187*bb4ee6a4SAndroid Build Coastguard Worker     fn test_atomic_open_existing_file() {
4188*bb4ee6a4SAndroid Build Coastguard Worker         atomic_open_existing_file(false);
4189*bb4ee6a4SAndroid Build Coastguard Worker     }
4190*bb4ee6a4SAndroid Build Coastguard Worker 
4191*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
test_atomic_open_existing_file_zero_message()4192*bb4ee6a4SAndroid Build Coastguard Worker     fn test_atomic_open_existing_file_zero_message() {
4193*bb4ee6a4SAndroid Build Coastguard Worker         atomic_open_existing_file(true);
4194*bb4ee6a4SAndroid Build Coastguard Worker     }
4195*bb4ee6a4SAndroid Build Coastguard Worker 
atomic_open_existing_file(zero_message_open: bool)4196*bb4ee6a4SAndroid Build Coastguard Worker     fn atomic_open_existing_file(zero_message_open: bool) {
4197*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
4198*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
4199*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
4200*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
4201*bb4ee6a4SAndroid Build Coastguard Worker 
4202*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
4203*bb4ee6a4SAndroid Build Coastguard Worker         create_test_data(&temp_dir, &["dir"], &["a.txt", "dir/b.txt", "dir/c.txt"]);
4204*bb4ee6a4SAndroid Build Coastguard Worker 
4205*bb4ee6a4SAndroid Build Coastguard Worker         let cache_policy = match zero_message_open {
4206*bb4ee6a4SAndroid Build Coastguard Worker             true => CachePolicy::Always,
4207*bb4ee6a4SAndroid Build Coastguard Worker             false => CachePolicy::Auto,
4208*bb4ee6a4SAndroid Build Coastguard Worker         };
4209*bb4ee6a4SAndroid Build Coastguard Worker 
4210*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
4211*bb4ee6a4SAndroid Build Coastguard Worker             cache_policy,
4212*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4213*bb4ee6a4SAndroid Build Coastguard Worker         };
4214*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
4215*bb4ee6a4SAndroid Build Coastguard Worker 
4216*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::ZERO_MESSAGE_OPEN;
4217*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
4218*bb4ee6a4SAndroid Build Coastguard Worker 
4219*bb4ee6a4SAndroid Build Coastguard Worker         // atomic_open with flag O_RDWR, should return positive dentry and file handler
4220*bb4ee6a4SAndroid Build Coastguard Worker         let res = atomic_open(
4221*bb4ee6a4SAndroid Build Coastguard Worker             &fs,
4222*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("a.txt"),
4223*bb4ee6a4SAndroid Build Coastguard Worker             0o666,
4224*bb4ee6a4SAndroid Build Coastguard Worker             libc::O_RDWR as u32,
4225*bb4ee6a4SAndroid Build Coastguard Worker             0,
4226*bb4ee6a4SAndroid Build Coastguard Worker             None,
4227*bb4ee6a4SAndroid Build Coastguard Worker         );
4228*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res.is_ok());
4229*bb4ee6a4SAndroid Build Coastguard Worker         let (entry, handler, open_options) = res.unwrap();
4230*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(entry.inode, 0);
4231*bb4ee6a4SAndroid Build Coastguard Worker 
4232*bb4ee6a4SAndroid Build Coastguard Worker         if zero_message_open {
4233*bb4ee6a4SAndroid Build Coastguard Worker             assert!(handler.is_none());
4234*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(open_options, OpenOptions::KEEP_CACHE);
4235*bb4ee6a4SAndroid Build Coastguard Worker         } else {
4236*bb4ee6a4SAndroid Build Coastguard Worker             assert!(handler.is_some());
4237*bb4ee6a4SAndroid Build Coastguard Worker             assert_ne!(
4238*bb4ee6a4SAndroid Build Coastguard Worker                 open_options & OpenOptions::FILE_CREATED,
4239*bb4ee6a4SAndroid Build Coastguard Worker                 OpenOptions::FILE_CREATED
4240*bb4ee6a4SAndroid Build Coastguard Worker             );
4241*bb4ee6a4SAndroid Build Coastguard Worker         }
4242*bb4ee6a4SAndroid Build Coastguard Worker 
4243*bb4ee6a4SAndroid Build Coastguard Worker         // atomic_open with flag O_RDWR |  O_CREATE, should return positive dentry and file handler
4244*bb4ee6a4SAndroid Build Coastguard Worker         let res = atomic_open(
4245*bb4ee6a4SAndroid Build Coastguard Worker             &fs,
4246*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("dir/b.txt"),
4247*bb4ee6a4SAndroid Build Coastguard Worker             0o666,
4248*bb4ee6a4SAndroid Build Coastguard Worker             (libc::O_RDWR | libc::O_CREAT) as u32,
4249*bb4ee6a4SAndroid Build Coastguard Worker             0,
4250*bb4ee6a4SAndroid Build Coastguard Worker             None,
4251*bb4ee6a4SAndroid Build Coastguard Worker         );
4252*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res.is_ok());
4253*bb4ee6a4SAndroid Build Coastguard Worker         let (entry, handler, open_options) = res.unwrap();
4254*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(entry.inode, 0);
4255*bb4ee6a4SAndroid Build Coastguard Worker 
4256*bb4ee6a4SAndroid Build Coastguard Worker         if zero_message_open {
4257*bb4ee6a4SAndroid Build Coastguard Worker             assert!(handler.is_none());
4258*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(open_options, OpenOptions::KEEP_CACHE);
4259*bb4ee6a4SAndroid Build Coastguard Worker         } else {
4260*bb4ee6a4SAndroid Build Coastguard Worker             assert!(handler.is_some());
4261*bb4ee6a4SAndroid Build Coastguard Worker             assert_ne!(
4262*bb4ee6a4SAndroid Build Coastguard Worker                 open_options & OpenOptions::FILE_CREATED,
4263*bb4ee6a4SAndroid Build Coastguard Worker                 OpenOptions::FILE_CREATED
4264*bb4ee6a4SAndroid Build Coastguard Worker             );
4265*bb4ee6a4SAndroid Build Coastguard Worker         }
4266*bb4ee6a4SAndroid Build Coastguard Worker 
4267*bb4ee6a4SAndroid Build Coastguard Worker         // atomic_open with flag O_RDWR | O_CREATE | O_EXCL, should return positive dentry and file
4268*bb4ee6a4SAndroid Build Coastguard Worker         // handler
4269*bb4ee6a4SAndroid Build Coastguard Worker         let res = atomic_open(
4270*bb4ee6a4SAndroid Build Coastguard Worker             &fs,
4271*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("dir/c.txt"),
4272*bb4ee6a4SAndroid Build Coastguard Worker             0o666,
4273*bb4ee6a4SAndroid Build Coastguard Worker             (libc::O_RDWR | libc::O_CREAT | libc::O_EXCL) as u32,
4274*bb4ee6a4SAndroid Build Coastguard Worker             0,
4275*bb4ee6a4SAndroid Build Coastguard Worker             None,
4276*bb4ee6a4SAndroid Build Coastguard Worker         );
4277*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res.is_err());
4278*bb4ee6a4SAndroid Build Coastguard Worker         let err_kind = res.unwrap_err().kind();
4279*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(err_kind, io::ErrorKind::AlreadyExists);
4280*bb4ee6a4SAndroid Build Coastguard Worker     }
4281*bb4ee6a4SAndroid Build Coastguard Worker 
4282*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
test_atomic_open_non_existing_file()4283*bb4ee6a4SAndroid Build Coastguard Worker     fn test_atomic_open_non_existing_file() {
4284*bb4ee6a4SAndroid Build Coastguard Worker         atomic_open_non_existing_file(false);
4285*bb4ee6a4SAndroid Build Coastguard Worker     }
4286*bb4ee6a4SAndroid Build Coastguard Worker 
4287*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
test_atomic_open_non_existing_file_zero_message()4288*bb4ee6a4SAndroid Build Coastguard Worker     fn test_atomic_open_non_existing_file_zero_message() {
4289*bb4ee6a4SAndroid Build Coastguard Worker         atomic_open_non_existing_file(true);
4290*bb4ee6a4SAndroid Build Coastguard Worker     }
4291*bb4ee6a4SAndroid Build Coastguard Worker 
atomic_open_non_existing_file(zero_message_open: bool)4292*bb4ee6a4SAndroid Build Coastguard Worker     fn atomic_open_non_existing_file(zero_message_open: bool) {
4293*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
4294*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
4295*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
4296*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
4297*bb4ee6a4SAndroid Build Coastguard Worker 
4298*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
4299*bb4ee6a4SAndroid Build Coastguard Worker 
4300*bb4ee6a4SAndroid Build Coastguard Worker         let cache_policy = match zero_message_open {
4301*bb4ee6a4SAndroid Build Coastguard Worker             true => CachePolicy::Always,
4302*bb4ee6a4SAndroid Build Coastguard Worker             false => CachePolicy::Auto,
4303*bb4ee6a4SAndroid Build Coastguard Worker         };
4304*bb4ee6a4SAndroid Build Coastguard Worker 
4305*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
4306*bb4ee6a4SAndroid Build Coastguard Worker             cache_policy,
4307*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4308*bb4ee6a4SAndroid Build Coastguard Worker         };
4309*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
4310*bb4ee6a4SAndroid Build Coastguard Worker 
4311*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::ZERO_MESSAGE_OPEN;
4312*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
4313*bb4ee6a4SAndroid Build Coastguard Worker 
4314*bb4ee6a4SAndroid Build Coastguard Worker         // atomic_open with flag O_RDWR, should return NO_EXIST error
4315*bb4ee6a4SAndroid Build Coastguard Worker         let res = atomic_open(
4316*bb4ee6a4SAndroid Build Coastguard Worker             &fs,
4317*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("a.txt"),
4318*bb4ee6a4SAndroid Build Coastguard Worker             0o666,
4319*bb4ee6a4SAndroid Build Coastguard Worker             libc::O_RDWR as u32,
4320*bb4ee6a4SAndroid Build Coastguard Worker             0,
4321*bb4ee6a4SAndroid Build Coastguard Worker             None,
4322*bb4ee6a4SAndroid Build Coastguard Worker         );
4323*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res.is_err());
4324*bb4ee6a4SAndroid Build Coastguard Worker         let err_kind = res.unwrap_err().kind();
4325*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(err_kind, io::ErrorKind::NotFound);
4326*bb4ee6a4SAndroid Build Coastguard Worker 
4327*bb4ee6a4SAndroid Build Coastguard Worker         // atomic_open with flag O_RDWR | O_CREATE, should return positive dentry and file handler
4328*bb4ee6a4SAndroid Build Coastguard Worker         let res = atomic_open(
4329*bb4ee6a4SAndroid Build Coastguard Worker             &fs,
4330*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("b.txt"),
4331*bb4ee6a4SAndroid Build Coastguard Worker             0o666,
4332*bb4ee6a4SAndroid Build Coastguard Worker             (libc::O_RDWR | libc::O_CREAT) as u32,
4333*bb4ee6a4SAndroid Build Coastguard Worker             0,
4334*bb4ee6a4SAndroid Build Coastguard Worker             None,
4335*bb4ee6a4SAndroid Build Coastguard Worker         );
4336*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res.is_ok());
4337*bb4ee6a4SAndroid Build Coastguard Worker         let (entry, handler, open_options) = res.unwrap();
4338*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(entry.inode, 0);
4339*bb4ee6a4SAndroid Build Coastguard Worker 
4340*bb4ee6a4SAndroid Build Coastguard Worker         if zero_message_open {
4341*bb4ee6a4SAndroid Build Coastguard Worker             assert!(handler.is_none());
4342*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(
4343*bb4ee6a4SAndroid Build Coastguard Worker                 open_options & OpenOptions::KEEP_CACHE,
4344*bb4ee6a4SAndroid Build Coastguard Worker                 OpenOptions::KEEP_CACHE
4345*bb4ee6a4SAndroid Build Coastguard Worker             );
4346*bb4ee6a4SAndroid Build Coastguard Worker         } else {
4347*bb4ee6a4SAndroid Build Coastguard Worker             assert!(handler.is_some());
4348*bb4ee6a4SAndroid Build Coastguard Worker         }
4349*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
4350*bb4ee6a4SAndroid Build Coastguard Worker             open_options & OpenOptions::FILE_CREATED,
4351*bb4ee6a4SAndroid Build Coastguard Worker             OpenOptions::FILE_CREATED
4352*bb4ee6a4SAndroid Build Coastguard Worker         );
4353*bb4ee6a4SAndroid Build Coastguard Worker     }
4354*bb4ee6a4SAndroid Build Coastguard Worker 
4355*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
atomic_open_symbol_link()4356*bb4ee6a4SAndroid Build Coastguard Worker     fn atomic_open_symbol_link() {
4357*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
4358*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
4359*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
4360*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
4361*bb4ee6a4SAndroid Build Coastguard Worker 
4362*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
4363*bb4ee6a4SAndroid Build Coastguard Worker         create_test_data(&temp_dir, &["dir"], &["a.txt"]);
4364*bb4ee6a4SAndroid Build Coastguard Worker 
4365*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Default::default();
4366*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
4367*bb4ee6a4SAndroid Build Coastguard Worker 
4368*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::empty();
4369*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
4370*bb4ee6a4SAndroid Build Coastguard Worker 
4371*bb4ee6a4SAndroid Build Coastguard Worker         // atomic open the link destination file
4372*bb4ee6a4SAndroid Build Coastguard Worker         let res_dst = atomic_open(
4373*bb4ee6a4SAndroid Build Coastguard Worker             &fs,
4374*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("a.txt"),
4375*bb4ee6a4SAndroid Build Coastguard Worker             0o666,
4376*bb4ee6a4SAndroid Build Coastguard Worker             libc::O_RDWR as u32,
4377*bb4ee6a4SAndroid Build Coastguard Worker             0,
4378*bb4ee6a4SAndroid Build Coastguard Worker             None,
4379*bb4ee6a4SAndroid Build Coastguard Worker         );
4380*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res_dst.is_ok());
4381*bb4ee6a4SAndroid Build Coastguard Worker         let (entry_dst, handler_dst, _) = res_dst.unwrap();
4382*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(entry_dst.inode, 0);
4383*bb4ee6a4SAndroid Build Coastguard Worker         assert!(handler_dst.is_some());
4384*bb4ee6a4SAndroid Build Coastguard Worker 
4385*bb4ee6a4SAndroid Build Coastguard Worker         // create depth 1 symbol link
4386*bb4ee6a4SAndroid Build Coastguard Worker         let sym1_res = symlink(
4387*bb4ee6a4SAndroid Build Coastguard Worker             &fs,
4388*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("a.txt"),
4389*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("blink"),
4390*bb4ee6a4SAndroid Build Coastguard Worker             None,
4391*bb4ee6a4SAndroid Build Coastguard Worker         );
4392*bb4ee6a4SAndroid Build Coastguard Worker         assert!(sym1_res.is_ok());
4393*bb4ee6a4SAndroid Build Coastguard Worker         let sym1_entry = sym1_res.unwrap();
4394*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(sym1_entry.inode, 0);
4395*bb4ee6a4SAndroid Build Coastguard Worker 
4396*bb4ee6a4SAndroid Build Coastguard Worker         // atomic_open symbol link, should return dentry with no handler
4397*bb4ee6a4SAndroid Build Coastguard Worker         let res = atomic_open(
4398*bb4ee6a4SAndroid Build Coastguard Worker             &fs,
4399*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("blink"),
4400*bb4ee6a4SAndroid Build Coastguard Worker             0o666,
4401*bb4ee6a4SAndroid Build Coastguard Worker             libc::O_RDWR as u32,
4402*bb4ee6a4SAndroid Build Coastguard Worker             0,
4403*bb4ee6a4SAndroid Build Coastguard Worker             None,
4404*bb4ee6a4SAndroid Build Coastguard Worker         );
4405*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res.is_ok());
4406*bb4ee6a4SAndroid Build Coastguard Worker         let (entry, handler, open_options) = res.unwrap();
4407*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(entry.inode, sym1_entry.inode);
4408*bb4ee6a4SAndroid Build Coastguard Worker         assert!(handler.is_none());
4409*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(open_options, OpenOptions::empty());
4410*bb4ee6a4SAndroid Build Coastguard Worker 
4411*bb4ee6a4SAndroid Build Coastguard Worker         // delete link destination
4412*bb4ee6a4SAndroid Build Coastguard Worker         unlink(&fs, &temp_dir.path().join("a.txt")).expect("Remove");
4413*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
4414*bb4ee6a4SAndroid Build Coastguard Worker             lookup(&fs, &temp_dir.path().join("a.txt"))
4415*bb4ee6a4SAndroid Build Coastguard Worker                 .expect_err("file must not exist")
4416*bb4ee6a4SAndroid Build Coastguard Worker                 .kind(),
4417*bb4ee6a4SAndroid Build Coastguard Worker             io::ErrorKind::NotFound,
4418*bb4ee6a4SAndroid Build Coastguard Worker             "a.txt must be removed"
4419*bb4ee6a4SAndroid Build Coastguard Worker         );
4420*bb4ee6a4SAndroid Build Coastguard Worker 
4421*bb4ee6a4SAndroid Build Coastguard Worker         // after link destination removed, should still return valid dentry
4422*bb4ee6a4SAndroid Build Coastguard Worker         let res = atomic_open(
4423*bb4ee6a4SAndroid Build Coastguard Worker             &fs,
4424*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("blink"),
4425*bb4ee6a4SAndroid Build Coastguard Worker             0o666,
4426*bb4ee6a4SAndroid Build Coastguard Worker             libc::O_RDWR as u32,
4427*bb4ee6a4SAndroid Build Coastguard Worker             0,
4428*bb4ee6a4SAndroid Build Coastguard Worker             None,
4429*bb4ee6a4SAndroid Build Coastguard Worker         );
4430*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res.is_ok());
4431*bb4ee6a4SAndroid Build Coastguard Worker         let (entry, handler, open_options) = res.unwrap();
4432*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(entry.inode, sym1_entry.inode);
4433*bb4ee6a4SAndroid Build Coastguard Worker         assert!(handler.is_none());
4434*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(open_options, OpenOptions::empty());
4435*bb4ee6a4SAndroid Build Coastguard Worker     }
4436*bb4ee6a4SAndroid Build Coastguard Worker 
4437*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
4438*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
set_permission_ioctl_valid_data()4439*bb4ee6a4SAndroid Build Coastguard Worker     fn set_permission_ioctl_valid_data() {
4440*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
4441*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
4442*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
4443*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
4444*bb4ee6a4SAndroid Build Coastguard Worker 
4445*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
4446*bb4ee6a4SAndroid Build Coastguard Worker             max_dynamic_perm: 1,
4447*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4448*bb4ee6a4SAndroid Build Coastguard Worker         };
4449*bb4ee6a4SAndroid Build Coastguard Worker         let p = PassthroughFs::new("tag", cfg).expect("Failed to create PassthroughFs");
4450*bb4ee6a4SAndroid Build Coastguard Worker 
4451*bb4ee6a4SAndroid Build Coastguard Worker         let perm_path_string = String::from("/test");
4452*bb4ee6a4SAndroid Build Coastguard Worker         let fs_permission_data_buffer = FsPermissionDataBuffer {
4453*bb4ee6a4SAndroid Build Coastguard Worker             guest_uid: 1,
4454*bb4ee6a4SAndroid Build Coastguard Worker             guest_gid: 2,
4455*bb4ee6a4SAndroid Build Coastguard Worker             host_uid: 3,
4456*bb4ee6a4SAndroid Build Coastguard Worker             host_gid: 4,
4457*bb4ee6a4SAndroid Build Coastguard Worker             umask: 5,
4458*bb4ee6a4SAndroid Build Coastguard Worker             pad: 0,
4459*bb4ee6a4SAndroid Build Coastguard Worker             perm_path: {
4460*bb4ee6a4SAndroid Build Coastguard Worker                 let mut perm_path: [u8; FS_IOCTL_PATH_MAX_LEN] = [0; FS_IOCTL_PATH_MAX_LEN];
4461*bb4ee6a4SAndroid Build Coastguard Worker                 perm_path[..perm_path_string.len()].copy_from_slice(perm_path_string.as_bytes());
4462*bb4ee6a4SAndroid Build Coastguard Worker                 perm_path
4463*bb4ee6a4SAndroid Build Coastguard Worker             },
4464*bb4ee6a4SAndroid Build Coastguard Worker         };
4465*bb4ee6a4SAndroid Build Coastguard Worker         let r = std::io::Cursor::new(fs_permission_data_buffer.as_bytes());
4466*bb4ee6a4SAndroid Build Coastguard Worker 
4467*bb4ee6a4SAndroid Build Coastguard Worker         let res = fs_ioc_setpermission(
4468*bb4ee6a4SAndroid Build Coastguard Worker             &p,
4469*bb4ee6a4SAndroid Build Coastguard Worker             mem::size_of_val(&fs_permission_data_buffer) as u32,
4470*bb4ee6a4SAndroid Build Coastguard Worker             r.clone(),
4471*bb4ee6a4SAndroid Build Coastguard Worker         )
4472*bb4ee6a4SAndroid Build Coastguard Worker         .expect("valid input should get IoctlReply");
4473*bb4ee6a4SAndroid Build Coastguard Worker         assert!(matches!(res, IoctlReply::Done(Ok(data)) if data.is_empty()));
4474*bb4ee6a4SAndroid Build Coastguard Worker 
4475*bb4ee6a4SAndroid Build Coastguard Worker         let read_guard = p
4476*bb4ee6a4SAndroid Build Coastguard Worker             .permission_paths
4477*bb4ee6a4SAndroid Build Coastguard Worker             .read()
4478*bb4ee6a4SAndroid Build Coastguard Worker             .expect("read permission_paths failed");
4479*bb4ee6a4SAndroid Build Coastguard Worker         let permission_data = read_guard
4480*bb4ee6a4SAndroid Build Coastguard Worker             .first()
4481*bb4ee6a4SAndroid Build Coastguard Worker             .expect("permission path should not be empty");
4482*bb4ee6a4SAndroid Build Coastguard Worker 
4483*bb4ee6a4SAndroid Build Coastguard Worker         // Check expected data item is added to permission_paths.
4484*bb4ee6a4SAndroid Build Coastguard Worker         let expected_data = PermissionData {
4485*bb4ee6a4SAndroid Build Coastguard Worker             guest_uid: 1,
4486*bb4ee6a4SAndroid Build Coastguard Worker             guest_gid: 2,
4487*bb4ee6a4SAndroid Build Coastguard Worker             host_uid: 3,
4488*bb4ee6a4SAndroid Build Coastguard Worker             host_gid: 4,
4489*bb4ee6a4SAndroid Build Coastguard Worker             umask: 5,
4490*bb4ee6a4SAndroid Build Coastguard Worker             perm_path: perm_path_string,
4491*bb4ee6a4SAndroid Build Coastguard Worker         };
4492*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*permission_data, expected_data);
4493*bb4ee6a4SAndroid Build Coastguard Worker 
4494*bb4ee6a4SAndroid Build Coastguard Worker         // Second ioctl should not succeed since max_dynamic_perm is set to 1
4495*bb4ee6a4SAndroid Build Coastguard Worker         let res = fs_ioc_setpermission(
4496*bb4ee6a4SAndroid Build Coastguard Worker             &p,
4497*bb4ee6a4SAndroid Build Coastguard Worker             mem::size_of_val(&fs_permission_data_buffer) as u32,
4498*bb4ee6a4SAndroid Build Coastguard Worker             r.clone(),
4499*bb4ee6a4SAndroid Build Coastguard Worker         )
4500*bb4ee6a4SAndroid Build Coastguard Worker         .expect("valid input should get IoctlReply");
4501*bb4ee6a4SAndroid Build Coastguard Worker         assert!(
4502*bb4ee6a4SAndroid Build Coastguard Worker             matches!(res, IoctlReply::Done(Err(err)) if err.raw_os_error().is_some_and(|errno| {
4503*bb4ee6a4SAndroid Build Coastguard Worker                 errno == libc::EPERM
4504*bb4ee6a4SAndroid Build Coastguard Worker             }))
4505*bb4ee6a4SAndroid Build Coastguard Worker         );
4506*bb4ee6a4SAndroid Build Coastguard Worker     }
4507*bb4ee6a4SAndroid Build Coastguard Worker 
4508*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
4509*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
set_permission_ioctl_invalid_data()4510*bb4ee6a4SAndroid Build Coastguard Worker     fn set_permission_ioctl_invalid_data() {
4511*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
4512*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
4513*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
4514*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
4515*bb4ee6a4SAndroid Build Coastguard Worker 
4516*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
4517*bb4ee6a4SAndroid Build Coastguard Worker             max_dynamic_perm: 1,
4518*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4519*bb4ee6a4SAndroid Build Coastguard Worker         };
4520*bb4ee6a4SAndroid Build Coastguard Worker         let p = PassthroughFs::new("tag", cfg).expect("Failed to create PassthroughFs");
4521*bb4ee6a4SAndroid Build Coastguard Worker 
4522*bb4ee6a4SAndroid Build Coastguard Worker         // The perm_path is not valid since it does not start with /.
4523*bb4ee6a4SAndroid Build Coastguard Worker         let perm_path_string = String::from("test");
4524*bb4ee6a4SAndroid Build Coastguard Worker         let fs_permission_data_buffer = FsPermissionDataBuffer {
4525*bb4ee6a4SAndroid Build Coastguard Worker             guest_uid: 1,
4526*bb4ee6a4SAndroid Build Coastguard Worker             guest_gid: 2,
4527*bb4ee6a4SAndroid Build Coastguard Worker             host_uid: 3,
4528*bb4ee6a4SAndroid Build Coastguard Worker             host_gid: 4,
4529*bb4ee6a4SAndroid Build Coastguard Worker             umask: 5,
4530*bb4ee6a4SAndroid Build Coastguard Worker             pad: 0,
4531*bb4ee6a4SAndroid Build Coastguard Worker             perm_path: {
4532*bb4ee6a4SAndroid Build Coastguard Worker                 let mut perm_path: [u8; FS_IOCTL_PATH_MAX_LEN] = [0; FS_IOCTL_PATH_MAX_LEN];
4533*bb4ee6a4SAndroid Build Coastguard Worker                 perm_path[..perm_path_string.len()].copy_from_slice(perm_path_string.as_bytes());
4534*bb4ee6a4SAndroid Build Coastguard Worker                 perm_path
4535*bb4ee6a4SAndroid Build Coastguard Worker             },
4536*bb4ee6a4SAndroid Build Coastguard Worker         };
4537*bb4ee6a4SAndroid Build Coastguard Worker 
4538*bb4ee6a4SAndroid Build Coastguard Worker         let r = std::io::Cursor::new(fs_permission_data_buffer.as_bytes());
4539*bb4ee6a4SAndroid Build Coastguard Worker         // In this ioctl inode,handle,flags,arg and out_size is irrelavant, set to empty value.
4540*bb4ee6a4SAndroid Build Coastguard Worker         // This call is supposed to get EINVAL ioctlReply, since the perm_path is invalid.
4541*bb4ee6a4SAndroid Build Coastguard Worker         let res = fs_ioc_setpermission(&p, mem::size_of_val(&fs_permission_data_buffer) as u32, r)
4542*bb4ee6a4SAndroid Build Coastguard Worker             .expect("invalid perm_path should get IoctlReply");
4543*bb4ee6a4SAndroid Build Coastguard Worker         assert!(
4544*bb4ee6a4SAndroid Build Coastguard Worker             matches!(res, IoctlReply::Done(Err(err)) if err.raw_os_error().is_some_and(|errno| {
4545*bb4ee6a4SAndroid Build Coastguard Worker                 errno == libc::EINVAL
4546*bb4ee6a4SAndroid Build Coastguard Worker             }))
4547*bb4ee6a4SAndroid Build Coastguard Worker         );
4548*bb4ee6a4SAndroid Build Coastguard Worker 
4549*bb4ee6a4SAndroid Build Coastguard Worker         let fake_data_buffer: [u8; 128] = [0; 128];
4550*bb4ee6a4SAndroid Build Coastguard Worker         let r = std::io::Cursor::new(fake_data_buffer.as_bytes());
4551*bb4ee6a4SAndroid Build Coastguard Worker 
4552*bb4ee6a4SAndroid Build Coastguard Worker         // This call is supposed to get EINVAL ioctlReply, since the in_size is not the size of
4553*bb4ee6a4SAndroid Build Coastguard Worker         // struct FsPermissionDataBuffer.
4554*bb4ee6a4SAndroid Build Coastguard Worker         let res = fs_ioc_setpermission(&p, mem::size_of_val(&fake_data_buffer) as u32, r)
4555*bb4ee6a4SAndroid Build Coastguard Worker             .expect_err("invalid in_size should get Error");
4556*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res
4557*bb4ee6a4SAndroid Build Coastguard Worker             .raw_os_error()
4558*bb4ee6a4SAndroid Build Coastguard Worker             .is_some_and(|errno| { errno == libc::EINVAL }));
4559*bb4ee6a4SAndroid Build Coastguard Worker     }
4560*bb4ee6a4SAndroid Build Coastguard Worker 
4561*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
4562*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
permission_data_path_matching()4563*bb4ee6a4SAndroid Build Coastguard Worker     fn permission_data_path_matching() {
4564*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
4565*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
4566*bb4ee6a4SAndroid Build Coastguard Worker         // Prepare `a.txt` before starting the test.
4567*bb4ee6a4SAndroid Build Coastguard Worker         create_test_data(&temp_dir, &["dir"], &["a.txt", "dir/a.txt"]);
4568*bb4ee6a4SAndroid Build Coastguard Worker 
4569*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
4570*bb4ee6a4SAndroid Build Coastguard Worker             max_dynamic_perm: 1,
4571*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4572*bb4ee6a4SAndroid Build Coastguard Worker         };
4573*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
4574*bb4ee6a4SAndroid Build Coastguard Worker 
4575*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::empty();
4576*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
4577*bb4ee6a4SAndroid Build Coastguard Worker 
4578*bb4ee6a4SAndroid Build Coastguard Worker         const BY_PATH_UID: u32 = 655360;
4579*bb4ee6a4SAndroid Build Coastguard Worker         const BY_PATH_GID: u32 = 655361;
4580*bb4ee6a4SAndroid Build Coastguard Worker         const BY_PATH_UMASK: u32 = 0o007;
4581*bb4ee6a4SAndroid Build Coastguard Worker 
4582*bb4ee6a4SAndroid Build Coastguard Worker         let dir_path = temp_dir.path().join("dir");
4583*bb4ee6a4SAndroid Build Coastguard Worker         let permission_data = PermissionData {
4584*bb4ee6a4SAndroid Build Coastguard Worker             guest_uid: BY_PATH_UID,
4585*bb4ee6a4SAndroid Build Coastguard Worker             guest_gid: BY_PATH_GID,
4586*bb4ee6a4SAndroid Build Coastguard Worker             host_uid: ctx.uid,
4587*bb4ee6a4SAndroid Build Coastguard Worker             host_gid: ctx.gid,
4588*bb4ee6a4SAndroid Build Coastguard Worker             umask: BY_PATH_UMASK,
4589*bb4ee6a4SAndroid Build Coastguard Worker             perm_path: dir_path.to_string_lossy().into_owned(),
4590*bb4ee6a4SAndroid Build Coastguard Worker         };
4591*bb4ee6a4SAndroid Build Coastguard Worker         fs.permission_paths
4592*bb4ee6a4SAndroid Build Coastguard Worker             .write()
4593*bb4ee6a4SAndroid Build Coastguard Worker             .expect("permission_path lock must be acquired")
4594*bb4ee6a4SAndroid Build Coastguard Worker             .push(permission_data);
4595*bb4ee6a4SAndroid Build Coastguard Worker 
4596*bb4ee6a4SAndroid Build Coastguard Worker         // a_path is the path with out set permission by path
4597*bb4ee6a4SAndroid Build Coastguard Worker         let a_path = temp_dir.path().join("a.txt");
4598*bb4ee6a4SAndroid Build Coastguard Worker         let in_dir_a_path = dir_path.join("a.txt");
4599*bb4ee6a4SAndroid Build Coastguard Worker 
4600*bb4ee6a4SAndroid Build Coastguard Worker         // a.txt should not be set with guest_uid/guest_uid/umask by path
4601*bb4ee6a4SAndroid Build Coastguard Worker         let a_entry = lookup_ent(&fs, &a_path).expect("a.txt must exist");
4602*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(a_entry.attr.st_uid, BY_PATH_UID);
4603*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(a_entry.attr.st_gid, BY_PATH_GID);
4604*bb4ee6a4SAndroid Build Coastguard Worker 
4605*bb4ee6a4SAndroid Build Coastguard Worker         // a.txt in dir should be set guest_uid/guest_uid/umask by path
4606*bb4ee6a4SAndroid Build Coastguard Worker         let in_dir_a_entry = lookup_ent(&fs, &in_dir_a_path).expect("dir/a.txt must exist");
4607*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(in_dir_a_entry.attr.st_uid, BY_PATH_UID);
4608*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(in_dir_a_entry.attr.st_gid, BY_PATH_GID);
4609*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(in_dir_a_entry.attr.st_mode & 0o777, !BY_PATH_UMASK & 0o777);
4610*bb4ee6a4SAndroid Build Coastguard Worker 
4611*bb4ee6a4SAndroid Build Coastguard Worker         // Create dir/b.txt.
4612*bb4ee6a4SAndroid Build Coastguard Worker         let in_dir_b_path = dir_path.join("b.txt");
4613*bb4ee6a4SAndroid Build Coastguard Worker         create(&fs, &in_dir_b_path).expect("create b.txt");
4614*bb4ee6a4SAndroid Build Coastguard Worker 
4615*bb4ee6a4SAndroid Build Coastguard Worker         // newly created b.txt in dir should be set guest_uid/guest_uid/umask by path
4616*bb4ee6a4SAndroid Build Coastguard Worker         let in_dir_b_entry = lookup_ent(&fs, &in_dir_a_path).expect("dir/b.txt must exist");
4617*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(in_dir_b_entry.attr.st_uid, BY_PATH_UID);
4618*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(in_dir_b_entry.attr.st_gid, BY_PATH_GID);
4619*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(in_dir_b_entry.attr.st_mode & 0o777, !BY_PATH_UMASK & 0o777);
4620*bb4ee6a4SAndroid Build Coastguard Worker     }
4621*bb4ee6a4SAndroid Build Coastguard Worker 
4622*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
4623*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
set_path_xattr_ioctl_valid_data()4624*bb4ee6a4SAndroid Build Coastguard Worker     fn set_path_xattr_ioctl_valid_data() {
4625*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
4626*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
4627*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
4628*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
4629*bb4ee6a4SAndroid Build Coastguard Worker 
4630*bb4ee6a4SAndroid Build Coastguard Worker         let cfg: Config = Config {
4631*bb4ee6a4SAndroid Build Coastguard Worker             max_dynamic_xattr: 1,
4632*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4633*bb4ee6a4SAndroid Build Coastguard Worker         };
4634*bb4ee6a4SAndroid Build Coastguard Worker         let p = PassthroughFs::new("tag", cfg).expect("Failed to create PassthroughFs");
4635*bb4ee6a4SAndroid Build Coastguard Worker 
4636*bb4ee6a4SAndroid Build Coastguard Worker         let path_string = String::from("/test");
4637*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_name_string = String::from("test_name");
4638*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_value_string = String::from("test_value");
4639*bb4ee6a4SAndroid Build Coastguard Worker         let fs_path_xattr_data_buffer = FsPathXattrDataBuffer {
4640*bb4ee6a4SAndroid Build Coastguard Worker             path: {
4641*bb4ee6a4SAndroid Build Coastguard Worker                 let mut path: [u8; FS_IOCTL_PATH_MAX_LEN] = [0; FS_IOCTL_PATH_MAX_LEN];
4642*bb4ee6a4SAndroid Build Coastguard Worker                 path[..path_string.len()].copy_from_slice(path_string.as_bytes());
4643*bb4ee6a4SAndroid Build Coastguard Worker                 path
4644*bb4ee6a4SAndroid Build Coastguard Worker             },
4645*bb4ee6a4SAndroid Build Coastguard Worker             xattr_name: {
4646*bb4ee6a4SAndroid Build Coastguard Worker                 let mut xattr_name: [u8; FS_IOCTL_XATTR_NAME_MAX_LEN] =
4647*bb4ee6a4SAndroid Build Coastguard Worker                     [0; FS_IOCTL_XATTR_NAME_MAX_LEN];
4648*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_name[..xattr_name_string.len()].copy_from_slice(xattr_name_string.as_bytes());
4649*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_name
4650*bb4ee6a4SAndroid Build Coastguard Worker             },
4651*bb4ee6a4SAndroid Build Coastguard Worker             xattr_value: {
4652*bb4ee6a4SAndroid Build Coastguard Worker                 let mut xattr_value: [u8; FS_IOCTL_XATTR_VALUE_MAX_LEN] =
4653*bb4ee6a4SAndroid Build Coastguard Worker                     [0; FS_IOCTL_XATTR_VALUE_MAX_LEN];
4654*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_value[..xattr_value_string.len()]
4655*bb4ee6a4SAndroid Build Coastguard Worker                     .copy_from_slice(xattr_value_string.as_bytes());
4656*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_value
4657*bb4ee6a4SAndroid Build Coastguard Worker             },
4658*bb4ee6a4SAndroid Build Coastguard Worker         };
4659*bb4ee6a4SAndroid Build Coastguard Worker         let r = std::io::Cursor::new(fs_path_xattr_data_buffer.as_bytes());
4660*bb4ee6a4SAndroid Build Coastguard Worker 
4661*bb4ee6a4SAndroid Build Coastguard Worker         let res = fs_ioc_setpathxattr(
4662*bb4ee6a4SAndroid Build Coastguard Worker             &p,
4663*bb4ee6a4SAndroid Build Coastguard Worker             mem::size_of_val(&fs_path_xattr_data_buffer) as u32,
4664*bb4ee6a4SAndroid Build Coastguard Worker             r.clone(),
4665*bb4ee6a4SAndroid Build Coastguard Worker         )
4666*bb4ee6a4SAndroid Build Coastguard Worker         .expect("valid input should get IoctlReply");
4667*bb4ee6a4SAndroid Build Coastguard Worker         assert!(matches!(res, IoctlReply::Done(Ok(data)) if data.is_empty()));
4668*bb4ee6a4SAndroid Build Coastguard Worker 
4669*bb4ee6a4SAndroid Build Coastguard Worker         let read_guard = p.xattr_paths.read().expect("read xattr_paths failed");
4670*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_data = read_guard.first().expect("xattr_paths should not be empty");
4671*bb4ee6a4SAndroid Build Coastguard Worker 
4672*bb4ee6a4SAndroid Build Coastguard Worker         // Check expected data item is added to permission_paths.
4673*bb4ee6a4SAndroid Build Coastguard Worker         let expected_data = XattrData {
4674*bb4ee6a4SAndroid Build Coastguard Worker             xattr_path: path_string,
4675*bb4ee6a4SAndroid Build Coastguard Worker             xattr_name: xattr_name_string,
4676*bb4ee6a4SAndroid Build Coastguard Worker             xattr_value: xattr_value_string,
4677*bb4ee6a4SAndroid Build Coastguard Worker         };
4678*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*xattr_data, expected_data);
4679*bb4ee6a4SAndroid Build Coastguard Worker 
4680*bb4ee6a4SAndroid Build Coastguard Worker         // Second ioctl should not succeed since max_dynamic_perm is set to 1
4681*bb4ee6a4SAndroid Build Coastguard Worker         let res = fs_ioc_setpathxattr(
4682*bb4ee6a4SAndroid Build Coastguard Worker             &p,
4683*bb4ee6a4SAndroid Build Coastguard Worker             mem::size_of_val(&fs_path_xattr_data_buffer) as u32,
4684*bb4ee6a4SAndroid Build Coastguard Worker             r.clone(),
4685*bb4ee6a4SAndroid Build Coastguard Worker         )
4686*bb4ee6a4SAndroid Build Coastguard Worker         .expect("valid input should get IoctlReply");
4687*bb4ee6a4SAndroid Build Coastguard Worker         assert!(
4688*bb4ee6a4SAndroid Build Coastguard Worker             matches!(res, IoctlReply::Done(Err(err)) if err.raw_os_error().is_some_and(|errno| {
4689*bb4ee6a4SAndroid Build Coastguard Worker                 errno == libc::EPERM
4690*bb4ee6a4SAndroid Build Coastguard Worker             }))
4691*bb4ee6a4SAndroid Build Coastguard Worker         );
4692*bb4ee6a4SAndroid Build Coastguard Worker     }
4693*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
4694*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
set_path_xattr_ioctl_invalid_data()4695*bb4ee6a4SAndroid Build Coastguard Worker     fn set_path_xattr_ioctl_invalid_data() {
4696*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
4697*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
4698*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
4699*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
4700*bb4ee6a4SAndroid Build Coastguard Worker 
4701*bb4ee6a4SAndroid Build Coastguard Worker         let cfg: Config = Config {
4702*bb4ee6a4SAndroid Build Coastguard Worker             max_dynamic_xattr: 1,
4703*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4704*bb4ee6a4SAndroid Build Coastguard Worker         };
4705*bb4ee6a4SAndroid Build Coastguard Worker         let p = PassthroughFs::new("tag", cfg).expect("Failed to create PassthroughFs");
4706*bb4ee6a4SAndroid Build Coastguard Worker 
4707*bb4ee6a4SAndroid Build Coastguard Worker         let path_string = String::from("test");
4708*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_name_string = String::from("test_name");
4709*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_value_string = String::from("test_value");
4710*bb4ee6a4SAndroid Build Coastguard Worker         let fs_path_xattr_data_buffer = FsPathXattrDataBuffer {
4711*bb4ee6a4SAndroid Build Coastguard Worker             path: {
4712*bb4ee6a4SAndroid Build Coastguard Worker                 let mut path: [u8; FS_IOCTL_PATH_MAX_LEN] = [0; FS_IOCTL_PATH_MAX_LEN];
4713*bb4ee6a4SAndroid Build Coastguard Worker                 path[..path_string.len()].copy_from_slice(path_string.as_bytes());
4714*bb4ee6a4SAndroid Build Coastguard Worker                 path
4715*bb4ee6a4SAndroid Build Coastguard Worker             },
4716*bb4ee6a4SAndroid Build Coastguard Worker             xattr_name: {
4717*bb4ee6a4SAndroid Build Coastguard Worker                 let mut xattr_name: [u8; FS_IOCTL_XATTR_NAME_MAX_LEN] =
4718*bb4ee6a4SAndroid Build Coastguard Worker                     [0; FS_IOCTL_XATTR_NAME_MAX_LEN];
4719*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_name[..xattr_name_string.len()].copy_from_slice(xattr_name_string.as_bytes());
4720*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_name
4721*bb4ee6a4SAndroid Build Coastguard Worker             },
4722*bb4ee6a4SAndroid Build Coastguard Worker             xattr_value: {
4723*bb4ee6a4SAndroid Build Coastguard Worker                 let mut xattr_value: [u8; FS_IOCTL_XATTR_VALUE_MAX_LEN] =
4724*bb4ee6a4SAndroid Build Coastguard Worker                     [0; FS_IOCTL_XATTR_VALUE_MAX_LEN];
4725*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_value[..xattr_value_string.len()]
4726*bb4ee6a4SAndroid Build Coastguard Worker                     .copy_from_slice(xattr_value_string.as_bytes());
4727*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_value
4728*bb4ee6a4SAndroid Build Coastguard Worker             },
4729*bb4ee6a4SAndroid Build Coastguard Worker         };
4730*bb4ee6a4SAndroid Build Coastguard Worker         let r = std::io::Cursor::new(fs_path_xattr_data_buffer.as_bytes());
4731*bb4ee6a4SAndroid Build Coastguard Worker 
4732*bb4ee6a4SAndroid Build Coastguard Worker         // This call is supposed to get EINVAL ioctlReply, since the perm_path is invalid.
4733*bb4ee6a4SAndroid Build Coastguard Worker         let res = fs_ioc_setpathxattr(
4734*bb4ee6a4SAndroid Build Coastguard Worker             &p,
4735*bb4ee6a4SAndroid Build Coastguard Worker             mem::size_of_val(&fs_path_xattr_data_buffer) as u32,
4736*bb4ee6a4SAndroid Build Coastguard Worker             r.clone(),
4737*bb4ee6a4SAndroid Build Coastguard Worker         )
4738*bb4ee6a4SAndroid Build Coastguard Worker         .expect("valid input should get IoctlReply");
4739*bb4ee6a4SAndroid Build Coastguard Worker         assert!(
4740*bb4ee6a4SAndroid Build Coastguard Worker             matches!(res, IoctlReply::Done(Err(err)) if err.raw_os_error().is_some_and(|errno| {
4741*bb4ee6a4SAndroid Build Coastguard Worker                 errno == libc::EINVAL
4742*bb4ee6a4SAndroid Build Coastguard Worker             }))
4743*bb4ee6a4SAndroid Build Coastguard Worker         );
4744*bb4ee6a4SAndroid Build Coastguard Worker 
4745*bb4ee6a4SAndroid Build Coastguard Worker         let fake_data_buffer: [u8; 128] = [0; 128];
4746*bb4ee6a4SAndroid Build Coastguard Worker         let r = std::io::Cursor::new(fake_data_buffer.as_bytes());
4747*bb4ee6a4SAndroid Build Coastguard Worker         // This call is supposed to get EINVAL ioctlReply, since the in_size is not the size of
4748*bb4ee6a4SAndroid Build Coastguard Worker         // struct FsPathXattrDataBuffer.
4749*bb4ee6a4SAndroid Build Coastguard Worker         let res = fs_ioc_setpathxattr(&p, mem::size_of_val(&fake_data_buffer) as u32, r.clone())
4750*bb4ee6a4SAndroid Build Coastguard Worker             .expect_err("valid input should get IoctlReply");
4751*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res
4752*bb4ee6a4SAndroid Build Coastguard Worker             .raw_os_error()
4753*bb4ee6a4SAndroid Build Coastguard Worker             .is_some_and(|errno| { errno == libc::EINVAL }));
4754*bb4ee6a4SAndroid Build Coastguard Worker     }
4755*bb4ee6a4SAndroid Build Coastguard Worker 
4756*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
4757*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "arc_quota")]
xattr_data_path_matching()4758*bb4ee6a4SAndroid Build Coastguard Worker     fn xattr_data_path_matching() {
4759*bb4ee6a4SAndroid Build Coastguard Worker         let ctx = get_context();
4760*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
4761*bb4ee6a4SAndroid Build Coastguard Worker         // Prepare `a.txt` before starting the test.
4762*bb4ee6a4SAndroid Build Coastguard Worker         create_test_data(&temp_dir, &["dir"], &["a.txt", "dir/a.txt"]);
4763*bb4ee6a4SAndroid Build Coastguard Worker 
4764*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
4765*bb4ee6a4SAndroid Build Coastguard Worker             max_dynamic_xattr: 1,
4766*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4767*bb4ee6a4SAndroid Build Coastguard Worker         };
4768*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
4769*bb4ee6a4SAndroid Build Coastguard Worker 
4770*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::empty();
4771*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
4772*bb4ee6a4SAndroid Build Coastguard Worker 
4773*bb4ee6a4SAndroid Build Coastguard Worker         let dir_path = temp_dir.path().join("dir");
4774*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_name_string = String::from("test_name");
4775*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_name_cstring = CString::new(xattr_name_string.clone()).expect("create c string");
4776*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_value_string = String::from("test_value");
4777*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_value_bytes = xattr_value_string.clone().into_bytes();
4778*bb4ee6a4SAndroid Build Coastguard Worker 
4779*bb4ee6a4SAndroid Build Coastguard Worker         let xattr_data = XattrData {
4780*bb4ee6a4SAndroid Build Coastguard Worker             xattr_name: xattr_name_string,
4781*bb4ee6a4SAndroid Build Coastguard Worker             xattr_value: xattr_value_string,
4782*bb4ee6a4SAndroid Build Coastguard Worker             xattr_path: dir_path.to_string_lossy().into_owned(),
4783*bb4ee6a4SAndroid Build Coastguard Worker         };
4784*bb4ee6a4SAndroid Build Coastguard Worker         fs.xattr_paths
4785*bb4ee6a4SAndroid Build Coastguard Worker             .write()
4786*bb4ee6a4SAndroid Build Coastguard Worker             .expect("xattr_paths lock must be acquired")
4787*bb4ee6a4SAndroid Build Coastguard Worker             .push(xattr_data);
4788*bb4ee6a4SAndroid Build Coastguard Worker 
4789*bb4ee6a4SAndroid Build Coastguard Worker         // a_path is the path with out set xattr by path
4790*bb4ee6a4SAndroid Build Coastguard Worker         let a_path: std::path::PathBuf = temp_dir.path().join("a.txt");
4791*bb4ee6a4SAndroid Build Coastguard Worker         let in_dir_a_path = dir_path.join("a.txt");
4792*bb4ee6a4SAndroid Build Coastguard Worker 
4793*bb4ee6a4SAndroid Build Coastguard Worker         let a_node = lookup(&fs, a_path.as_path()).expect("lookup a node");
4794*bb4ee6a4SAndroid Build Coastguard Worker         // a.txt should not be set with xattr by path
4795*bb4ee6a4SAndroid Build Coastguard Worker         assert!(fs
4796*bb4ee6a4SAndroid Build Coastguard Worker             .getxattr(
4797*bb4ee6a4SAndroid Build Coastguard Worker                 ctx,
4798*bb4ee6a4SAndroid Build Coastguard Worker                 a_node,
4799*bb4ee6a4SAndroid Build Coastguard Worker                 &xattr_name_cstring,
4800*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_value_bytes.len() as u32
4801*bb4ee6a4SAndroid Build Coastguard Worker             )
4802*bb4ee6a4SAndroid Build Coastguard Worker             .is_err());
4803*bb4ee6a4SAndroid Build Coastguard Worker 
4804*bb4ee6a4SAndroid Build Coastguard Worker         let in_dir_a_node = lookup(&fs, in_dir_a_path.as_path()).expect("lookup in dir a node");
4805*bb4ee6a4SAndroid Build Coastguard Worker         // a.txt in dir should be set xattr by path
4806*bb4ee6a4SAndroid Build Coastguard Worker         let in_dir_a_reply = fs
4807*bb4ee6a4SAndroid Build Coastguard Worker             .getxattr(
4808*bb4ee6a4SAndroid Build Coastguard Worker                 ctx,
4809*bb4ee6a4SAndroid Build Coastguard Worker                 in_dir_a_node,
4810*bb4ee6a4SAndroid Build Coastguard Worker                 &xattr_name_cstring,
4811*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_value_bytes.len() as u32,
4812*bb4ee6a4SAndroid Build Coastguard Worker             )
4813*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Getxattr should success");
4814*bb4ee6a4SAndroid Build Coastguard Worker         assert!(matches!(in_dir_a_reply, GetxattrReply::Value(v) if v == xattr_value_bytes));
4815*bb4ee6a4SAndroid Build Coastguard Worker         // Create dir/b.txt.
4816*bb4ee6a4SAndroid Build Coastguard Worker         let in_dir_b_path = dir_path.join("b.txt");
4817*bb4ee6a4SAndroid Build Coastguard Worker         create(&fs, &in_dir_b_path).expect("create b.txt");
4818*bb4ee6a4SAndroid Build Coastguard Worker 
4819*bb4ee6a4SAndroid Build Coastguard Worker         // newly created b.txt in dir should be set xattr by path
4820*bb4ee6a4SAndroid Build Coastguard Worker         let in_dir_b_node = lookup(&fs, in_dir_a_path.as_path()).expect("lookup in dir b node");
4821*bb4ee6a4SAndroid Build Coastguard Worker         let in_dir_b_reply = fs
4822*bb4ee6a4SAndroid Build Coastguard Worker             .getxattr(
4823*bb4ee6a4SAndroid Build Coastguard Worker                 ctx,
4824*bb4ee6a4SAndroid Build Coastguard Worker                 in_dir_b_node,
4825*bb4ee6a4SAndroid Build Coastguard Worker                 &xattr_name_cstring,
4826*bb4ee6a4SAndroid Build Coastguard Worker                 xattr_value_bytes.len() as u32,
4827*bb4ee6a4SAndroid Build Coastguard Worker             )
4828*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Getxattr should success");
4829*bb4ee6a4SAndroid Build Coastguard Worker         assert!(matches!(in_dir_b_reply, GetxattrReply::Value(v) if v == xattr_value_bytes));
4830*bb4ee6a4SAndroid Build Coastguard Worker     }
4831*bb4ee6a4SAndroid Build Coastguard Worker 
4832*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates and open a new file by atomic_open with O_APPEND flag.
4833*bb4ee6a4SAndroid Build Coastguard Worker     /// We check O_APPEND is properly handled, depending on writeback cache is enabled or not.
atomic_open_create_o_append(writeback: bool)4834*bb4ee6a4SAndroid Build Coastguard Worker     fn atomic_open_create_o_append(writeback: bool) {
4835*bb4ee6a4SAndroid Build Coastguard Worker         // Since PassthroughFs may executes process-wide operations such as `fchdir`, acquire
4836*bb4ee6a4SAndroid Build Coastguard Worker         // `NamedLock` before starting each unit test creating a `PassthroughFs` instance.
4837*bb4ee6a4SAndroid Build Coastguard Worker         let lock = NamedLock::create(UNITTEST_LOCK_NAME).expect("create named lock");
4838*bb4ee6a4SAndroid Build Coastguard Worker         let _guard = lock.lock().expect("acquire named lock");
4839*bb4ee6a4SAndroid Build Coastguard Worker 
4840*bb4ee6a4SAndroid Build Coastguard Worker         let temp_dir = TempDir::new().unwrap();
4841*bb4ee6a4SAndroid Build Coastguard Worker 
4842*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = Config {
4843*bb4ee6a4SAndroid Build Coastguard Worker             cache_policy: CachePolicy::Always,
4844*bb4ee6a4SAndroid Build Coastguard Worker             writeback,
4845*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
4846*bb4ee6a4SAndroid Build Coastguard Worker         };
4847*bb4ee6a4SAndroid Build Coastguard Worker         let fs = PassthroughFs::new("tag", cfg).unwrap();
4848*bb4ee6a4SAndroid Build Coastguard Worker 
4849*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::ZERO_MESSAGE_OPEN | FsOptions::WRITEBACK_CACHE;
4850*bb4ee6a4SAndroid Build Coastguard Worker         fs.init(capable).unwrap();
4851*bb4ee6a4SAndroid Build Coastguard Worker 
4852*bb4ee6a4SAndroid Build Coastguard Worker         let (entry, _, _) = atomic_open(
4853*bb4ee6a4SAndroid Build Coastguard Worker             &fs,
4854*bb4ee6a4SAndroid Build Coastguard Worker             &temp_dir.path().join("a.txt"),
4855*bb4ee6a4SAndroid Build Coastguard Worker             0o666,
4856*bb4ee6a4SAndroid Build Coastguard Worker             (libc::O_RDWR | libc::O_CREAT | libc::O_APPEND) as u32,
4857*bb4ee6a4SAndroid Build Coastguard Worker             0,
4858*bb4ee6a4SAndroid Build Coastguard Worker             None,
4859*bb4ee6a4SAndroid Build Coastguard Worker         )
4860*bb4ee6a4SAndroid Build Coastguard Worker         .expect("atomic_open");
4861*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(entry.inode, 0);
4862*bb4ee6a4SAndroid Build Coastguard Worker 
4863*bb4ee6a4SAndroid Build Coastguard Worker         let inodes = fs.inodes.lock();
4864*bb4ee6a4SAndroid Build Coastguard Worker         let data = inodes.get(&entry.inode).unwrap();
4865*bb4ee6a4SAndroid Build Coastguard Worker         let flags = data.file.lock().1;
4866*bb4ee6a4SAndroid Build Coastguard Worker         if writeback {
4867*bb4ee6a4SAndroid Build Coastguard Worker             // When writeback is enabled, O_APPEND must be handled by the guest kernel.
4868*bb4ee6a4SAndroid Build Coastguard Worker             // So, it must be cleared.
4869*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(flags & libc::O_APPEND, 0);
4870*bb4ee6a4SAndroid Build Coastguard Worker         } else {
4871*bb4ee6a4SAndroid Build Coastguard Worker             // Without writeback cache, O_APPEND must not be cleared.
4872*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(flags & libc::O_APPEND, libc::O_APPEND);
4873*bb4ee6a4SAndroid Build Coastguard Worker         }
4874*bb4ee6a4SAndroid Build Coastguard Worker     }
4875*bb4ee6a4SAndroid Build Coastguard Worker 
4876*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
test_atomic_open_create_o_append_no_writeback()4877*bb4ee6a4SAndroid Build Coastguard Worker     fn test_atomic_open_create_o_append_no_writeback() {
4878*bb4ee6a4SAndroid Build Coastguard Worker         atomic_open_create_o_append(false);
4879*bb4ee6a4SAndroid Build Coastguard Worker     }
4880*bb4ee6a4SAndroid Build Coastguard Worker 
4881*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
test_atomic_open_create_o_append_writeback()4882*bb4ee6a4SAndroid Build Coastguard Worker     fn test_atomic_open_create_o_append_writeback() {
4883*bb4ee6a4SAndroid Build Coastguard Worker         atomic_open_create_o_append(true);
4884*bb4ee6a4SAndroid Build Coastguard Worker     }
4885*bb4ee6a4SAndroid Build Coastguard Worker }
4886