Skip to main content

starnix_core/vfs/
fs_node.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::device::DeviceMode;
6use crate::mm::PAGE_SIZE;
7use crate::security::{self, Auditable, PermissionFlags};
8use crate::signals::{SignalInfo, send_standard_signal};
9use crate::task::{CurrentTask, WaitQueue, Waiter, register_delayed_release};
10use crate::time::utc;
11use crate::vfs::fsverity::FsVerityState;
12use crate::vfs::pipe::{Pipe, PipeHandle};
13use crate::vfs::rw_queue::{RwQueue, RwQueueReadGuard, RwQueueWriteGuard};
14use crate::vfs::socket::SocketHandle;
15use crate::vfs::{
16    CheckAccessReason, DefaultDirEntryOps, DirEntry, DirEntryOps, FileObject, FileObjectState,
17    FileOps, FileSystem, FileSystemHandle, FileWriteGuardMode, FileWriteGuardRef,
18    FileWriteGuardState, FsLockDepType, FsStr, FsString, MAX_LFS_FILESIZE, MountInfo,
19    NamespaceNode, OPathOps, OpenAccessCheck, RecordLockCommand, RecordLockOwner, RecordLocks,
20    WeakFileHandle, checked_add_offset_and_length, inotify_hook,
21};
22use bitflags::bitflags;
23use fuchsia_runtime::UtcInstant;
24use linux_uapi::{XATTR_SECURITY_PREFIX, XATTR_SYSTEM_PREFIX, XATTR_TRUSTED_PREFIX};
25use once_cell::race::OnceBool;
26use smallvec::SmallVec;
27use starnix_crypt::EncryptionKeyId;
28use starnix_lifecycle::{ObjectReleaser, ReleaserAction};
29use starnix_logging::{log_error, track_stub};
30use starnix_sync::{
31    DynamicLockDepRwLock, FsNodeAppend, FsNodeFlockInfoLock, FsNodeFsVerityLock, FsNodeInfoLevel,
32    FsNodeInfoRecursiveLevel, FsNodeWriteGuardStateLock, FuseFsNodeInfoLevel, LockDepMutex,
33    LockDepReadGuard, allow_subclass,
34};
35use starnix_types::ownership::{Releasable, ReleaseGuard};
36use starnix_types::time::{NANOS_PER_SECOND, timespec_from_time};
37use starnix_uapi::as_any::AsAny;
38use starnix_uapi::auth::{
39    CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_FSETID, CAP_MKNOD,
40    CAP_SYS_ADMIN, CAP_SYS_RESOURCE, Credentials, FsCred,
41};
42use starnix_uapi::device_id::DeviceId;
43use starnix_uapi::errors::{EACCES, ENOTSUP, EPERM, Errno};
44use starnix_uapi::file_mode::{Access, FileMode};
45use starnix_uapi::inotify_mask::InotifyMask;
46use starnix_uapi::mount_flags::MountFlags;
47use starnix_uapi::open_flags::OpenFlags;
48use starnix_uapi::resource_limits::Resource;
49use starnix_uapi::seal_flags::SealFlags;
50use starnix_uapi::signals::SIGXFSZ;
51use starnix_uapi::{
52    FALLOC_FL_COLLAPSE_RANGE, FALLOC_FL_INSERT_RANGE, FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE,
53    FALLOC_FL_UNSHARE_RANGE, FALLOC_FL_ZERO_RANGE, LOCK_EX, LOCK_NB, LOCK_SH, LOCK_UN,
54    STATX__RESERVED, STATX_ATIME, STATX_ATTR_VERITY, STATX_BASIC_STATS, STATX_BLOCKS, STATX_CTIME,
55    STATX_GID, STATX_INO, STATX_MTIME, STATX_NLINK, STATX_SIZE, STATX_UID, XATTR_USER_PREFIX,
56    errno, error, fsverity_descriptor, gid_t, ino_t, statx, statx_timestamp, timespec, uapi, uid_t,
57};
58use std::sync::atomic::Ordering;
59use std::sync::{Arc, OnceLock, Weak};
60use syncio::zxio_node_attr_has_t;
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum FsNodeLinkBehavior {
64    Allowed,
65    Disallowed,
66}
67
68impl Default for FsNodeLinkBehavior {
69    fn default() -> Self {
70        FsNodeLinkBehavior::Allowed
71    }
72}
73
74pub type AppendLockGuard<'a> = RwQueueReadGuard<'a, FsNodeAppend>;
75pub type AppendLockWriteGuard<'a> = RwQueueWriteGuard<'a, FsNodeAppend>;
76
77bitflags! {
78    pub struct FsNodeFlags: u8 {
79        const IS_PRIVATE = 1 << 0;
80    }
81}
82
83pub struct FsNode {
84    /// The inode number for this FsNode.
85    pub ino: ino_t,
86
87    /// Flags for this node.
88    pub flags: FsNodeFlags,
89
90    /// The FsNodeOps for this FsNode.
91    ///
92    /// The FsNodeOps are implemented by the individual file systems to provide
93    /// specific behaviors for this FsNode.
94    ops: Box<dyn FsNodeOps>,
95
96    /// The FileSystem that owns this FsNode's tree.
97    fs: Weak<FileSystem>,
98
99    /// A RwLock to synchronize append operations for this node.
100    ///
101    /// FileObjects writing with O_APPEND should grab a write() lock on this
102    /// field to ensure they operate sequentially. FileObjects writing without
103    /// O_APPEND should grab read() lock so that they can operate in parallel.
104    pub append_lock: RwQueue<FsNodeAppend>,
105
106    /// Mutable information about this node.
107    ///
108    /// This data is used to populate the uapi::stat structure.
109    info: DynamicLockDepRwLock<FsNodeInfo>,
110
111    /// Data associated with an FsNode that is rarely needed.
112    rare_data: OnceLock<Box<FsNodeRareData>>,
113
114    /// Tracks lock state for this file.
115    pub write_guard_state: LockDepMutex<FileWriteGuardState, FsNodeWriteGuardStateLock>,
116
117    /// Cached FsVerity state associated with this node.
118    pub fsverity: LockDepMutex<FsVerityState, FsNodeFsVerityLock>,
119
120    /// The security state associated with this node. Must always be acquired last
121    /// relative to other `FsNode` locks.
122    pub security_state: security::FsNodeState,
123}
124
125#[derive(Default)]
126struct FsNodeRareData {
127    /// The pipe located at this node, if any.
128    ///
129    /// Used if, and only if, the node has a mode of FileMode::IFIFO.
130    fifo: OnceLock<PipeHandle>,
131
132    /// The UNIX domain socket bound to this node, if any.
133    bound_socket: OnceLock<SocketHandle>,
134
135    /// Information about the locking information on this node.
136    ///
137    /// No other lock on this object may be taken while this lock is held.
138    flock_info: LockDepMutex<FlockInfo, FsNodeFlockInfoLock>,
139
140    /// Records locks associated with this node.
141    record_locks: RecordLocks,
142
143    /// Whether this node can be linked into a directory.
144    ///
145    /// Only set for nodes created with `O_TMPFILE`.
146    link_behavior: OnceLock<FsNodeLinkBehavior>,
147
148    /// Inotify watchers on this node. See inotify(7).
149    watchers: inotify_hook::InotifyWatchers,
150}
151
152impl FsNodeRareData {
153    fn ensure_fifo(&self, current_task: &CurrentTask) -> &PipeHandle {
154        self.fifo.get_or_init(|| {
155            let default_pipe_capacity = (*PAGE_SIZE * 16) as usize;
156            let kernel = current_task.kernel();
157            let max_size = kernel.system_limits.pipe_max_size.load(Ordering::Relaxed);
158            let capacity = if default_pipe_capacity <= max_size
159                || security::is_task_capable_noaudit(current_task, CAP_SYS_RESOURCE)
160            {
161                default_pipe_capacity
162            } else {
163                max_size
164            };
165            Pipe::new(capacity)
166        })
167    }
168}
169
170pub enum FsNodeReleaserAction {}
171impl ReleaserAction<FsNode> for FsNodeReleaserAction {
172    fn release(fs_node: ReleaseGuard<FsNode>) {
173        register_delayed_release(fs_node);
174    }
175}
176pub type FsNodeReleaser = ObjectReleaser<FsNode, FsNodeReleaserAction>;
177pub type FsNodeHandle = Arc<FsNodeReleaser>;
178pub type WeakFsNodeHandle = Weak<FsNodeReleaser>;
179
180bitflags! {
181    /// Flags configuring an fscrypt encryption policy (`fscrypt_policy_v2.flags`).
182    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
183    pub struct FscryptPolicyFlags: u8 {
184        const PAD_8 = uapi::FSCRYPT_POLICY_FLAGS_PAD_8 as u8;
185        const PAD_16 = uapi::FSCRYPT_POLICY_FLAGS_PAD_16 as u8;
186        const DIRECT_KEY = uapi::FSCRYPT_POLICY_FLAG_DIRECT_KEY as u8;
187        const IV_INO_LBLK_64 = uapi::FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 as u8;
188        const IV_INO_LBLK_32 = uapi::FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32 as u8;
189    }
190}
191
192#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
193pub struct FscryptNodePolicy {
194    pub key_identifier: [u8; 16],
195    pub flags: FscryptPolicyFlags,
196}
197
198#[derive(Debug, Default, Clone, PartialEq)]
199pub struct FsNodeInfo {
200    pub mode: FileMode,
201    pub link_count: usize,
202    pub uid: uid_t,
203    pub gid: gid_t,
204    pub rdev: DeviceId,
205    pub size: usize,
206    pub blksize: usize,
207    pub blocks: usize,
208    pub time_status_change: UtcInstant,
209    pub time_access: UtcInstant,
210    pub time_modify: UtcInstant,
211    pub casefold: bool,
212
213    // If this node is fscrypt encrypted, stores the encryption policy (main key identifier and
214    // flags).
215    pub encryption_policy: Option<FscryptNodePolicy>,
216
217    // Used to indicate to filesystems that manage timestamps that an access has occurred and to
218    // update the node's atime.
219    // This only impacts accesses within Starnix. Most Fuchsia programs are not expected to maintain
220    // access times. If the file handle is transferred out of Starnix, there may be inconsistencies.
221    pub pending_time_access_update: bool,
222}
223
224impl FsNodeInfo {
225    pub fn new(mode: FileMode, owner: FsCred) -> Self {
226        let now = utc::utc_now();
227        Self {
228            mode,
229            link_count: if mode.is_dir() { 2 } else { 1 },
230            uid: owner.uid,
231            gid: owner.gid,
232            blksize: DEFAULT_BYTES_PER_BLOCK,
233            time_status_change: now,
234            time_access: now,
235            time_modify: now,
236            ..Default::default()
237        }
238    }
239
240    pub fn storage_size(&self) -> usize {
241        self.blksize.saturating_mul(self.blocks)
242    }
243
244    pub fn chmod(&mut self, mode: FileMode) {
245        self.mode = (self.mode & !FileMode::PERMISSIONS) | (mode & FileMode::PERMISSIONS);
246    }
247
248    pub fn chown(&mut self, owner: Option<uid_t>, group: Option<gid_t>) {
249        if let Some(owner) = owner {
250            self.uid = owner;
251        }
252        if let Some(group) = group {
253            self.gid = group;
254        }
255        self.clear_suid_and_sgid_bits();
256    }
257
258    fn clear_sgid_bit(&mut self) {
259        // If the group execute bit is not set, the setgid bit actually indicates mandatory
260        // locking and should not be cleared.
261        if self.mode.intersects(FileMode::IXGRP) {
262            self.mode &= !FileMode::ISGID;
263        }
264    }
265
266    fn has_suid_or_sgid_bits(&self) -> bool {
267        // ISGID is only considered as setgid bit if IXGRP is present.
268        self.mode.is_reg()
269            && (self.mode.contains(FileMode::ISUID)
270                || self.mode.contains(FileMode::ISGID | FileMode::IXGRP))
271    }
272
273    fn clear_suid_and_sgid_bits(&mut self) {
274        // Clear the setuid and setgid bits if the file is executable and a regular file.
275        if self.mode.is_reg() {
276            self.mode &= !FileMode::ISUID;
277            self.clear_sgid_bit();
278        }
279    }
280
281    pub fn cred(&self) -> FsCred {
282        FsCred { uid: self.uid, gid: self.gid }
283    }
284
285    pub fn apply_suid_and_sgid(&self, creds: &mut Credentials) {
286        if self.mode.contains(FileMode::ISUID) {
287            creds.euid = self.uid;
288        }
289
290        // See <https://man7.org/linux/man-pages/man7/inode.7.html>:
291        //
292        //   For an executable file, the set-group-ID bit causes the
293        //   effective group ID of a process that executes the file to change
294        //   as described in execve(2).  For a file that does not have the
295        //   group execution bit (S_IXGRP) set, the set-group-ID bit indicates
296        //   mandatory file/record locking.
297        if self.mode.contains(FileMode::ISGID | FileMode::IXGRP) {
298            creds.egid = self.gid;
299        }
300    }
301}
302
303#[derive(Default)]
304struct FlockInfo {
305    /// Whether the node is currently locked. The meaning of the different values are:
306    /// - `None`: The node is not locked.
307    /// - `Some(false)`: The node is locked non exclusively.
308    /// - `Some(true)`: The node is locked exclusively.
309    locked_exclusive: Option<bool>,
310    /// The FileObject that hold the lock.
311    locking_handles: Vec<WeakFileHandle>,
312    /// The queue to notify process waiting on the lock.
313    wait_queue: WaitQueue,
314}
315
316impl FlockInfo {
317    /// Removes all file handle not holding `predicate` from the list of object holding the lock. If
318    /// this empties the list, unlocks the node and notifies all waiting processes.
319    pub fn retain<F>(&mut self, predicate: F)
320    where
321        F: Fn(&FileObject) -> bool,
322    {
323        if !self.locking_handles.is_empty() {
324            self.locking_handles
325                .retain(|w| if let Some(fh) = w.upgrade() { predicate(&fh) } else { false });
326            if self.locking_handles.is_empty() {
327                self.locked_exclusive = None;
328                self.wait_queue.notify_all();
329            }
330        }
331    }
332}
333
334/// `st_blksize` is measured in units of 512 bytes.
335pub const DEFAULT_BYTES_PER_BLOCK: usize = 512;
336
337pub struct FlockOperation {
338    operation: u32,
339}
340
341impl FlockOperation {
342    pub fn from_flags(operation: u32) -> Result<Self, Errno> {
343        if operation & !(LOCK_SH | LOCK_EX | LOCK_UN | LOCK_NB) != 0 {
344            return error!(EINVAL);
345        }
346        if [LOCK_SH, LOCK_EX, LOCK_UN].iter().filter(|&&o| operation & o == o).count() != 1 {
347            return error!(EINVAL);
348        }
349        Ok(Self { operation })
350    }
351
352    pub fn is_unlock(&self) -> bool {
353        self.operation & LOCK_UN > 0
354    }
355
356    pub fn is_lock_exclusive(&self) -> bool {
357        self.operation & LOCK_EX > 0
358    }
359
360    pub fn is_blocking(&self) -> bool {
361        self.operation & LOCK_NB == 0
362    }
363}
364
365impl FileObject {
366    /// Advisory locking.
367    ///
368    /// See flock(2).
369    pub fn flock(
370        &self,
371        current_task: &CurrentTask,
372        operation: FlockOperation,
373    ) -> Result<(), Errno> {
374        if self.flags().contains(OpenFlags::PATH) {
375            return error!(EBADF);
376        }
377        security::check_file_lock_access(current_task, self)?;
378        loop {
379            let mut flock_info = self.name.entry.node.ensure_rare_data().flock_info.lock();
380            if operation.is_unlock() {
381                flock_info.retain(|fh| !std::ptr::eq(fh, self));
382                return Ok(());
383            }
384            // Operation is a locking operation.
385            // 1. File is not locked
386            if flock_info.locked_exclusive.is_none() {
387                flock_info.locked_exclusive = Some(operation.is_lock_exclusive());
388                flock_info.locking_handles.push(self.weak_handle.clone());
389                return Ok(());
390            }
391
392            let file_lock_is_exclusive = flock_info.locked_exclusive == Some(true);
393            let fd_has_lock = flock_info
394                .locking_handles
395                .iter()
396                .find_map(|w| {
397                    w.upgrade().and_then(|fh| {
398                        if std::ptr::eq(&fh as &FileObject, self) { Some(()) } else { None }
399                    })
400                })
401                .is_some();
402
403            // 2. File is locked, but fd already have a lock
404            if fd_has_lock {
405                if operation.is_lock_exclusive() == file_lock_is_exclusive {
406                    // Correct lock is already held, return.
407                    return Ok(());
408                } else {
409                    // Incorrect lock is held. Release the lock and loop back to try to reacquire
410                    // it. flock doesn't guarantee atomic lock type switching.
411                    flock_info.retain(|fh| !std::ptr::eq(fh, self));
412                    continue;
413                }
414            }
415
416            // 3. File is locked, and fd doesn't have a lock.
417            if !file_lock_is_exclusive && !operation.is_lock_exclusive() {
418                // The lock is not exclusive, let's grab it.
419                flock_info.locking_handles.push(self.weak_handle.clone());
420                return Ok(());
421            }
422
423            // 4. The operation cannot be done at this time.
424            if !operation.is_blocking() {
425                return error!(EAGAIN);
426            }
427
428            // Register a waiter to be notified when the lock is released. Release the lock on
429            // FlockInfo, and wait.
430            let waiter = Waiter::new();
431            flock_info.wait_queue.wait_async(&waiter);
432            std::mem::drop(flock_info);
433            waiter.wait(current_task)?;
434        }
435    }
436}
437
438// The inner mod is required because bitflags cannot pass the attribute through to the single
439// variant, and attributes cannot be applied to macro invocations.
440mod inner_flags {
441    // Part of the code for the AT_STATX_SYNC_AS_STAT case that's produced by the macro triggers the
442    // lint, but as a whole, the produced code is still correct.
443    #![allow(clippy::bad_bit_mask)] // TODO(b/303500202) Remove once addressed in bitflags.
444    use super::{bitflags, uapi};
445
446    bitflags! {
447        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
448        pub struct StatxFlags: u32 {
449            const AT_SYMLINK_NOFOLLOW = uapi::AT_SYMLINK_NOFOLLOW;
450            const AT_EMPTY_PATH = uapi::AT_EMPTY_PATH;
451            const AT_NO_AUTOMOUNT = uapi::AT_NO_AUTOMOUNT;
452            const AT_STATX_SYNC_AS_STAT = uapi::AT_STATX_SYNC_AS_STAT;
453            const AT_STATX_FORCE_SYNC = uapi::AT_STATX_FORCE_SYNC;
454            const AT_STATX_DONT_SYNC = uapi::AT_STATX_DONT_SYNC;
455            const STATX_ATTR_VERITY = uapi::STATX_ATTR_VERITY;
456        }
457    }
458}
459
460pub use inner_flags::StatxFlags;
461
462#[derive(Copy, Clone, Debug, PartialEq, Eq)]
463pub enum UnlinkKind {
464    /// Unlink a directory.
465    Directory,
466
467    /// Unlink a non-directory.
468    NonDirectory,
469}
470
471pub enum SymlinkTarget {
472    Path(FsString),
473    Node(NamespaceNode),
474}
475
476#[derive(Clone, Copy, PartialEq, Eq)]
477pub enum XattrOp {
478    /// Set the value of the extended attribute regardless of whether it exists.
479    Set,
480    /// Create a new extended attribute. Fail if it already exists.
481    Create,
482    /// Replace the value of the extended attribute. Fail if it doesn't exist.
483    Replace,
484}
485
486impl XattrOp {
487    pub fn into_flags(self) -> u32 {
488        match self {
489            Self::Set => 0,
490            Self::Create => uapi::XATTR_CREATE,
491            Self::Replace => uapi::XATTR_REPLACE,
492        }
493    }
494}
495
496/// Returns a value, or the size required to contains it.
497#[derive(Clone, Debug, PartialEq)]
498pub enum ValueOrSize<T> {
499    Value(T),
500    Size(usize),
501}
502
503impl<T> ValueOrSize<T> {
504    pub fn map<F, U>(self, f: F) -> ValueOrSize<U>
505    where
506        F: FnOnce(T) -> U,
507    {
508        match self {
509            Self::Size(s) => ValueOrSize::Size(s),
510            Self::Value(v) => ValueOrSize::Value(f(v)),
511        }
512    }
513
514    #[cfg(test)]
515    pub fn unwrap(self) -> T {
516        match self {
517            Self::Size(_) => panic!("Unwrap ValueOrSize that is a Size"),
518            Self::Value(v) => v,
519        }
520    }
521}
522
523impl<T> From<T> for ValueOrSize<T> {
524    fn from(t: T) -> Self {
525        Self::Value(t)
526    }
527}
528
529#[derive(Copy, Clone, Eq, PartialEq, Debug)]
530pub enum FallocMode {
531    Allocate { keep_size: bool },
532    PunchHole,
533    Collapse,
534    Zero { keep_size: bool },
535    InsertRange,
536    UnshareRange,
537}
538
539impl FallocMode {
540    pub fn from_bits(mode: u32) -> Option<Self> {
541        // `fallocate()` allows only the following values for `mode`.
542        if mode == 0 {
543            Some(Self::Allocate { keep_size: false })
544        } else if mode == FALLOC_FL_KEEP_SIZE {
545            Some(Self::Allocate { keep_size: true })
546        } else if mode == FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE {
547            Some(Self::PunchHole)
548        } else if mode == FALLOC_FL_COLLAPSE_RANGE {
549            Some(Self::Collapse)
550        } else if mode == FALLOC_FL_ZERO_RANGE {
551            Some(Self::Zero { keep_size: false })
552        } else if mode == FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE {
553            Some(Self::Zero { keep_size: true })
554        } else if mode == FALLOC_FL_INSERT_RANGE {
555            Some(Self::InsertRange)
556        } else if mode == FALLOC_FL_UNSHARE_RANGE {
557            Some(Self::UnshareRange)
558        } else {
559            None
560        }
561    }
562}
563
564pub type LookupVec<T> = SmallVec<[T; 8]>;
565
566pub trait FsNodeOps: Send + Sync + AsAny + 'static {
567    /// Delegate the access check to the node.
568    fn check_access(
569        &self,
570        node: &FsNode,
571        current_task: &CurrentTask,
572        access: security::PermissionFlags,
573        info: &DynamicLockDepRwLock<FsNodeInfo>,
574        reason: CheckAccessReason,
575        audit_context: security::Auditable<'_>,
576    ) -> Result<(), Errno> {
577        node.default_check_access_impl(current_task, access, reason, info.read(), audit_context)
578    }
579
580    /// Build the [`DirEntryOps`] for a new [`DirEntry`] that will be associated
581    /// to this node.
582    fn create_dir_entry_ops(&self) -> Box<dyn DirEntryOps> {
583        Box::new(DefaultDirEntryOps)
584    }
585
586    /// Build the `FileOps` for the file associated to this node.
587    ///
588    /// The returned FileOps will be used to create a FileObject, which might
589    /// be assigned an FdNumber.
590    fn create_file_ops(
591        &self,
592        node: &FsNode,
593        _current_task: &CurrentTask,
594        flags: OpenFlags,
595    ) -> Result<Box<dyn FileOps>, Errno>;
596
597    /// Finds an existing child node matching `name` within the parent directory `entry`.
598    fn lookup(
599        &self,
600        _entry: &DirEntry,
601        _current_task: &CurrentTask,
602        name: &FsStr,
603    ) -> Result<FsNodeHandle, Errno> {
604        // The default implementation here is suitable for filesystems that have permanent entries;
605        // entries that already exist will get found in the cache and shouldn't get this far.
606        error!(ENOENT, format!("looking for {name}"))
607    }
608
609    /// Returns whether this node supports pipelined lookups.
610    fn has_lookup_pipelined(&self) -> bool {
611        false
612    }
613
614    /// Finds multiple children nodes in sequence.
615    ///
616    /// This can be used to pipeline lookups in filesystems that support it.
617    ///
618    /// Each name in `names` is looked up in the node found for the previous name, starting with
619    /// `entry`, and the results are returned in the same order as `names`. Lookups stop at the
620    /// first error, so fewer results than `names` may be returned, but at least one result must
621    /// be returned if `names` is not empty.
622    fn lookup_pipelined(
623        &self,
624        _entry: &DirEntry,
625        _current_task: &CurrentTask,
626        _names: &[&FsStr],
627    ) -> LookupVec<Result<FsNodeHandle, Errno>> {
628        panic!("has_lookup_pipelined should be false");
629    }
630
631    /// Create and return the given child node.
632    ///
633    /// The mode field of the FsNodeInfo indicates what kind of child to
634    /// create.
635    ///
636    /// This function is never called with FileMode::IFDIR. The mkdir function
637    /// is used to create directories instead.
638    fn mknod(
639        &self,
640        node: &FsNode,
641        _current_task: &CurrentTask,
642        _name: &FsStr,
643        _mode: FileMode,
644        _dev: DeviceId,
645        _owner: FsCred,
646    ) -> Result<FsNodeHandle, Errno>;
647
648    /// Create and return the given child node as a subdirectory.
649    fn mkdir(
650        &self,
651        node: &FsNode,
652        _current_task: &CurrentTask,
653        _name: &FsStr,
654        _mode: FileMode,
655        _owner: FsCred,
656    ) -> Result<FsNodeHandle, Errno>;
657
658    /// Creates a symlink with the given `target` path.
659    fn create_symlink(
660        &self,
661        node: &FsNode,
662        _current_task: &CurrentTask,
663        _name: &FsStr,
664        _target: &FsStr,
665        _owner: FsCred,
666    ) -> Result<FsNodeHandle, Errno>;
667
668    /// Creates an anonymous file.
669    ///
670    /// The FileMode::IFMT of the FileMode is always FileMode::IFREG.
671    ///
672    /// Used by O_TMPFILE.
673    fn create_tmpfile(
674        &self,
675        _node: &FsNode,
676        _current_task: &CurrentTask,
677        _mode: FileMode,
678        _owner: FsCred,
679    ) -> Result<FsNodeHandle, Errno> {
680        error!(EOPNOTSUPP)
681    }
682
683    /// Reads the symlink from this node.
684    fn readlink(
685        &self,
686        _node: &FsNode,
687        _current_task: &CurrentTask,
688    ) -> Result<SymlinkTarget, Errno> {
689        error!(EINVAL)
690    }
691
692    /// Create a hard link with the given name to the given child.
693    fn link(
694        &self,
695        _node: &FsNode,
696        _current_task: &CurrentTask,
697        _name: &FsStr,
698        _child: &FsNodeHandle,
699    ) -> Result<(), Errno> {
700        error!(EPERM)
701    }
702
703    /// Remove the child with the given name, if the child exists.
704    ///
705    /// The UnlinkKind parameter indicates whether the caller intends to unlink
706    /// a directory or a non-directory child.
707    fn unlink(
708        &self,
709        node: &FsNode,
710        _current_task: &CurrentTask,
711        _name: &FsStr,
712        _child: &FsNodeHandle,
713    ) -> Result<(), Errno>;
714
715    /// Acquire the necessary append lock for the operations that depend on them.
716    /// Should be done before calling `allocate` or `truncate` to avoid lock ordering issues.
717    fn append_lock_read<'a>(
718        &'a self,
719        node: &'a FsNode,
720        current_task: &CurrentTask,
721    ) -> Result<AppendLockGuard<'a>, Errno> {
722        return node.append_lock.read(current_task);
723    }
724
725    /// Acquire the necessary append lock for operations that need exclusive access (e.g., write append).
726    fn append_lock_write<'a>(
727        &'a self,
728        node: &'a FsNode,
729        current_task: &CurrentTask,
730    ) -> Result<AppendLockWriteGuard<'a>, Errno> {
731        return node.append_lock.write(current_task);
732    }
733
734    /// Change the length of the file.
735    fn truncate(
736        &self,
737        _guard: &AppendLockWriteGuard<'_>,
738        _node: &FsNode,
739        _current_task: &CurrentTask,
740        _length: u64,
741    ) -> Result<(), Errno> {
742        error!(EINVAL)
743    }
744
745    /// Manipulate allocated disk space for the file.
746    fn allocate(
747        &self,
748        _guard: &AppendLockWriteGuard<'_>,
749        _node: &FsNode,
750        _current_task: &CurrentTask,
751        _mode: FallocMode,
752        _offset: u64,
753        _length: u64,
754    ) -> Result<(), Errno> {
755        error!(EINVAL)
756    }
757
758    /// Update the supplied info with initial state (e.g. size) for the node.
759    ///
760    /// FsNode calls this method when created, to allow the FsNodeOps to
761    /// set appropriate initial values in the FsNodeInfo.
762    fn initial_info(&self, _info: &mut FsNodeInfo) {}
763
764    /// Update node.info as needed.
765    ///
766    /// FsNode calls this method before converting the FsNodeInfo struct into
767    /// the uapi::stat struct to give the file system a chance to update this data
768    /// before it is used by clients.
769    ///
770    /// File systems that keep the FsNodeInfo up-to-date do not need to
771    /// override this function.
772    ///
773    /// Return a read guard for the updated information.
774    fn fetch_and_refresh_info<'a>(
775        &self,
776        _node: &FsNode,
777        _current_task: &CurrentTask,
778        info: &'a DynamicLockDepRwLock<FsNodeInfo>,
779        _flags: StatxFlags,
780    ) -> Result<LockDepReadGuard<'a, FsNodeInfo>, Errno> {
781        Ok(info.read())
782    }
783
784    /// Syncs cached data to persistent storage.
785    fn sync(&self, _node: &FsNode, _current_task: &CurrentTask) -> Result<(), Errno> {
786        Ok(())
787    }
788
789    /// Update node attributes persistently.
790    ///
791    /// Implementations must enforce prerequisites for attribute changes (for example,
792    /// enabling casefold on a non-empty directory must return [`ENOTEMPTY`]).
793    fn update_attributes(
794        &self,
795        _node: &FsNode,
796        _current_task: &CurrentTask,
797        _info: &FsNodeInfo,
798        _has: zxio_node_attr_has_t,
799    ) -> Result<(), Errno> {
800        Ok(())
801    }
802
803    /// Get an extended attribute on the node.
804    ///
805    /// An implementation can systematically return a value. Otherwise, if `max_size` is 0, it can
806    /// instead return the size of the attribute, and can return an ERANGE error if max_size is not
807    /// 0, and lesser than the required size.
808    fn get_xattr(
809        &self,
810        _node: &FsNode,
811        _current_task: &CurrentTask,
812        _name: &FsStr,
813        _max_size: usize,
814    ) -> Result<ValueOrSize<FsString>, Errno> {
815        error!(ENOTSUP)
816    }
817
818    /// Set an extended attribute on the node.
819    fn set_xattr(
820        &self,
821        _node: &FsNode,
822        _current_task: &CurrentTask,
823        _name: &FsStr,
824        _value: &FsStr,
825        _op: XattrOp,
826    ) -> Result<(), Errno> {
827        error!(ENOTSUP)
828    }
829
830    fn remove_xattr(
831        &self,
832        _node: &FsNode,
833        _current_task: &CurrentTask,
834        _name: &FsStr,
835    ) -> Result<(), Errno> {
836        error!(ENOTSUP)
837    }
838
839    /// An implementation can systematically return a value. Otherwise, if `max_size` is 0, it can
840    /// instead return the size of the 0 separated string needed to represent the value, and can
841    /// return an ERANGE error if max_size is not 0, and lesser than the required size.
842    fn list_xattrs(
843        &self,
844        _node: &FsNode,
845        _current_task: &CurrentTask,
846        _max_size: usize,
847    ) -> Result<ValueOrSize<Vec<FsString>>, Errno> {
848        error!(ENOTSUP)
849    }
850
851    /// Called when the FsNode is freed by the Kernel.
852    fn forget(
853        self: Box<Self>,
854        _current_task: &CurrentTask,
855        _info: FsNodeInfo,
856    ) -> Result<(), Errno> {
857        Ok(())
858    }
859
860    ////////////////////
861    // FS-Verity operations
862
863    /// Marks that FS-Verity is being built. Writes fsverity descriptor and merkle tree, the latter
864    /// computed by the filesystem.
865    /// This should ensure there are no writable file handles. Returns EEXIST if the file was
866    /// already fsverity-enabled. Returns EBUSY if this ioctl was already running on this file.
867    fn enable_fsverity(
868        &self,
869        _node: &FsNode,
870        _current_task: &CurrentTask,
871        _descriptor: &fsverity_descriptor,
872    ) -> Result<(), Errno> {
873        error!(ENOTSUP)
874    }
875
876    /// Read fsverity descriptor, if the node is fsverity-enabled. Else returns ENODATA.
877    fn get_fsverity_descriptor(&self, _log_blocksize: u8) -> Result<fsverity_descriptor, Errno> {
878        error!(ENOTSUP)
879    }
880
881    /// The key used to identify this node in the file system's node cache.
882    ///
883    /// For many file systems, this will be the same as the inode number. However, some file
884    /// systems, such as FUSE, sometimes use different `node_key` and inode numbers.
885    fn node_key(&self, node: &FsNode) -> ino_t {
886        node.ino
887    }
888
889    /// Returns the size of the file.
890    fn get_size(&self, node: &FsNode, current_task: &CurrentTask) -> Result<usize, Errno> {
891        let info = node.fetch_and_refresh_info(current_task)?;
892        Ok(info.size.try_into().map_err(|_| errno!(EINVAL))?)
893    }
894}
895
896impl<T> From<T> for Box<dyn FsNodeOps>
897where
898    T: FsNodeOps,
899{
900    fn from(ops: T) -> Box<dyn FsNodeOps> {
901        Box::new(ops)
902    }
903}
904
905/// Implements [`FsNodeOps`] methods in a way that makes sense for symlinks.
906/// You must implement [`FsNodeOps::readlink`].
907#[macro_export]
908macro_rules! fs_node_impl_symlink {
909    () => {
910        $crate::vfs::fs_node_impl_not_dir!();
911
912        fn create_file_ops(
913            &self,
914            node: &$crate::vfs::FsNode,
915            _current_task: &CurrentTask,
916            _flags: starnix_uapi::open_flags::OpenFlags,
917        ) -> Result<Box<dyn $crate::vfs::FileOps>, starnix_uapi::errors::Errno> {
918            assert!(node.is_lnk());
919            unreachable!("Symlink nodes cannot be opened.");
920        }
921    };
922}
923
924#[macro_export]
925macro_rules! fs_node_impl_dir_readonly_ops {
926    () => {
927        fn mkdir(
928            &self,
929            _node: &$crate::vfs::FsNode,
930            _current_task: &$crate::task::CurrentTask,
931            name: &$crate::vfs::FsStr,
932            _mode: starnix_uapi::file_mode::FileMode,
933            _owner: starnix_uapi::auth::FsCred,
934        ) -> Result<$crate::vfs::FsNodeHandle, starnix_uapi::errors::Errno> {
935            starnix_uapi::error!(EROFS, format!("mkdir failed: {:?}", name))
936        }
937
938        fn mknod(
939            &self,
940            _node: &$crate::vfs::FsNode,
941            _current_task: &$crate::task::CurrentTask,
942            name: &$crate::vfs::FsStr,
943            _mode: starnix_uapi::file_mode::FileMode,
944            _dev: starnix_uapi::device_id::DeviceId,
945            _owner: starnix_uapi::auth::FsCred,
946        ) -> Result<$crate::vfs::FsNodeHandle, starnix_uapi::errors::Errno> {
947            starnix_uapi::error!(EROFS, format!("mknod failed: {:?}", name))
948        }
949
950        fn create_symlink(
951            &self,
952            _node: &$crate::vfs::FsNode,
953            _current_task: &$crate::task::CurrentTask,
954            name: &$crate::vfs::FsStr,
955            _target: &$crate::vfs::FsStr,
956            _owner: starnix_uapi::auth::FsCred,
957        ) -> Result<$crate::vfs::FsNodeHandle, starnix_uapi::errors::Errno> {
958            starnix_uapi::error!(EROFS, format!("symlink failed: {:?}", name))
959        }
960
961        fn link(
962            &self,
963            _node: &$crate::vfs::FsNode,
964            _current_task: &$crate::task::CurrentTask,
965            name: &$crate::vfs::FsStr,
966            _child: &$crate::vfs::FsNodeHandle,
967        ) -> Result<(), starnix_uapi::errors::Errno> {
968            starnix_uapi::error!(EROFS, format!("link failed: {:?}", name))
969        }
970
971        fn unlink(
972            &self,
973            _node: &$crate::vfs::FsNode,
974            _current_task: &$crate::task::CurrentTask,
975            name: &$crate::vfs::FsStr,
976            _child: &$crate::vfs::FsNodeHandle,
977        ) -> Result<(), starnix_uapi::errors::Errno> {
978            starnix_uapi::error!(EROFS, format!("unlink failed: {:?}", name))
979        }
980    };
981}
982
983#[macro_export]
984macro_rules! fs_node_impl_dir_readonly {
985    () => {
986        $crate::vfs::fs_node_impl_dir_readonly_ops!();
987
988        fn check_access(
989            &self,
990            node: &$crate::vfs::FsNode,
991            current_task: &$crate::task::CurrentTask,
992            permission_flags: $crate::security::PermissionFlags,
993            info: &starnix_sync::DynamicLockDepRwLock<$crate::vfs::FsNodeInfo>,
994            reason: $crate::vfs::CheckAccessReason,
995            audit_context: $crate::security::Auditable<'_>,
996        ) -> Result<(), starnix_uapi::errors::Errno> {
997            let access = permission_flags.as_access();
998            if access.contains(starnix_uapi::file_mode::Access::WRITE) {
999                return starnix_uapi::error!(
1000                    EROFS,
1001                    format!("check_access failed: read-only directory")
1002                );
1003            }
1004            node.default_check_access_impl(
1005                current_task,
1006                permission_flags,
1007                reason,
1008                info.read(),
1009                audit_context,
1010            )
1011        }
1012    };
1013}
1014
1015/// Trait that objects can implement if they need to handle extended attribute storage. Allows
1016/// delegating extended attribute operations in [`FsNodeOps`] to another object.
1017///
1018/// See [`fs_node_impl_xattr_delegate`] for usage details.
1019pub trait XattrStorage {
1020    /// Delegate for [`FsNodeOps::get_xattr`].
1021    fn get_xattr(&self, name: &FsStr) -> Result<FsString, Errno>;
1022
1023    /// Delegate for [`FsNodeOps::set_xattr`].
1024    fn set_xattr(&self, name: &FsStr, value: &FsStr, op: XattrOp) -> Result<(), Errno>;
1025
1026    /// Delegate for [`FsNodeOps::remove_xattr`].
1027    fn remove_xattr(&self, name: &FsStr) -> Result<(), Errno>;
1028
1029    /// Delegate for [`FsNodeOps::list_xattrs`].
1030    fn list_xattrs(&self) -> Result<Vec<FsString>, Errno>;
1031}
1032
1033/// Implements extended attribute ops for [`FsNodeOps`] by delegating to another object which
1034/// implements the [`XattrStorage`] trait or a similar interface. For example:
1035///
1036/// ```
1037/// struct Xattrs {}
1038///
1039/// impl XattrStorage for Xattrs {
1040///     // implement XattrStorage
1041/// }
1042///
1043/// struct Node {
1044///     xattrs: Xattrs
1045/// }
1046///
1047/// impl FsNodeOps for Node {
1048///     // Delegate extended attribute ops in FsNodeOps to self.xattrs
1049///     fs_node_impl_xattr_delegate!(self, self.xattrs);
1050///
1051///     // add other FsNodeOps impls here
1052/// }
1053/// ```
1054#[macro_export]
1055macro_rules! fs_node_impl_xattr_delegate {
1056    ($self:ident, $delegate:expr) => {
1057        fn get_xattr(
1058            &$self,
1059            _node: &FsNode,
1060            _current_task: &CurrentTask,
1061            name: &$crate::vfs::FsStr,
1062            _size: usize,
1063        ) -> Result<$crate::vfs::ValueOrSize<$crate::vfs::FsString>, starnix_uapi::errors::Errno> {
1064            Ok($delegate.get_xattr(name)?.into())
1065        }
1066
1067        fn set_xattr(
1068            &$self,
1069            _node: &FsNode,
1070            _current_task: &CurrentTask,
1071            name: &$crate::vfs::FsStr,
1072            value: &$crate::vfs::FsStr,
1073            op: $crate::vfs::XattrOp,
1074        ) -> Result<(), starnix_uapi::errors::Errno> {
1075            $delegate.set_xattr(name, value, op)
1076        }
1077
1078        fn remove_xattr(
1079            &$self,
1080            _node: &FsNode,
1081            _current_task: &CurrentTask,
1082            name: &$crate::vfs::FsStr,
1083        ) -> Result<(), starnix_uapi::errors::Errno> {
1084            $delegate.remove_xattr(name)
1085        }
1086
1087        fn list_xattrs(
1088            &$self,
1089            _node: &FsNode,
1090            _current_task: &CurrentTask,
1091            _size: usize,
1092        ) -> Result<$crate::vfs::ValueOrSize<Vec<$crate::vfs::FsString>>, starnix_uapi::errors::Errno> {
1093            Ok($delegate.list_xattrs()?.into())
1094        }
1095    };
1096}
1097
1098/// Stubs out [`FsNodeOps`] methods that only apply to directories.
1099#[macro_export]
1100macro_rules! fs_node_impl_not_dir {
1101    () => {
1102        fn lookup(
1103            &self,
1104            _entry: &$crate::vfs::DirEntry,
1105            _current_task: &$crate::task::CurrentTask,
1106            _name: &$crate::vfs::FsStr,
1107        ) -> Result<$crate::vfs::FsNodeHandle, starnix_uapi::errors::Errno> {
1108            starnix_uapi::error!(ENOTDIR)
1109        }
1110
1111        fn mknod(
1112            &self,
1113            _node: &$crate::vfs::FsNode,
1114            _current_task: &$crate::task::CurrentTask,
1115            _name: &$crate::vfs::FsStr,
1116            _mode: starnix_uapi::file_mode::FileMode,
1117            _dev: starnix_uapi::device_id::DeviceId,
1118            _owner: starnix_uapi::auth::FsCred,
1119        ) -> Result<$crate::vfs::FsNodeHandle, starnix_uapi::errors::Errno> {
1120            starnix_uapi::error!(ENOTDIR)
1121        }
1122
1123        fn mkdir(
1124            &self,
1125            _node: &$crate::vfs::FsNode,
1126            _current_task: &$crate::task::CurrentTask,
1127            _name: &$crate::vfs::FsStr,
1128            _mode: starnix_uapi::file_mode::FileMode,
1129            _owner: starnix_uapi::auth::FsCred,
1130        ) -> Result<$crate::vfs::FsNodeHandle, starnix_uapi::errors::Errno> {
1131            starnix_uapi::error!(ENOTDIR)
1132        }
1133
1134        fn create_symlink(
1135            &self,
1136            _node: &$crate::vfs::FsNode,
1137            _current_task: &$crate::task::CurrentTask,
1138            _name: &$crate::vfs::FsStr,
1139            _target: &$crate::vfs::FsStr,
1140            _owner: starnix_uapi::auth::FsCred,
1141        ) -> Result<$crate::vfs::FsNodeHandle, starnix_uapi::errors::Errno> {
1142            starnix_uapi::error!(ENOTDIR)
1143        }
1144
1145        fn unlink(
1146            &self,
1147            _node: &$crate::vfs::FsNode,
1148            _current_task: &$crate::task::CurrentTask,
1149            _name: &$crate::vfs::FsStr,
1150            _child: &$crate::vfs::FsNodeHandle,
1151        ) -> Result<(), starnix_uapi::errors::Errno> {
1152            starnix_uapi::error!(ENOTDIR)
1153        }
1154    };
1155}
1156
1157#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1158pub enum TimeUpdateType {
1159    Now,
1160    Omit,
1161    Time(UtcInstant),
1162}
1163
1164// Public re-export of macros allows them to be used like regular rust items.
1165pub use fs_node_impl_dir_readonly;
1166pub use fs_node_impl_dir_readonly_ops;
1167pub use fs_node_impl_not_dir;
1168pub use fs_node_impl_symlink;
1169pub use fs_node_impl_xattr_delegate;
1170
1171pub struct SpecialNode;
1172
1173impl FsNodeOps for SpecialNode {
1174    fs_node_impl_not_dir!();
1175
1176    fn create_file_ops(
1177        &self,
1178        _node: &FsNode,
1179        _current_task: &CurrentTask,
1180        _flags: OpenFlags,
1181    ) -> Result<Box<dyn FileOps>, Errno> {
1182        unreachable!("Special nodes cannot be opened.");
1183    }
1184}
1185
1186impl FsNode {
1187    /// Returns true if the `fs_node` is private to the `Kernel`/`FileSystem`, in which
1188    /// case both MAC and DAC checks should be skipped.
1189    pub fn is_private(&self) -> bool {
1190        self.flags.contains(FsNodeFlags::IS_PRIVATE)
1191    }
1192
1193    /// Create a node without inserting it into the FileSystem node cache.
1194    ///
1195    /// This is usually not what you want!
1196    /// Only use if you're also using get_or_create_node, like ext4.
1197    pub fn new_uncached(
1198        ino: ino_t,
1199        ops: impl Into<Box<dyn FsNodeOps>>,
1200        fs: &FileSystemHandle,
1201        info: FsNodeInfo,
1202        flags: FsNodeFlags,
1203    ) -> FsNodeHandle {
1204        let ops = ops.into();
1205        FsNodeHandle::new(Self::new_internal(ino, ops, Arc::downgrade(fs), info, flags).into())
1206    }
1207
1208    fn new_internal(
1209        ino: ino_t,
1210        ops: Box<dyn FsNodeOps>,
1211        fs: Weak<FileSystem>,
1212        info: FsNodeInfo,
1213        flags: FsNodeFlags,
1214    ) -> Self {
1215        // Allow the FsNodeOps to populate initial info.
1216        let mut info = info;
1217        ops.initial_info(&mut info);
1218
1219        let fs_lockdep_type =
1220            fs.upgrade().map(|fs| fs.fs_lockdep_type()).unwrap_or(FsLockDepType::Normal);
1221        let info_lock = match fs_lockdep_type {
1222            FsLockDepType::Normal => DynamicLockDepRwLock::new::<FsNodeInfoLevel>(info),
1223            FsLockDepType::Fuse => DynamicLockDepRwLock::new::<FuseFsNodeInfoLevel>(info),
1224            FsLockDepType::Recursive => DynamicLockDepRwLock::new::<FsNodeInfoRecursiveLevel>(info),
1225        };
1226
1227        // The linter will fail in non test mode as it will not see the lock check.
1228        #[allow(clippy::let_and_return)]
1229        {
1230            let result = Self {
1231                ino,
1232                flags,
1233                ops,
1234                fs,
1235                info: info_lock,
1236                append_lock: Default::default(),
1237                rare_data: Default::default(),
1238                write_guard_state: Default::default(),
1239                fsverity: Default::default(),
1240                security_state: Default::default(),
1241            };
1242            #[cfg(any(test, debug_assertions))]
1243            {
1244                let _l1 = result.append_lock.read_for_lock_ordering();
1245                let _l2 = result.info.read();
1246                let _l3 = result.write_guard_state.lock();
1247                let _l4 = result.fsverity.lock();
1248            }
1249            result
1250        }
1251    }
1252
1253    pub fn fs(&self) -> FileSystemHandle {
1254        self.fs.upgrade().expect("FileSystem did not live long enough")
1255    }
1256
1257    pub fn try_fs(&self) -> Option<FileSystemHandle> {
1258        self.fs.upgrade()
1259    }
1260
1261    pub fn ops(&self) -> &dyn FsNodeOps {
1262        self.ops.as_ref()
1263    }
1264
1265    /// Returns an error if this node is encrypted and locked. Does not require
1266    /// fetch_and_refresh_info because FS_IOC_SET_ENCRYPTION_POLICY updates info and once a node is
1267    /// encrypted, it remains encrypted forever.
1268    pub fn fail_if_locked(
1269        &self,
1270        _current_task: &CurrentTask,
1271        node_info: &FsNodeInfo,
1272    ) -> Result<(), Errno> {
1273        if let Some(policy) = node_info.encryption_policy {
1274            let crypt_service = self.fs().crypt_service().ok_or_else(|| errno!(ENOKEY))?;
1275            if !crypt_service.contains_key(EncryptionKeyId::from(policy.key_identifier)) {
1276                return error!(ENOKEY);
1277            }
1278        }
1279        Ok(())
1280    }
1281
1282    /// Returns the `FsNode`'s `FsNodeOps` as a `&T`, or `None` if the downcast fails.
1283    pub fn downcast_ops<T>(&self) -> Option<&T>
1284    where
1285        T: 'static,
1286    {
1287        self.ops().as_any().downcast_ref::<T>()
1288    }
1289
1290    pub fn on_file_closed(&self, file: &FileObjectState) {
1291        if let Some(rare_data) = self.rare_data.get() {
1292            let mut flock_info = rare_data.flock_info.lock();
1293            // This function will drop the flock from `file` because the `WeakFileHandle` for
1294            // `file` will no longer upgrade to an `FileHandle`.
1295            flock_info.retain(|_| true);
1296        }
1297        self.record_lock_release(RecordLockOwner::FileObject(file.id));
1298    }
1299
1300    pub fn record_lock(
1301        &self,
1302        current_task: &CurrentTask,
1303        file: &FileObject,
1304        cmd: RecordLockCommand,
1305        flock: uapi::flock,
1306    ) -> Result<Option<uapi::flock>, Errno> {
1307        self.ensure_rare_data().record_locks.lock(current_task, file, cmd, flock)
1308    }
1309
1310    /// Release all record locks acquired by the given owner.
1311    pub fn record_lock_release(&self, owner: RecordLockOwner) {
1312        if let Some(rare_data) = self.rare_data.get() {
1313            rare_data.record_locks.release_locks(owner);
1314        }
1315    }
1316
1317    pub fn create_dir_entry_ops(&self) -> Box<dyn DirEntryOps> {
1318        self.ops().create_dir_entry_ops()
1319    }
1320
1321    pub fn create_file_ops(
1322        &self,
1323        current_task: &CurrentTask,
1324        flags: OpenFlags,
1325    ) -> Result<Box<dyn FileOps>, Errno> {
1326        self.ops().create_file_ops(self, current_task, flags)
1327    }
1328
1329    pub fn open(
1330        &self,
1331        current_task: &CurrentTask,
1332        namespace_node: &NamespaceNode,
1333        open_check: impl Into<OpenAccessCheck>,
1334    ) -> Result<Box<dyn FileOps>, Errno> {
1335        let open_check = open_check.into();
1336        let flags = open_check.open_flags();
1337        // If O_PATH is set, there is no need to create a real FileOps because
1338        // most file operations are disabled.
1339        if flags.contains(OpenFlags::PATH) {
1340            return Ok(Box::new(OPathOps::new()));
1341        }
1342
1343        let access_check = open_check.access_check();
1344        let permission_flags = access_check.permission_flags();
1345        if !permission_flags.is_empty() {
1346            if flags.contains(OpenFlags::NOATIME) {
1347                self.check_o_noatime_allowed(current_task)?;
1348            }
1349
1350            self.check_access(
1351                current_task,
1352                &namespace_node.mount,
1353                permission_flags,
1354                access_check.reason(),
1355                namespace_node,
1356            )?;
1357        }
1358
1359        let (mode, rdev) = {
1360            // Don't hold the info lock while calling into open_device or self.ops().
1361            // TODO: The mode and rdev are immutable and shouldn't require a lock to read.
1362            let info = self.info();
1363            (info.mode, info.rdev)
1364        };
1365
1366        match mode & FileMode::IFMT {
1367            FileMode::IFCHR => {
1368                if namespace_node.mount.flags().contains(MountFlags::NODEV) {
1369                    return error!(EACCES);
1370                }
1371                current_task.kernel().open_device(
1372                    current_task,
1373                    namespace_node,
1374                    flags,
1375                    rdev,
1376                    DeviceMode::Char,
1377                )
1378            }
1379            FileMode::IFBLK => {
1380                if namespace_node.mount.flags().contains(MountFlags::NODEV) {
1381                    return error!(EACCES);
1382                }
1383                current_task.kernel().open_device(
1384                    current_task,
1385                    namespace_node,
1386                    flags,
1387                    rdev,
1388                    DeviceMode::Block,
1389                )
1390            }
1391            FileMode::IFIFO => Pipe::open(current_task, self.fifo(current_task), flags),
1392            // UNIX domain sockets can't be opened.
1393            FileMode::IFSOCK => error!(ENXIO),
1394            _ => self.create_file_ops(current_task, flags),
1395        }
1396    }
1397
1398    pub fn create_node(
1399        &self,
1400        current_task: &CurrentTask,
1401        mount: &MountInfo,
1402        name: &FsStr,
1403        mut mode: FileMode,
1404        dev: DeviceId,
1405        mut owner: FsCred,
1406    ) -> Result<FsNodeHandle, Errno> {
1407        assert!(
1408            !matches!(mode.fmt(), FileMode::EMPTY | FileMode::IFLNK),
1409            "create_node with missing or symlink node type"
1410        );
1411
1412        self.check_access(
1413            current_task,
1414            mount,
1415            Access::WRITE,
1416            CheckAccessReason::InternalPermissionChecks,
1417            security::Auditable::Name(name),
1418        )?;
1419
1420        if mode.is_dir() {
1421            // Even though the man page for mknod(2) says that mknod "cannot be used to create
1422            // directories" in starnix the mkdir syscall (`sys_mkdirat`) ends up calling
1423            // create_node.
1424            security::check_fs_node_mkdir_access(current_task, self, mode, name)?;
1425        } else {
1426            // https://man7.org/linux/man-pages/man2/mknod.2.html says on error EPERM:
1427            //
1428            //   mode requested creation of something other than a regular
1429            //   file, FIFO (named pipe), or UNIX domain socket, and the
1430            //   caller is not privileged (Linux: does not have the
1431            //   CAP_MKNOD capability); also returned if the filesystem
1432            //   containing pathname does not support the type of node
1433            //   requested.
1434            match mode.fmt() {
1435                FileMode::IFREG | FileMode::IFIFO | FileMode::IFSOCK => (),
1436                FileMode::IFCHR if dev == DeviceId::NONE => (),
1437                _ => security::check_task_capable(current_task, CAP_MKNOD)?,
1438            }
1439
1440            if mode.is_reg() {
1441                security::check_fs_node_create_access(current_task, self, mode, name)?;
1442            } else {
1443                security::check_fs_node_mknod_access(current_task, self, mode, name, dev)?;
1444            }
1445        }
1446
1447        // Propagate sticky bit(s) from parent directory to the child.
1448        self.update_metadata_for_child(current_task, &mut mode, &mut owner);
1449
1450        // Delegate to the `ops` implementation to actually create the node.
1451        let new_node = if mode.is_dir() {
1452            self.ops().mkdir(self, current_task, name, mode, owner)?
1453        } else {
1454            self.ops().mknod(self, current_task, name, mode, dev, owner)?
1455        };
1456
1457        // Allow the LSM to apply a security label to the new node.
1458        self.init_new_node_security_on_create(current_task, &new_node, name)?;
1459
1460        Ok(new_node)
1461    }
1462
1463    pub fn create_symlink(
1464        &self,
1465        current_task: &CurrentTask,
1466        mount: &MountInfo,
1467        name: &FsStr,
1468        target: &FsStr,
1469        owner: FsCred,
1470    ) -> Result<FsNodeHandle, Errno> {
1471        self.check_access(
1472            current_task,
1473            mount,
1474            Access::WRITE,
1475            CheckAccessReason::InternalPermissionChecks,
1476            security::Auditable::Name(name),
1477        )?;
1478        security::check_fs_node_symlink_access(current_task, self, name, target)?;
1479
1480        let new_node = self.ops().create_symlink(self, current_task, name, target, owner)?;
1481
1482        self.init_new_node_security_on_create(current_task, &new_node, name)?;
1483
1484        Ok(new_node)
1485    }
1486
1487    /// Requests that the LSM initialise a security label for the `new_node`, and optionally provide
1488    /// an extended attribute to write to the file to persist it.  If no LSM is enabled, no extended
1489    /// attribute returned, or if the filesystem does not support extended attributes, then the call
1490    /// returns success. All other failure modes return an `Errno` that should be early-returned.
1491    fn init_new_node_security_on_create(
1492        &self,
1493        current_task: &CurrentTask,
1494        new_node: &FsNode,
1495        name: &FsStr,
1496    ) -> Result<(), Errno> {
1497        security::fs_node_init_on_create(current_task, &new_node, self, name)?
1498            .map(|xattr| {
1499                match new_node.ops().set_xattr(
1500                    &new_node,
1501                    current_task,
1502                    xattr.name,
1503                    xattr.value.as_slice().into(),
1504                    XattrOp::Create,
1505                ) {
1506                    Err(e) => {
1507                        if e.code == ENOTSUP {
1508                            // This should only occur if a task has an "fscreate" context set, and
1509                            // creates a new file in a filesystem that does not support xattrs.
1510                            Ok(())
1511                        } else {
1512                            Err(e)
1513                        }
1514                    }
1515                    result => result,
1516                }
1517            })
1518            .unwrap_or_else(|| Ok(()))
1519    }
1520
1521    pub fn create_tmpfile(
1522        &self,
1523        current_task: &CurrentTask,
1524        mount: &MountInfo,
1525        mut mode: FileMode,
1526        mut owner: FsCred,
1527        link_behavior: FsNodeLinkBehavior,
1528    ) -> Result<FsNodeHandle, Errno> {
1529        self.check_access(
1530            current_task,
1531            mount,
1532            Access::WRITE,
1533            CheckAccessReason::InternalPermissionChecks,
1534            security::Auditable::Location(std::panic::Location::caller()),
1535        )?;
1536        self.update_metadata_for_child(current_task, &mut mode, &mut owner);
1537        let node = self.ops().create_tmpfile(self, current_task, mode, owner)?;
1538        self.init_new_node_security_on_create(current_task, &node, "".into())?;
1539        if link_behavior == FsNodeLinkBehavior::Disallowed {
1540            node.ensure_rare_data().link_behavior.set(link_behavior).unwrap();
1541        }
1542        Ok(node)
1543    }
1544
1545    // This method does not attempt to update the atime of the node.
1546    // Use `NamespaceNode::readlink` which checks the mount flags and updates the atime accordingly.
1547    pub fn readlink(&self, current_task: &CurrentTask) -> Result<SymlinkTarget, Errno> {
1548        // Only symbolic links can be read, so other nodes fail before any access checks.
1549        if !self.is_lnk() {
1550            return error!(EINVAL);
1551        }
1552        // TODO: 378864856 - Is there a permission check here other than security checks?
1553        security::check_fs_node_read_link_access(current_task, self)?;
1554        self.ops().readlink(self, current_task)
1555    }
1556
1557    pub fn link(
1558        &self,
1559        current_task: &CurrentTask,
1560        mount: &MountInfo,
1561        name: &FsStr,
1562        child: &FsNodeHandle,
1563    ) -> Result<FsNodeHandle, Errno> {
1564        self.check_access(
1565            current_task,
1566            mount,
1567            Access::WRITE,
1568            CheckAccessReason::InternalPermissionChecks,
1569            security::Auditable::Location(std::panic::Location::caller()),
1570        )?;
1571
1572        if child.is_dir() {
1573            return error!(EPERM);
1574        }
1575
1576        if let Some(child_rare_data) = child.rare_data.get() {
1577            if matches!(child_rare_data.link_behavior.get(), Some(FsNodeLinkBehavior::Disallowed)) {
1578                return error!(ENOENT);
1579            }
1580        }
1581
1582        // Check that `current_task` has permission to create the hard link.
1583        //
1584        // See description of /proc/sys/fs/protected_hardlinks in
1585        // https://man7.org/linux/man-pages/man5/proc.5.html for details of the security
1586        // vulnerabilities.
1587        //
1588        let (child_uid, mode) = {
1589            let info = child.info();
1590            (info.uid, info.mode)
1591        };
1592        // Check that the the filesystem UID of the calling process (`current_task`) is the same as
1593        // the UID of the existing file. The check can be bypassed if the calling process has
1594        // `CAP_FOWNER` capability.
1595        if child_uid != current_task.current_creds().fsuid
1596            && !security::is_task_capable_noaudit(current_task, CAP_FOWNER)
1597        {
1598            // If current_task is not the user of the existing file, it needs to have read and write
1599            // access to the existing file.
1600            child
1601                .check_access(
1602                    current_task,
1603                    mount,
1604                    Access::READ | Access::WRITE,
1605                    CheckAccessReason::InternalPermissionChecks,
1606                    security::Auditable::Name(name),
1607                )
1608                .map_err(|e| {
1609                    // `check_access(..)` returns EACCES when the access rights doesn't match - change
1610                    // it to EPERM to match Linux standards.
1611                    if e == EACCES { errno!(EPERM) } else { e }
1612                })?;
1613            // There are also security issues that may arise when users link to setuid, setgid, or
1614            // special files.
1615            if mode.contains(FileMode::ISGID | FileMode::IXGRP) {
1616                return error!(EPERM);
1617            };
1618            if mode.contains(FileMode::ISUID) {
1619                return error!(EPERM);
1620            };
1621            if !mode.contains(FileMode::IFREG) {
1622                return error!(EPERM);
1623            };
1624        }
1625
1626        security::check_fs_node_link_access(current_task, self, child)?;
1627
1628        self.ops().link(self, current_task, name, child)?;
1629        Ok(child.clone())
1630    }
1631
1632    pub fn unlink(
1633        &self,
1634        current_task: &CurrentTask,
1635        mount: &MountInfo,
1636        name: &FsStr,
1637        child: &FsNodeHandle,
1638    ) -> Result<(), Errno> {
1639        // The user must be able to write to the directory; search permission was already
1640        // verified when looking up `child`.
1641        self.check_access(
1642            current_task,
1643            mount,
1644            Access::WRITE,
1645            CheckAccessReason::InternalPermissionChecks,
1646            security::Auditable::Name(name),
1647        )?;
1648        {
1649            let parent_info = self.info();
1650            // Safe because we acquire the parent directory lock first, and then the child lock
1651            // inside check_sticky_bit. This parent -> child acquisition follows the
1652            // hierarchical lock ordering.
1653            let _token = allow_subclass();
1654            self.check_sticky_bit(current_task, child, &parent_info)?;
1655        }
1656        if child.is_dir() {
1657            security::check_fs_node_rmdir_access(current_task, self, child, name)?;
1658        } else {
1659            security::check_fs_node_unlink_access(current_task, self, child, name)?;
1660        }
1661        self.ops().unlink(self, current_task, name, child)?;
1662        self.update_ctime_mtime();
1663        Ok(())
1664    }
1665
1666    /// Acquires a [`FileWriteGuardMode`] reservation on this node for the lifetime of the returned
1667    /// [`FileWriteGuardRef`].
1668    ///
1669    /// The internal [`FileWriteGuardState`] mutex is locked only for the duration of the counter
1670    /// update and is dropped before returning.
1671    pub fn create_write_guard(
1672        &self,
1673        mode: FileWriteGuardMode,
1674    ) -> Result<FileWriteGuardRef<'_>, Errno> {
1675        FileWriteGuardRef::new(self, mode)
1676    }
1677
1678    pub fn truncate(
1679        &self,
1680        current_task: &CurrentTask,
1681        mount: &MountInfo,
1682        length: u64,
1683    ) -> Result<(), Errno> {
1684        if self.is_dir() {
1685            return error!(EISDIR);
1686        }
1687        self.check_access(
1688            current_task,
1689            mount,
1690            Access::WRITE,
1691            CheckAccessReason::InternalPermissionChecks,
1692            security::Auditable::Location(std::panic::Location::caller()),
1693        )?;
1694
1695        // Per `truncate(2)`:
1696        // "ETXTBSY: The file is an executable file that is being executed."
1697        // And per `open(2)` (`O_TRUNC` / `ETXTBSY`), which routes truncation through here:
1698        // "ETXTBSY: pathname refers to an executable image which is currently being executed
1699        // and write access was requested."
1700        //
1701        // Hold a `FileWriteGuardMode::WriteFile` reservation for the duration of the truncation so
1702        // that truncating an actively executing file fails with `ETXTBSY`, and any concurrent
1703        // `execve(2)` (`FileWriteGuardMode::ExecMapping`) fails with `ETXTBSY` while truncation is
1704        // in flight.
1705        // `create_write_guard` drops the `write_guard_state` mutex immediately while keeping the
1706        // `WriteFile` reservation active until `_write_guard` is dropped, avoiding lock-order
1707        // inversion or self-deadlock when filesystem truncate ops lock `write_guard_state` to check
1708        // seals (e.g., `check_no_seal`).
1709        let _write_guard = self.create_write_guard(FileWriteGuardMode::WriteFile)?;
1710
1711        let guard = self.ops().append_lock_write(self, current_task)?;
1712        self.truncate_locked(&guard, current_task, length)
1713    }
1714
1715    /// Avoid calling this method directly. You probably want to call `FileObject::ftruncate()`
1716    /// which will also perform all file-descriptor based verifications.
1717    pub fn ftruncate(&self, current_task: &CurrentTask, length: u64) -> Result<(), Errno> {
1718        if self.is_dir() {
1719            // When truncating a file descriptor, if the descriptor references a directory,
1720            // return EINVAL. This is different from the truncate() syscall which returns EISDIR.
1721            //
1722            // See https://man7.org/linux/man-pages/man2/ftruncate.2.html#ERRORS
1723            return error!(EINVAL);
1724        }
1725
1726        // For ftruncate, we do not need to check that the file node is writable.
1727        //
1728        // The file object that calls this method must verify that the file was opened
1729        // with write permissions.
1730        //
1731        // This matters because a file could be opened with O_CREAT + O_RDWR + 0444 mode.
1732        // The file descriptor returned from such an operation can be truncated, even
1733        // though the file was created with a read-only mode.
1734        //
1735        // See https://man7.org/linux/man-pages/man2/ftruncate.2.html#DESCRIPTION
1736        // which says:
1737        //
1738        // "With ftruncate(), the file must be open for writing; with truncate(),
1739        // the file must be writable."
1740
1741        let guard = self.ops().append_lock_write(self, current_task)?;
1742        self.truncate_locked(&guard, current_task, length)
1743    }
1744
1745    // Called by `truncate` and `ftruncate` above.
1746    pub fn truncate_locked(
1747        &self,
1748        guard: &AppendLockWriteGuard<'_>,
1749        current_task: &CurrentTask,
1750        length: u64,
1751    ) -> Result<(), Errno> {
1752        if length > MAX_LFS_FILESIZE as u64 {
1753            return error!(EINVAL);
1754        }
1755        if length > current_task.thread_group().get_rlimit(Resource::FSIZE) {
1756            send_standard_signal(current_task, SignalInfo::kernel(SIGXFSZ));
1757            return error!(EFBIG);
1758        }
1759        self.clear_suid_and_sgid_bits(current_task)?;
1760
1761        self.ops().truncate(guard, self, current_task, length)?;
1762        self.update_ctime_mtime();
1763        Ok(())
1764    }
1765
1766    /// Avoid calling this method directly. You probably want to call `FileObject::fallocate()`
1767    /// which will also perform additional verifications.
1768    pub fn fallocate(
1769        &self,
1770        current_task: &CurrentTask,
1771        mode: FallocMode,
1772        offset: u64,
1773        length: u64,
1774    ) -> Result<(), Errno> {
1775        let guard = self.ops().append_lock_write(self, current_task)?;
1776        self.fallocate_locked(&guard, current_task, mode, offset, length)
1777    }
1778
1779    pub fn fallocate_locked(
1780        &self,
1781        guard: &AppendLockWriteGuard<'_>,
1782        current_task: &CurrentTask,
1783        mode: FallocMode,
1784        offset: u64,
1785        length: u64,
1786    ) -> Result<(), Errno> {
1787        let allocate_size = checked_add_offset_and_length(offset as usize, length as usize)
1788            .map_err(|_| errno!(EFBIG))? as u64;
1789        if allocate_size > current_task.thread_group().get_rlimit(Resource::FSIZE) {
1790            send_standard_signal(current_task, SignalInfo::kernel(SIGXFSZ));
1791            return error!(EFBIG);
1792        }
1793
1794        self.clear_suid_and_sgid_bits(current_task)?;
1795
1796        self.ops().allocate(guard, self, current_task, mode, offset, length)?;
1797        self.update_ctime_mtime();
1798        Ok(())
1799    }
1800
1801    fn update_metadata_for_child(
1802        &self,
1803        current_task: &CurrentTask,
1804        mode: &mut FileMode,
1805        owner: &mut FsCred,
1806    ) {
1807        // The setgid bit on a directory causes the gid to be inherited by new children and the
1808        // setgid bit to be inherited by new child directories. See SetgidDirTest in gvisor.
1809        {
1810            let self_info = self.info();
1811            if self_info.mode.contains(FileMode::ISGID) {
1812                owner.gid = self_info.gid;
1813                if mode.is_dir() {
1814                    *mode |= FileMode::ISGID;
1815                }
1816            }
1817        }
1818
1819        if !mode.is_dir() && mode.contains(FileMode::ISGID | FileMode::IXGRP) {
1820            // https://man7.org/linux/man-pages/man7/inode.7.html says:
1821            //
1822            //   For an executable file, the set-group-ID bit causes the
1823            //   effective group ID of a process that executes the file to change
1824            //   as described in execve(2).
1825            //
1826            // We need to check whether the current task has permission to create such a file.
1827            // See a similar check in `FsNode::chmod`.
1828            if !can_retain_sgid(current_task, owner.gid) {
1829                *mode &= !FileMode::ISGID;
1830            }
1831        }
1832    }
1833
1834    /// Checks if O_NOATIME is allowed,
1835    pub fn check_o_noatime_allowed(&self, current_task: &CurrentTask) -> Result<(), Errno> {
1836        // Per open(2),
1837        //
1838        //   O_NOATIME (since Linux 2.6.8)
1839        //      ...
1840        //
1841        //      This flag can be employed only if one of the following
1842        //      conditions is true:
1843        //
1844        //      *  The effective UID of the process matches the owner UID
1845        //         of the file.
1846        //
1847        //      *  The calling process has the CAP_FOWNER capability in
1848        //         its user namespace and the owner UID of the file has a
1849        //         mapping in the namespace.
1850        if current_task.current_creds().fsuid != self.info().uid {
1851            security::check_task_capable(current_task, CAP_FOWNER)?;
1852        }
1853        Ok(())
1854    }
1855
1856    pub fn default_check_access_impl(
1857        &self,
1858        current_task: &CurrentTask,
1859        permission_flags: security::PermissionFlags,
1860        reason: CheckAccessReason,
1861        info: LockDepReadGuard<'_, FsNodeInfo>,
1862        audit_context: Auditable<'_>,
1863    ) -> Result<(), Errno> {
1864        let (node_uid, node_gid, mode) = (info.uid, info.gid, info.mode);
1865        std::mem::drop(info);
1866        if let CheckAccessReason::ChangeTimestamps { now } = reason {
1867            // To set the timestamps to the current time the caller must either have write access to
1868            // the file, be the file owner, or hold the CAP_DAC_OVERRIDE or CAP_FOWNER capability.
1869            // To set the timestamps to other values the caller must either be the file owner or hold
1870            // the CAP_FOWNER capability.
1871            if current_task.current_creds().fsuid == node_uid {
1872                return Ok(());
1873            }
1874            if now {
1875                if security::is_task_capable_noaudit(current_task, CAP_FOWNER) {
1876                    return Ok(());
1877                }
1878            } else {
1879                security::check_task_capable(current_task, CAP_FOWNER)?;
1880                return Ok(());
1881            }
1882        }
1883        check_access(self, current_task, permission_flags, node_uid, node_gid, mode)?;
1884        security::fs_node_permission(current_task, self, permission_flags, audit_context)
1885    }
1886
1887    /// Check whether the node can be accessed in the current context with the specified access
1888    /// flags (read, write, or exec). Accounts for capabilities and whether the current user is the
1889    /// owner or is in the file's group.
1890    pub fn check_access<'a>(
1891        &self,
1892        current_task: &CurrentTask,
1893        mount: &MountInfo,
1894        access: impl Into<security::PermissionFlags>,
1895        reason: CheckAccessReason,
1896        audit_context: impl Into<security::Auditable<'a>>,
1897    ) -> Result<(), Errno> {
1898        let mut permission_flags = access.into();
1899        if permission_flags.contains(security::PermissionFlags::WRITE)
1900            && !self.info().mode.is_special()
1901        {
1902            mount.check_readonly_filesystem()?;
1903        }
1904        if permission_flags.contains(security::PermissionFlags::EXEC) && !self.is_dir() {
1905            mount.check_noexec_filesystem()?;
1906        }
1907        if reason == CheckAccessReason::Access {
1908            permission_flags |= PermissionFlags::ACCESS;
1909        }
1910        self.ops().check_access(
1911            self,
1912            current_task,
1913            permission_flags,
1914            &self.info,
1915            reason,
1916            audit_context.into(),
1917        )
1918    }
1919
1920    /// Check whether the stick bit, `S_ISVTX`, forbids the `current_task` from removing the given
1921    /// `child`. If this node has `S_ISVTX`, then either the child must be owned by the `fsuid` of
1922    /// `current_task` or `current_task` must have `CAP_FOWNER`.
1923    pub fn check_sticky_bit(
1924        &self,
1925        current_task: &CurrentTask,
1926        child: &FsNodeHandle,
1927        self_info: &FsNodeInfo,
1928    ) -> Result<(), Errno> {
1929        if self_info.mode.contains(FileMode::ISVTX)
1930            && child.info().uid != current_task.current_creds().fsuid
1931        {
1932            security::check_task_capable(current_task, CAP_FOWNER)?;
1933        }
1934        Ok(())
1935    }
1936
1937    pub fn fifo(&self, current_task: &CurrentTask) -> &PipeHandle {
1938        assert!(self.is_fifo());
1939        self.ensure_rare_data().ensure_fifo(current_task)
1940    }
1941
1942    /// Returns the UNIX domain socket bound to this node, if any.
1943    pub fn bound_socket(&self) -> Option<&SocketHandle> {
1944        if let Some(rare_data) = self.rare_data.get() { rare_data.bound_socket.get() } else { None }
1945    }
1946
1947    /// Register the provided socket as the UNIX domain socket bound to this node.
1948    ///
1949    /// It is a fatal error to call this method again if it has already been called on this node.
1950    pub fn set_bound_socket(&self, socket: SocketHandle) {
1951        assert!(self.ensure_rare_data().bound_socket.set(socket).is_ok());
1952    }
1953
1954    /// Updates node attributes and persists changes via [`FsNodeOps::update_attributes`].
1955    ///
1956    /// For directory-level attributes like `casefold` and `wrapping_key_id`, callers should
1957    /// use directory helpers (such as [`DirEntry::set_casefold`]) to synchronize child caches
1958    /// and directory locks.
1959    pub fn update_attributes<F>(&self, current_task: &CurrentTask, mutator: F) -> Result<(), Errno>
1960    where
1961        F: FnOnce(&mut FsNodeInfo) -> Result<(), Errno>,
1962    {
1963        let mut info = self.info.write();
1964        let mut new_info = info.clone();
1965        mutator(&mut new_info)?;
1966
1967        let new_access = new_info.mode.user_access()
1968            | new_info.mode.group_access()
1969            | new_info.mode.other_access();
1970
1971        if new_access.intersects(Access::EXEC) {
1972            let write_guard_state = self.write_guard_state.lock();
1973            if let Ok(seals) = write_guard_state.get_seals() {
1974                if seals.contains(SealFlags::NO_EXEC) {
1975                    return error!(EPERM);
1976                }
1977            }
1978        }
1979
1980        // `mutator`s should not update the attribute change time, which is managed by this API.
1981        assert_eq!(info.time_status_change, new_info.time_status_change);
1982        if *info == new_info {
1983            return Ok(());
1984        }
1985        new_info.time_status_change = utc::utc_now();
1986
1987        let mut has = zxio_node_attr_has_t { ..Default::default() };
1988        has.modification_time = info.time_modify != new_info.time_modify;
1989        has.access_time = info.time_access != new_info.time_access;
1990        has.mode = info.mode != new_info.mode;
1991        has.uid = info.uid != new_info.uid;
1992        has.gid = info.gid != new_info.gid;
1993        has.rdev = info.rdev != new_info.rdev;
1994        has.casefold = info.casefold != new_info.casefold;
1995        has.encryption_policy = info.encryption_policy != new_info.encryption_policy;
1996
1997        if has.casefold && !self.fs().has_casefold_support() {
1998            return error!(ENOTSUP);
1999        }
2000        security::check_fs_node_setattr_access(current_task, &self, &has)?;
2001
2002        // Call `update_attributes(..)` to persist the changes for the following fields.
2003        if has.modification_time
2004            || has.access_time
2005            || has.mode
2006            || has.uid
2007            || has.gid
2008            || has.rdev
2009            || has.casefold
2010            || has.encryption_policy
2011        {
2012            self.ops().update_attributes(self, current_task, &new_info, has)?;
2013        }
2014
2015        *info = new_info;
2016        Ok(())
2017    }
2018
2019    /// Set the permissions on this FsNode to the given values.
2020    ///
2021    /// Does not change the IFMT of the node.
2022    pub fn chmod(
2023        &self,
2024        current_task: &CurrentTask,
2025        mount: &MountInfo,
2026        mut mode: FileMode,
2027    ) -> Result<(), Errno> {
2028        mount.check_readonly_filesystem()?;
2029        self.update_attributes(current_task, |info| {
2030            if info.uid != current_task.current_creds().fsuid {
2031                security::check_task_capable(current_task, CAP_FOWNER)?;
2032            }
2033            if mode.intersects(FileMode::ISGID) && !can_retain_sgid(current_task, info.gid) {
2034                mode &= !FileMode::ISGID;
2035            }
2036            info.chmod(mode);
2037            Ok(())
2038        })
2039    }
2040
2041    /// Sets the owner and/or group on this FsNode.
2042    pub fn chown(
2043        &self,
2044        current_task: &CurrentTask,
2045        mount: &MountInfo,
2046        owner: Option<uid_t>,
2047        group: Option<gid_t>,
2048    ) -> Result<(), Errno> {
2049        mount.check_readonly_filesystem()?;
2050        self.update_attributes(current_task, |info| {
2051            if security::is_task_capable_noaudit(current_task, CAP_CHOWN) {
2052                info.chown(owner, group);
2053                return Ok(());
2054            }
2055
2056            // Nobody can change the owner.
2057            if let Some(uid) = owner {
2058                if info.uid != uid {
2059                    return error!(EPERM);
2060                }
2061            }
2062
2063            let (euid, is_in_group) = {
2064                let current_creds = current_task.current_creds();
2065                (current_creds.euid, group.map(|gid| current_creds.is_in_group(gid)))
2066            };
2067
2068            // The owner can change the group.
2069            if info.uid == euid {
2070                // To a group that it belongs.
2071                if let Some(is_in_group) = is_in_group {
2072                    if !is_in_group {
2073                        return error!(EPERM);
2074                    }
2075                }
2076                info.chown(None, group);
2077                return Ok(());
2078            }
2079
2080            // Any other user can call chown(file, -1, -1)
2081            if owner.is_some() || group.is_some() {
2082                return error!(EPERM);
2083            }
2084
2085            // But not on set-user-ID or set-group-ID files.
2086            // If we were to chown them, they would drop the set-ID bit.
2087            if info.has_suid_or_sgid_bits() {
2088                return error!(EPERM);
2089            }
2090
2091            info.chown(None, None);
2092            Ok(())
2093        })?;
2094        // From <https://man7.org/linux/man-pages/man2/chown.2.html>:
2095        //
2096        //   When the owner or group of an executable file is changed by an
2097        //   unprivileged user, the S_ISUID and S_ISGID mode bits are cleared.
2098        //   POSIX does not specify whether this also should happen when root
2099        //   does the chown(); the Linux behavior depends on the kernel version,
2100        //   and since Linux 2.2.13, root is treated like other users.
2101        //   ...
2102        //   When the owner or group of an executable file is changed (by any user),
2103        //   all capability sets for the file are cleared.
2104        self.clear_suid_and_sgid_bits(current_task)
2105    }
2106
2107    /// Forcefully change the owner and group of this node.
2108    ///
2109    /// # Safety
2110    ///
2111    /// This function skips all the security checks and just updates the owner and group. Also, does
2112    /// not check if the filesystem is read-only and does not update the attribute change time.
2113    ///
2114    /// This function is used to set the owner and group of /proc/pid to the credentials of the
2115    /// current task. Please consider carefully whether you want to use this function for another
2116    /// purpose.
2117    pub unsafe fn force_chown(&self, creds: FsCred) {
2118        self.update_info(|info| {
2119            info.chown(Some(creds.uid), Some(creds.gid));
2120        });
2121    }
2122
2123    /// Whether this node is a regular file.
2124    pub fn is_reg(&self) -> bool {
2125        self.info().mode.is_reg()
2126    }
2127
2128    /// Whether this node is a directory.
2129    pub fn is_dir(&self) -> bool {
2130        self.info().mode.is_dir()
2131    }
2132
2133    /// Whether this node is a socket.
2134    pub fn is_sock(&self) -> bool {
2135        self.info().mode.is_sock()
2136    }
2137
2138    /// Whether this node is a FIFO.
2139    pub fn is_fifo(&self) -> bool {
2140        self.info().mode.is_fifo()
2141    }
2142
2143    /// Whether this node is a symbolic link.
2144    pub fn is_lnk(&self) -> bool {
2145        self.info().mode.is_lnk()
2146    }
2147
2148    pub fn dev(&self) -> DeviceId {
2149        self.fs().dev_id
2150    }
2151
2152    pub fn stat(&self, current_task: &CurrentTask) -> Result<uapi::stat, Errno> {
2153        security::check_fs_node_getattr_access(current_task, self)?;
2154
2155        let info = self.fetch_and_refresh_info(current_task)?;
2156
2157        let time_to_kernel_timespec_pair = |t| {
2158            let timespec { tv_sec, tv_nsec } = timespec_from_time(t);
2159            let time = tv_sec.try_into().map_err(|_| errno!(EINVAL))?;
2160            let time_nsec = tv_nsec.try_into().map_err(|_| errno!(EINVAL))?;
2161            Ok((time, time_nsec))
2162        };
2163
2164        let (st_atime, st_atime_nsec) = time_to_kernel_timespec_pair(info.time_access)?;
2165        let (st_mtime, st_mtime_nsec) = time_to_kernel_timespec_pair(info.time_modify)?;
2166        let (st_ctime, st_ctime_nsec) = time_to_kernel_timespec_pair(info.time_status_change)?;
2167
2168        Ok(uapi::stat {
2169            st_dev: self.dev().bits(),
2170            st_ino: self.ino,
2171            st_nlink: info.link_count.try_into().map_err(|_| errno!(EINVAL))?,
2172            st_mode: info.mode.bits(),
2173            st_uid: info.uid,
2174            st_gid: info.gid,
2175            st_rdev: info.rdev.bits(),
2176            st_size: info.size.try_into().map_err(|_| errno!(EINVAL))?,
2177            st_blksize: info.blksize.try_into().map_err(|_| errno!(EINVAL))?,
2178            st_blocks: info.blocks.try_into().map_err(|_| errno!(EINVAL))?,
2179            st_atime,
2180            st_atime_nsec,
2181            st_mtime,
2182            st_mtime_nsec,
2183            st_ctime,
2184            st_ctime_nsec,
2185            ..Default::default()
2186        })
2187    }
2188
2189    /// Returns the current size of the file.  This is inherently racy, so any caller that
2190    /// might want to use the value returned should hold their own locks if necessary.  For
2191    /// example, if using the value here to implement append (which is the case at the time
2192    /// of writing this comment), locks must be held to prevent the file size being changed
2193    /// concurrently.
2194    // TODO(https://fxbug.dev/454730248): This is probably the wrong way to implement O_APPEND.
2195    pub fn get_size(&self, current_task: &CurrentTask) -> Result<usize, Errno> {
2196        self.ops().get_size(self, current_task)
2197    }
2198
2199    fn statx_timestamp_from_time(time: UtcInstant) -> statx_timestamp {
2200        let nanos = time.into_nanos();
2201        statx_timestamp {
2202            tv_sec: nanos / NANOS_PER_SECOND,
2203            tv_nsec: (nanos % NANOS_PER_SECOND) as u32,
2204            ..Default::default()
2205        }
2206    }
2207
2208    pub fn statx(
2209        &self,
2210        current_task: &CurrentTask,
2211        flags: StatxFlags,
2212        mask: u32,
2213    ) -> Result<statx, Errno> {
2214        security::check_fs_node_getattr_access(current_task, self)?;
2215
2216        // Ignore mask for now and fill in all of the fields.
2217        let info = self.fetch_and_refresh_info_with_flags(current_task, flags)?;
2218        if mask & STATX__RESERVED == STATX__RESERVED {
2219            return error!(EINVAL);
2220        }
2221
2222        track_stub!(TODO("https://fxbug.dev/302594110"), "statx attributes");
2223        let stx_mnt_id = 0;
2224        let mut stx_attributes = 0;
2225        let stx_attributes_mask = STATX_ATTR_VERITY as u64;
2226
2227        if matches!(*self.fsverity.lock(), FsVerityState::FsVerity) {
2228            stx_attributes |= STATX_ATTR_VERITY as u64;
2229        }
2230
2231        Ok(statx {
2232            stx_mask: STATX_NLINK
2233                | STATX_UID
2234                | STATX_GID
2235                | STATX_ATIME
2236                | STATX_MTIME
2237                | STATX_CTIME
2238                | STATX_INO
2239                | STATX_SIZE
2240                | STATX_BLOCKS
2241                | STATX_BASIC_STATS,
2242            stx_blksize: info.blksize.try_into().map_err(|_| errno!(EINVAL))?,
2243            stx_attributes,
2244            stx_nlink: info.link_count.try_into().map_err(|_| errno!(EINVAL))?,
2245            stx_uid: info.uid,
2246            stx_gid: info.gid,
2247            stx_mode: info.mode.bits().try_into().map_err(|_| errno!(EINVAL))?,
2248            stx_ino: self.ino,
2249            stx_size: info.size.try_into().map_err(|_| errno!(EINVAL))?,
2250            stx_blocks: info.blocks.try_into().map_err(|_| errno!(EINVAL))?,
2251            stx_attributes_mask,
2252            stx_ctime: Self::statx_timestamp_from_time(info.time_status_change),
2253            stx_mtime: Self::statx_timestamp_from_time(info.time_modify),
2254            stx_atime: Self::statx_timestamp_from_time(info.time_access),
2255
2256            stx_rdev_major: info.rdev.major(),
2257            stx_rdev_minor: info.rdev.minor(),
2258
2259            stx_dev_major: self.fs().dev_id.major(),
2260            stx_dev_minor: self.fs().dev_id.minor(),
2261            stx_mnt_id,
2262            ..Default::default()
2263        })
2264    }
2265
2266    /// Checks whether `current_task` has capabilities required for the specified `access` to the
2267    /// extended attribute `name`.
2268    fn check_xattr_access(
2269        &self,
2270        current_task: &CurrentTask,
2271        mount: &MountInfo,
2272        name: &FsStr,
2273        access: Access,
2274    ) -> Result<(), Errno> {
2275        assert!(access == Access::READ || access == Access::WRITE);
2276
2277        let enodata_if_read =
2278            |e: Errno| if access == Access::READ && e.code == EPERM { errno!(ENODATA) } else { e };
2279
2280        // man xattr(7) describes the different access checks applied to each extended attribute
2281        // namespace.
2282        if name.starts_with(XATTR_USER_PREFIX.to_bytes()) {
2283            {
2284                let info = self.info();
2285                if !info.mode.is_reg() && !info.mode.is_dir() {
2286                    return Err(enodata_if_read(errno!(EPERM)));
2287                }
2288            }
2289
2290            // TODO: https://fxbug.dev/460734830 - Perform capability check(s) if file has sticky
2291            // bit set.
2292
2293            self.check_access(
2294                current_task,
2295                mount,
2296                access,
2297                CheckAccessReason::InternalPermissionChecks,
2298                security::Auditable::Name(name),
2299            )?;
2300        } else if name.starts_with(XATTR_TRUSTED_PREFIX.to_bytes()) {
2301            // Trusted extended attributes require `CAP_SYS_ADMIN` to read or write.
2302            security::check_task_capable(current_task, CAP_SYS_ADMIN).map_err(enodata_if_read)?;
2303        } else if name.starts_with(XATTR_SYSTEM_PREFIX.to_bytes()) {
2304            // System extended attributes have attribute-specific access policy.
2305            // TODO: https://fxbug.dev/460734830 -  Revise how system extended attributes are
2306            // access-controlled.
2307            security::check_task_capable(current_task, CAP_SYS_ADMIN).map_err(enodata_if_read)?;
2308        } else if name.starts_with(XATTR_SECURITY_PREFIX.to_bytes()) {
2309            if access == Access::WRITE {
2310                // Writes require `CAP_SYS_ADMIN`, unless the LSM owning `name` specifies to skip.
2311                if !security::fs_node_xattr_skipcap(name) {
2312                    security::check_task_capable(current_task, CAP_SYS_ADMIN)
2313                        .map_err(enodata_if_read)?;
2314                }
2315            }
2316        } else {
2317            panic!("Unknown extended attribute prefix: {}", name);
2318        }
2319        Ok(())
2320    }
2321
2322    pub fn get_xattr(
2323        &self,
2324        current_task: &CurrentTask,
2325        mount: &MountInfo,
2326        name: &FsStr,
2327        max_size: usize,
2328    ) -> Result<ValueOrSize<FsString>, Errno> {
2329        // Perform discretionary capability & access checks appropriate to the xattr prefix.
2330        self.check_xattr_access(current_task, mount, name, Access::READ)?;
2331
2332        // LSM access checks must be performed after discretionary checks.
2333        security::check_fs_node_getxattr_access(current_task, self, name)?;
2334
2335        if name.starts_with(XATTR_SECURITY_PREFIX.to_bytes()) {
2336            // If the attribute is in the security.* domain then allow the LSM to handle the
2337            // request, or to delegate to `FsNodeOps::get_xattr()`.
2338            security::fs_node_getsecurity(current_task, self, name, max_size)
2339        } else {
2340            // If the attribute is outside security.*, delegate the read to the `FsNodeOps`.
2341            self.ops().get_xattr(self, current_task, name, max_size)
2342        }
2343    }
2344
2345    pub fn set_xattr(
2346        &self,
2347        current_task: &CurrentTask,
2348        mount: &MountInfo,
2349        name: &FsStr,
2350        value: &FsStr,
2351        op: XattrOp,
2352    ) -> Result<(), Errno> {
2353        // Perform discretionary capability & access checks appropriate to the xattr prefix.
2354        self.check_xattr_access(current_task, mount, name, Access::WRITE)?;
2355
2356        // LSM access checks must be performed after discretionary checks.
2357        security::check_fs_node_setxattr_access(current_task, self, name, value, op)?;
2358
2359        if name.starts_with(XATTR_SECURITY_PREFIX.to_bytes()) {
2360            // If the attribute is in the security.* domain then allow the LSM to handle the
2361            // request, or to delegate to `FsNodeOps::set_xattr()`.
2362            security::fs_node_setsecurity(current_task, self, name, value, op)
2363        } else {
2364            // If the attribute is outside security.*, delegate the read to the `FsNodeOps`.
2365            self.ops().set_xattr(self, current_task, name, value, op)
2366        }
2367    }
2368
2369    pub fn remove_xattr(
2370        &self,
2371        current_task: &CurrentTask,
2372        mount: &MountInfo,
2373        name: &FsStr,
2374    ) -> Result<(), Errno> {
2375        // Perform discretionary capability & access checks appropriate to the xattr prefix.
2376        self.check_xattr_access(current_task, mount, name, Access::WRITE)?;
2377
2378        // LSM access checks must be performed after discretionary checks.
2379        security::check_fs_node_removexattr_access(current_task, self, name)?;
2380        self.ops().remove_xattr(self, current_task, name)
2381    }
2382
2383    pub fn list_xattrs(
2384        &self,
2385        current_task: &CurrentTask,
2386        max_size: usize,
2387    ) -> Result<ValueOrSize<Vec<FsString>>, Errno> {
2388        security::check_fs_node_listxattr_access(current_task, self)?;
2389        Ok(self.ops().list_xattrs(self, current_task, max_size)?.map(|mut v| {
2390            // Extended attributes may be listed even if the caller would not be able to read
2391            // (or modify) the attribute's value.
2392            // trusted.* attributes are only accessible with CAP_SYS_ADMIN and are omitted by
2393            // `listxattr()` unless the caller holds CAP_SYS_ADMIN.
2394            if !security::is_task_capable_noaudit(current_task, CAP_SYS_ADMIN) {
2395                v.retain(|name| !name.starts_with(XATTR_TRUSTED_PREFIX.to_bytes()));
2396            }
2397            v
2398        }))
2399    }
2400
2401    /// Returns current `FsNodeInfo`.
2402    pub fn info(&self) -> LockDepReadGuard<'_, FsNodeInfo> {
2403        self.info.read()
2404    }
2405
2406    /// Returns a reference to the `info` lock itself.
2407    ///
2408    /// This should ONLY be used by `RenameGuard` to perform ordered write locking on independent
2409    /// nodes.
2410    pub(super) fn info_lock(&self) -> &DynamicLockDepRwLock<FsNodeInfo> {
2411        &self.info
2412    }
2413
2414    /// Refreshes the `FsNodeInfo` if necessary and returns a read guard.
2415    pub fn fetch_and_refresh_info(
2416        &self,
2417        current_task: &CurrentTask,
2418    ) -> Result<LockDepReadGuard<'_, FsNodeInfo>, Errno> {
2419        self.fetch_and_refresh_info_with_flags(current_task, StatxFlags::empty())
2420    }
2421
2422    pub fn fetch_and_refresh_info_with_flags(
2423        &self,
2424        current_task: &CurrentTask,
2425        flags: StatxFlags,
2426    ) -> Result<LockDepReadGuard<'_, FsNodeInfo>, Errno> {
2427        self.ops().fetch_and_refresh_info(self, current_task, &self.info, flags)
2428    }
2429
2430    pub fn update_info<F, T>(&self, mutator: F) -> T
2431    where
2432        F: FnOnce(&mut FsNodeInfo) -> T,
2433    {
2434        let mut info = self.info.write();
2435        mutator(&mut info)
2436    }
2437
2438    /// Clears the `S_ISUID` and `S_ISGID` mode bits (unless `current_task` has [`CAP_FSETID`]),
2439    /// and removes any `security.capability` extended attribute.
2440    pub fn clear_suid_and_sgid_bits(&self, current_task: &CurrentTask) -> Result<(), Errno> {
2441        // Clear `S_ISUID` and `S_ISGID` before removing `security.capability` so that a
2442        // SUID-root binary whose capabilities are restricted by `security.capability` cannot
2443        // be observed with `S_ISUID` still set after `security.capability` is removed.
2444        //
2445        // From <https://man7.org/linux/man-pages/man7/capabilities.7.html>:
2446        //
2447        //   CAP_FSETID
2448        //          •  Don't clear set-user-ID and set-group-ID mode bits when a
2449        //             file is modified;
2450        if self.info().has_suid_or_sgid_bits()
2451            && !security::is_task_capable_noaudit(current_task, CAP_FSETID)
2452        {
2453            self.update_attributes(current_task, |info| {
2454                info.clear_suid_and_sgid_bits();
2455                Ok(())
2456            })?;
2457        }
2458
2459        // Always clear `security.capability` when file contents or ownership are modified,
2460        // regardless of `CAP_FSETID`.
2461        if security::fs_node_needs_killpriv(current_task, self)? {
2462            security::fs_node_killpriv(current_task, self)?;
2463        }
2464        Ok(())
2465    }
2466
2467    /// Update the ctime and mtime of a file to now.
2468    pub fn update_ctime_mtime(&self) {
2469        if self.fs().manages_timestamps() {
2470            return;
2471        }
2472        self.update_info(|info| {
2473            let now = utc::utc_now();
2474            info.time_status_change = now;
2475            info.time_modify = now;
2476        });
2477    }
2478
2479    /// Update the ctime of a file to now.
2480    pub fn update_ctime(&self) {
2481        if self.fs().manages_timestamps() {
2482            return;
2483        }
2484        self.update_info(|info| {
2485            let now = utc::utc_now();
2486            info.time_status_change = now;
2487        });
2488    }
2489
2490    /// Update the atime and mtime if the `current_task` has write access, is the file owner, or
2491    /// holds either the CAP_DAC_OVERRIDE or CAP_FOWNER capability.
2492    pub fn update_atime_mtime(
2493        &self,
2494        current_task: &CurrentTask,
2495        mount: &MountInfo,
2496        atime: TimeUpdateType,
2497        mtime: TimeUpdateType,
2498    ) -> Result<(), Errno> {
2499        // If the filesystem is read-only, this always fail.
2500        mount.check_readonly_filesystem()?;
2501
2502        let now = matches!((atime, mtime), (TimeUpdateType::Now, TimeUpdateType::Now));
2503        self.check_access(
2504            current_task,
2505            mount,
2506            Access::WRITE,
2507            CheckAccessReason::ChangeTimestamps { now },
2508            security::Auditable::Location(std::panic::Location::caller()),
2509        )?;
2510
2511        if !matches!((atime, mtime), (TimeUpdateType::Omit, TimeUpdateType::Omit)) {
2512            // This function is called by `utimes(..)` which will update the access and
2513            // modification time. We need to call `update_attributes()` to update the mtime of
2514            // filesystems that manages file timestamps.
2515            self.update_attributes(current_task, |info| {
2516                let now = utc::utc_now();
2517                let get_time = |time: TimeUpdateType| match time {
2518                    TimeUpdateType::Now => Some(now),
2519                    TimeUpdateType::Time(t) => Some(t),
2520                    TimeUpdateType::Omit => None,
2521                };
2522                if let Some(time) = get_time(atime) {
2523                    info.time_access = time;
2524                }
2525                if let Some(time) = get_time(mtime) {
2526                    info.time_modify = time;
2527                }
2528                Ok(())
2529            })?;
2530        }
2531        Ok(())
2532    }
2533
2534    /// The key used to identify this node in the file system's node cache.
2535    ///
2536    /// For many file systems, this will be the same as the inode number. However, some file
2537    /// systems, such as FUSE, sometimes use different `node_key` and inode numbers.
2538    pub fn node_key(&self) -> ino_t {
2539        self.ops().node_key(self)
2540    }
2541
2542    fn ensure_rare_data(&self) -> &FsNodeRareData {
2543        self.rare_data.get_or_init(|| Box::new(FsNodeRareData::default()))
2544    }
2545
2546    /// Returns the set of watchers for this node.
2547    ///
2548    /// Only call this function if you require this node to actually store a list of watchers. If
2549    /// you just wish to notify any watchers that might exist, please use `notify` instead.
2550    pub fn ensure_watchers(&self) -> &inotify_hook::InotifyWatchers {
2551        &self.ensure_rare_data().watchers
2552    }
2553
2554    /// Notify the watchers of the given event.
2555    pub fn notify(
2556        &self,
2557        event_mask: InotifyMask,
2558        cookie: u32,
2559        name: &FsStr,
2560        mode: FileMode,
2561        is_dead: bool,
2562    ) {
2563        if let Some(rare_data) = self.rare_data.get() {
2564            let kernel = self.fs().kernel.upgrade().expect("kernel is dead");
2565            if let Some(hook) = kernel.expando.peek::<Arc<dyn inotify_hook::NotifyHook>>() {
2566                hook.notify(&rare_data.watchers, event_mask, cookie, name, mode, is_dead);
2567            }
2568        }
2569    }
2570
2571    /// Calls through to the filesystem to enable fs-verity on this file.
2572    pub fn enable_fsverity(
2573        &self,
2574        current_task: &CurrentTask,
2575        descriptor: &fsverity_descriptor,
2576    ) -> Result<(), Errno> {
2577        self.ops().enable_fsverity(self, current_task, descriptor)
2578    }
2579}
2580
2581impl std::fmt::Debug for FsNode {
2582    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2583        f.debug_struct("FsNode")
2584            .field("fs", &self.fs().name())
2585            .field("info", &*self.info())
2586            .field("ops_ty", &self.ops().type_name())
2587            .finish()
2588    }
2589}
2590
2591impl Releasable for FsNode {
2592    type Context<'a> = &'a CurrentTask;
2593
2594    fn release<'a>(self, context: &'a CurrentTask) {
2595        let current_task = context;
2596        if let Some(fs) = self.fs.upgrade() {
2597            fs.remove_node(&self);
2598        }
2599        if let Err(err) = self.ops.forget(current_task, self.info.into_inner()) {
2600            log_error!("Error on FsNodeOps::forget: {err:?}");
2601        }
2602    }
2603}
2604
2605/// Returns whether the `current_task` may set (or keep) the setgid bit on a file with group `gid`.
2606///
2607/// This is the case if `gid` is the task's fsgid or one of its supplementary groups, or if the
2608/// task has `CAP_FSETID`. Note that the egid is intentionally not considered.
2609fn can_retain_sgid(current_task: &CurrentTask, gid: gid_t) -> bool {
2610    let in_group = {
2611        let current_creds = current_task.current_creds();
2612        gid == current_creds.fsgid || current_creds.groups.contains(&gid)
2613    };
2614    in_group || security::check_task_capable(current_task, CAP_FSETID).is_ok()
2615}
2616
2617fn check_access(
2618    fs_node: &FsNode,
2619    current_task: &CurrentTask,
2620    permission_flags: security::PermissionFlags,
2621    node_uid: uid_t,
2622    node_gid: gid_t,
2623    mode: FileMode,
2624) -> Result<(), Errno> {
2625    // Determine which of the access bits apply to the `current_task`.
2626    let (fsuid, is_in_group) = {
2627        let current_creds = current_task.current_creds();
2628        (current_creds.fsuid, current_creds.is_in_group(node_gid))
2629    };
2630    let granted = if fsuid == node_uid {
2631        mode.user_access()
2632    } else if is_in_group {
2633        mode.group_access()
2634    } else {
2635        mode.other_access()
2636    };
2637
2638    let access = permission_flags.as_access();
2639    if granted.contains(access) {
2640        return Ok(());
2641    }
2642
2643    // Callers with CAP_DAC_READ_SEARCH override can read files & directories, and traverse
2644    // directories to which they lack permission.
2645    let mut requested = access & !granted;
2646
2647    // If this check was triggered by `access()`, or a variant, then check for a `dontaudit`
2648    // statement for the `audit_access` permission for this caller & file.
2649    let have_dont_audit = OnceBool::new();
2650    let has_capability = move |current_task, capability| {
2651        let dont_audit = have_dont_audit.get_or_init(|| {
2652            permission_flags.contains(PermissionFlags::ACCESS)
2653                && security::has_dontaudit_access(current_task, fs_node)
2654        });
2655        if dont_audit {
2656            security::is_task_capable_noaudit(current_task, capability)
2657        } else {
2658            security::check_task_capable(current_task, capability).is_ok()
2659        }
2660    };
2661
2662    // CAP_DAC_READ_SEARCH allows bypass of read checks, and directory traverse (eXecute) checks.
2663    let dac_read_search_access =
2664        if mode.is_dir() { Access::READ | Access::EXEC } else { Access::READ };
2665    if dac_read_search_access.intersects(requested)
2666        && has_capability(current_task, CAP_DAC_READ_SEARCH)
2667    {
2668        requested.remove(dac_read_search_access);
2669    }
2670    if requested.is_empty() {
2671        return Ok(());
2672    }
2673
2674    // CAP_DAC_OVERRIDE allows bypass of all checks (though see the comment for file-execute).
2675    let mut dac_override_access = Access::READ | Access::WRITE;
2676    dac_override_access |= if mode.is_dir() {
2677        Access::EXEC
2678    } else {
2679        // File execute access checks may not be bypassed unless at least one executable bit is set.
2680        (mode.user_access() | mode.group_access() | mode.other_access()) & Access::EXEC
2681    };
2682    if dac_override_access.intersects(requested) && has_capability(current_task, CAP_DAC_OVERRIDE) {
2683        requested.remove(dac_override_access);
2684    }
2685    if requested.is_empty() {
2686        return Ok(());
2687    }
2688
2689    return error!(EACCES);
2690}
2691
2692#[cfg(test)]
2693mod tests {
2694    use super::*;
2695    use crate::device::mem::mem_device_init;
2696    use crate::testing::*;
2697    use crate::vfs::buffers::VecOutputBuffer;
2698    use starnix_uapi::auth::Credentials;
2699    use starnix_uapi::file_mode::mode;
2700
2701    #[::fuchsia::test]
2702    async fn open_device_file() {
2703        spawn_kernel_and_run(async |current_task| {
2704            mem_device_init(current_task.kernel()).expect("mem_device_init");
2705
2706            // Create a device file that points to the `zero` device (which is automatically
2707            // registered in the kernel).
2708            current_task
2709                .fs()
2710                .root()
2711                .create_node(&current_task, "zero".into(), mode!(IFCHR, 0o666), DeviceId::ZERO)
2712                .expect("create_node");
2713
2714            const CONTENT_LEN: usize = 10;
2715            let mut buffer = VecOutputBuffer::new(CONTENT_LEN);
2716
2717            // Read from the zero device.
2718            let device_file =
2719                current_task.open_file("zero".into(), OpenFlags::RDONLY).expect("open device file");
2720            device_file.read(&current_task, &mut buffer).expect("read from zero");
2721
2722            // Assert the contents.
2723            assert_eq!(&[0; CONTENT_LEN], buffer.data());
2724        })
2725        .await;
2726    }
2727
2728    #[::fuchsia::test]
2729    async fn node_info_is_reflected_in_stat() {
2730        spawn_kernel_and_run(async |current_task| {
2731            // Create a node.
2732            let node = &current_task
2733                .fs()
2734                .root()
2735                .create_node(&current_task, "zero".into(), FileMode::IFCHR, DeviceId::ZERO)
2736                .expect("create_node")
2737                .entry
2738                .node;
2739            node.update_info(|info| {
2740                info.mode = FileMode::IFSOCK;
2741                info.size = 1;
2742                info.blocks = 2;
2743                info.blksize = 4;
2744                info.uid = 9;
2745                info.gid = 10;
2746                info.link_count = 11;
2747                info.time_status_change = UtcInstant::from_nanos(1);
2748                info.time_access = UtcInstant::from_nanos(2);
2749                info.time_modify = UtcInstant::from_nanos(3);
2750                info.rdev = DeviceId::new(13, 13);
2751            });
2752            let stat = node.stat(&current_task).expect("stat");
2753
2754            assert_eq!(stat.st_mode, FileMode::IFSOCK.bits());
2755            assert_eq!(stat.st_size, 1);
2756            assert_eq!(stat.st_blksize, 4);
2757            assert_eq!(stat.st_blocks, 2);
2758            assert_eq!(stat.st_uid, 9);
2759            assert_eq!(stat.st_gid, 10);
2760            assert_eq!(stat.st_nlink, 11);
2761            assert_eq!(stat.st_ctime, 0);
2762            assert_eq!(stat.st_ctime_nsec, 1);
2763            assert_eq!(stat.st_atime, 0);
2764            assert_eq!(stat.st_atime_nsec, 2);
2765            assert_eq!(stat.st_mtime, 0);
2766            assert_eq!(stat.st_mtime_nsec, 3);
2767            assert_eq!(stat.st_rdev, DeviceId::new(13, 13).bits());
2768        })
2769        .await;
2770    }
2771
2772    #[::fuchsia::test]
2773    fn test_flock_operation() {
2774        assert!(FlockOperation::from_flags(0).is_err());
2775        assert!(FlockOperation::from_flags(u32::MAX).is_err());
2776
2777        let operation1 = FlockOperation::from_flags(LOCK_SH).expect("from_flags");
2778        assert!(!operation1.is_unlock());
2779        assert!(!operation1.is_lock_exclusive());
2780        assert!(operation1.is_blocking());
2781
2782        let operation2 = FlockOperation::from_flags(LOCK_EX | LOCK_NB).expect("from_flags");
2783        assert!(!operation2.is_unlock());
2784        assert!(operation2.is_lock_exclusive());
2785        assert!(!operation2.is_blocking());
2786
2787        let operation3 = FlockOperation::from_flags(LOCK_UN).expect("from_flags");
2788        assert!(operation3.is_unlock());
2789        assert!(!operation3.is_lock_exclusive());
2790        assert!(operation3.is_blocking());
2791    }
2792
2793    #[::fuchsia::test]
2794    async fn test_check_access() {
2795        spawn_kernel_and_run(async |current_task| {
2796            let mut creds = Credentials::with_ids(1, 2);
2797            creds.groups = vec![3, 4];
2798            current_task.set_creds(creds);
2799
2800            // Create a node.
2801            let node = &current_task
2802                .fs()
2803                .root()
2804                .create_node(&current_task, "foo".into(), FileMode::IFREG, DeviceId::NONE)
2805                .expect("create_node")
2806                .entry
2807                .node;
2808            let check_access = |uid: uid_t, gid: gid_t, perm: u32, access: Access| {
2809                node.update_info(|info| {
2810                    info.mode = mode!(IFREG, perm);
2811                    info.uid = uid;
2812                    info.gid = gid;
2813                });
2814                node.check_access(
2815                    &current_task,
2816                    &MountInfo::detached(),
2817                    access,
2818                    CheckAccessReason::InternalPermissionChecks,
2819                    security::Auditable::Location(std::panic::Location::caller()),
2820                )
2821            };
2822
2823            assert_eq!(check_access(0, 0, 0o700, Access::EXEC), error!(EACCES));
2824            assert_eq!(check_access(0, 0, 0o700, Access::READ), error!(EACCES));
2825            assert_eq!(check_access(0, 0, 0o700, Access::WRITE), error!(EACCES));
2826
2827            assert_eq!(check_access(0, 0, 0o070, Access::EXEC), error!(EACCES));
2828            assert_eq!(check_access(0, 0, 0o070, Access::READ), error!(EACCES));
2829            assert_eq!(check_access(0, 0, 0o070, Access::WRITE), error!(EACCES));
2830
2831            assert_eq!(check_access(0, 0, 0o007, Access::EXEC), Ok(()));
2832            assert_eq!(check_access(0, 0, 0o007, Access::READ), Ok(()));
2833            assert_eq!(check_access(0, 0, 0o007, Access::WRITE), Ok(()));
2834
2835            assert_eq!(check_access(1, 0, 0o700, Access::EXEC), Ok(()));
2836            assert_eq!(check_access(1, 0, 0o700, Access::READ), Ok(()));
2837            assert_eq!(check_access(1, 0, 0o700, Access::WRITE), Ok(()));
2838
2839            assert_eq!(check_access(1, 0, 0o100, Access::EXEC), Ok(()));
2840            assert_eq!(check_access(1, 0, 0o100, Access::READ), error!(EACCES));
2841            assert_eq!(check_access(1, 0, 0o100, Access::WRITE), error!(EACCES));
2842
2843            assert_eq!(check_access(1, 0, 0o200, Access::EXEC), error!(EACCES));
2844            assert_eq!(check_access(1, 0, 0o200, Access::READ), error!(EACCES));
2845            assert_eq!(check_access(1, 0, 0o200, Access::WRITE), Ok(()));
2846
2847            assert_eq!(check_access(1, 0, 0o400, Access::EXEC), error!(EACCES));
2848            assert_eq!(check_access(1, 0, 0o400, Access::READ), Ok(()));
2849            assert_eq!(check_access(1, 0, 0o400, Access::WRITE), error!(EACCES));
2850
2851            assert_eq!(check_access(0, 2, 0o700, Access::EXEC), error!(EACCES));
2852            assert_eq!(check_access(0, 2, 0o700, Access::READ), error!(EACCES));
2853            assert_eq!(check_access(0, 2, 0o700, Access::WRITE), error!(EACCES));
2854
2855            assert_eq!(check_access(0, 2, 0o070, Access::EXEC), Ok(()));
2856            assert_eq!(check_access(0, 2, 0o070, Access::READ), Ok(()));
2857            assert_eq!(check_access(0, 2, 0o070, Access::WRITE), Ok(()));
2858
2859            assert_eq!(check_access(0, 3, 0o070, Access::EXEC), Ok(()));
2860            assert_eq!(check_access(0, 3, 0o070, Access::READ), Ok(()));
2861            assert_eq!(check_access(0, 3, 0o070, Access::WRITE), Ok(()));
2862        })
2863        .await;
2864    }
2865
2866    #[::fuchsia::test]
2867    async fn set_security_xattr_fails_without_security_module_or_root() {
2868        spawn_kernel_and_run(async |current_task| {
2869            let mut creds = Credentials::with_ids(1, 2);
2870            creds.groups = vec![3, 4];
2871            current_task.set_creds(creds);
2872
2873            // Create a node.
2874            let node = &current_task
2875                .fs()
2876                .root()
2877                .create_node(&current_task, "foo".into(), FileMode::IFREG, DeviceId::NONE)
2878                .expect("create_node")
2879                .entry
2880                .node;
2881
2882            // Give read-write-execute access.
2883            node.update_info(|info| info.mode = mode!(IFREG, 0o777));
2884
2885            // Without a security module, and without CAP_SYS_ADMIN capabilities, setting the xattr
2886            // should fail.
2887            assert_eq!(
2888                node.set_xattr(
2889                    &current_task,
2890                    &MountInfo::detached(),
2891                    "security.name".into(),
2892                    "security_label".into(),
2893                    XattrOp::Create,
2894                ),
2895                error!(EPERM)
2896            );
2897        })
2898        .await;
2899    }
2900
2901    #[::fuchsia::test]
2902    async fn set_non_user_xattr_fails_without_security_module_or_root() {
2903        spawn_kernel_and_run(async |current_task| {
2904            let mut creds = Credentials::with_ids(1, 2);
2905            creds.groups = vec![3, 4];
2906            current_task.set_creds(creds);
2907
2908            // Create a node.
2909            let node = &current_task
2910                .fs()
2911                .root()
2912                .create_node(&current_task, "foo".into(), FileMode::IFREG, DeviceId::NONE)
2913                .expect("create_node")
2914                .entry
2915                .node;
2916
2917            // Give read-write-execute access.
2918            node.update_info(|info| info.mode = mode!(IFREG, 0o777));
2919
2920            // Without a security module, and without CAP_SYS_ADMIN capabilities, setting the xattr
2921            // should fail.
2922            assert_eq!(
2923                node.set_xattr(
2924                    &current_task,
2925                    &MountInfo::detached(),
2926                    "trusted.name".into(),
2927                    "some data".into(),
2928                    XattrOp::Create,
2929                ),
2930                error!(EPERM)
2931            );
2932        })
2933        .await;
2934    }
2935
2936    #[::fuchsia::test]
2937    async fn get_security_xattr_succeeds_without_read_access() {
2938        spawn_kernel_and_run(async |current_task| {
2939            let mut creds = Credentials::with_ids(1, 2);
2940            creds.groups = vec![3, 4];
2941            current_task.set_creds(creds);
2942
2943            // Create a node.
2944            let node = &current_task
2945                .fs()
2946                .root()
2947                .create_node(&current_task, "foo".into(), FileMode::IFREG, DeviceId::NONE)
2948                .expect("create_node")
2949                .entry
2950                .node;
2951
2952            // Only give read access to the root and give root access to the current task.
2953            node.update_info(|info| info.mode = mode!(IFREG, 0o100));
2954            current_task.set_creds(Credentials::with_ids(0, 0));
2955
2956            // Setting the label should succeed even without write access to the file.
2957            assert_eq!(
2958                node.set_xattr(
2959                    &current_task,
2960                    &MountInfo::detached(),
2961                    "security.name".into(),
2962                    "security_label".into(),
2963                    XattrOp::Create,
2964                ),
2965                Ok(())
2966            );
2967
2968            // Remove root access from the current task.
2969            current_task.set_creds(Credentials::with_ids(1, 1));
2970
2971            // Getting the label should succeed even without read access to the file.
2972            assert_eq!(
2973                node.get_xattr(&current_task, &MountInfo::detached(), "security.name".into(), 4096),
2974                Ok(ValueOrSize::Value("security_label".into()))
2975            );
2976        })
2977        .await;
2978    }
2979
2980    #[fuchsia::test]
2981    async fn test_casefold_not_supported_by_default() {
2982        spawn_kernel_and_run(async |current_task| {
2983            let file_node = &current_task
2984                .fs()
2985                .root()
2986                .create_node(&current_task, "foo".into(), FileMode::IFREG, DeviceId::NONE)
2987                .expect("create_node")
2988                .entry;
2989
2990            assert!(!file_node.node.fs().has_casefold_support());
2991            assert_eq!(
2992                file_node.node.update_attributes(&current_task, |info| {
2993                    info.casefold = true;
2994                    Ok(())
2995                }),
2996                error!(ENOTSUP)
2997            );
2998            // Calling set_casefold on a regular file returns Ok(()) when casefold is already false,
2999            // and ENOTDIR when attempting to enable casefolding.
3000            assert_eq!(file_node.set_casefold(&current_task, false), Ok(()));
3001            assert_eq!(file_node.set_casefold(&current_task, true), error!(ENOTDIR));
3002
3003            // Calling set_casefold on a directory in an unsupported filesystem returns ENOTSUP.
3004            let dir_entry = &current_task
3005                .fs()
3006                .root()
3007                .create_node(&current_task, "dir".into(), FileMode::IFDIR, DeviceId::NONE)
3008                .expect("create_dir")
3009                .entry;
3010            assert_eq!(dir_entry.set_casefold(&current_task, true), error!(ENOTSUP));
3011            assert_eq!(dir_entry.set_casefold(&current_task, false), Ok(()));
3012        })
3013        .await;
3014    }
3015}