Skip to main content

starnix_core/vfs/
namespace.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::security;
6use crate::task::{
7    CurrentTask, EventHandler, Kernel, MountsWriteToken, Task, WaitCanceler, Waiter,
8    register_delayed_call,
9};
10use crate::time::utc;
11use crate::vfs::fs_registry::FsRegistry;
12use crate::vfs::pseudo::dynamic_file::{DynamicFile, DynamicFileBuf, DynamicFileSource};
13use crate::vfs::pseudo::simple_file::SimpleFileNode;
14use crate::vfs::socket::{SocketAddress, SocketHandle, UnixSocket};
15use crate::vfs::{
16    CheckAccessReason, DirEntry, DirEntryHandle, FileHandle, FileObject, FileOps, FileSystemHandle,
17    FileSystemOptions, FileWriteGuardMode, FsContext, FsNode, FsNodeHandle, FsNodeOps, FsStr,
18    FsString, PathBuilder, RenameFlags, SymlinkTarget, UnlinkKind, fileops_impl_dataless,
19    fileops_impl_delegate_read_write_and_seek, fileops_impl_nonseekable, fileops_impl_noop_sync,
20    fs_node_impl_not_dir,
21};
22use fuchsia_rcu::{RcuBox, RcuReadScope};
23use fuchsia_rcu_collections::rcu_raw_hash_map::RcuRawHashMap;
24use ref_cast::RefCast;
25use starnix_logging::log_warn;
26use starnix_rcu::RcuHashMap;
27use starnix_sync::{LockDepMutex, NamespaceFlagsLock};
28use starnix_uapi::arc_key::{ArcKey, PtrKey, WeakKey};
29use starnix_uapi::auth::Credentials;
30use starnix_uapi::device_id::DeviceId;
31use starnix_uapi::errors::Errno;
32use starnix_uapi::file_mode::{AccessCheck, FileMode};
33use starnix_uapi::inotify_mask::InotifyMask;
34use starnix_uapi::mount_flags::{
35    AtomicMountpointFlags, FileSystemFlags, MountFlags, MountpointFlags,
36};
37use starnix_uapi::open_flags::OpenFlags;
38use starnix_uapi::unmount_flags::UnmountFlags;
39use starnix_uapi::vfs::{FdEvents, ResolveFlags};
40use starnix_uapi::{NAME_MAX, errno, error};
41use std::borrow::Borrow;
42use std::collections::HashSet;
43use std::fmt;
44use std::hash::{Hash, Hasher};
45use std::ops::{Deref, DerefMut};
46use std::sync::atomic::Ordering;
47use std::sync::{Arc, Weak};
48
49/// A mount namespace.
50///
51/// The namespace records at which entries filesystems are mounted.
52#[derive(Debug)]
53pub struct Namespace {
54    root_mount: MountHandle,
55
56    // Unique ID of this namespace.
57    pub id: u64,
58}
59
60impl Namespace {
61    pub fn new(fs: FileSystemHandle) -> Arc<Namespace> {
62        Self::new_with_flags(fs, MountpointFlags::empty())
63    }
64
65    pub fn new_with_flags(fs: FileSystemHandle, flags: MountpointFlags) -> Arc<Namespace> {
66        let kernel = fs.kernel.upgrade().expect("can't create namespace without a kernel");
67        let mounts_guard = kernel.mounts_lock();
68
69        let root_mount = Mount::new(&mounts_guard, WhatToMount::Fs(fs), flags)
70            .expect("creating root mount for new filesystem");
71        Arc::new(Self { root_mount, id: kernel.get_next_namespace_id() })
72    }
73
74    pub fn root(&self) -> NamespaceNode {
75        self.root_mount.root()
76    }
77
78    pub fn kernel(&self) -> Arc<Kernel> {
79        self.root_mount.kernel()
80    }
81
82    pub fn clone_namespace(&self, mounts_guard: &MountsWriteToken) -> Arc<Namespace> {
83        Arc::new(Self {
84            root_mount: self.root_mount.clone_mount_recursive(mounts_guard),
85            id: self.kernel().get_next_namespace_id(),
86        })
87    }
88
89    /// Assuming new_ns is a clone of the namespace that node is from, return the equivalent of
90    /// node in new_ns. If this assumption is violated, returns None.
91    pub fn translate_node(
92        mut node: NamespaceNode,
93        new_ns: &Namespace,
94        _mounts_guard: &MountsWriteToken,
95    ) -> Option<NamespaceNode> {
96        // Collect the list of mountpoints that leads to this node's mount
97        let mut mountpoints = vec![];
98        let mut mount = node.mount;
99        while let Some(mountpoint) = mount.as_ref().and_then(|m| m.mountpoint()) {
100            mountpoints.push(mountpoint.entry);
101            mount = mountpoint.mount;
102        }
103
104        // Follow the same path in the new namespace
105        let scope = RcuReadScope::new();
106        let mut mount = &new_ns.root_mount;
107        for mountpoint in mountpoints.iter().rev() {
108            let next_mount =
109                &mount.relations.get_submount(&scope, ArcKey::ref_cast(mountpoint))?.mount;
110            mount = next_mount;
111        }
112        node.mount = Some(Arc::clone(mount)).into();
113        Some(node)
114    }
115}
116
117impl FsNodeOps for Arc<Namespace> {
118    fs_node_impl_not_dir!();
119
120    fn create_file_ops(
121        &self,
122        _node: &FsNode,
123        _current_task: &CurrentTask,
124        _flags: OpenFlags,
125    ) -> Result<Box<dyn FileOps>, Errno> {
126        Ok(Box::new(MountNamespaceFile(self.clone())))
127    }
128}
129
130pub struct MountNamespaceFile(pub Arc<Namespace>);
131
132impl FileOps for MountNamespaceFile {
133    fileops_impl_nonseekable!();
134    fileops_impl_dataless!();
135    fileops_impl_noop_sync!();
136}
137
138/// An empty struct that we use to track the number of active clients for a mount.
139///
140/// Each active client takes a reference to this object. The unmount operation fails
141/// if there are any active clients of the mount.
142type MountClientMarker = Arc<()>;
143
144/// An instance of a filesystem mounted in a namespace.
145///
146/// At a mount, path traversal switches from one filesystem to another.
147/// The client sees a composed directory structure that glues together the
148/// directories from the underlying FsNodes from those filesystems.
149///
150/// The mounts in a namespace form a mount tree, with `mountpoint` pointing to the parent and
151/// `submounts` pointing to the children.
152pub struct Mount {
153    root: DirEntryHandle,
154    fs: FileSystemHandle,
155
156    /// Holds the flags specific to this mount of the underlying filesystem.
157    flags: AtomicMountpointFlags,
158
159    /// Lock used to serialize updates of `flags` to ensure consistency during remount operations.
160    flags_lock: LockDepMutex<(), NamespaceFlagsLock>,
161
162    /// A unique identifier for this mount reported in /proc/pid/mountinfo.
163    id: u64,
164
165    /// A count of the number of active clients.
166    active_client_counter: MountClientMarker,
167
168    /// The namespace node that this mount is mounted on. This is a tuple instead of a
169    /// NamespaceNode because the Mount pointer has to be weak because this is the pointer to the
170    /// parent mount, the parent has a pointer to the children too, and making both strong would be
171    /// a cycle.
172    /// Stores the relationships to other mounts (mountpoint and submounts).
173    /// Both require the `MountsWriteToken` to mutate.
174    relations: MountRelations,
175    // Mount used to contain a Weak<Namespace>. It no longer does because since the mount point
176    // hash was moved from Namespace to Mount, nothing actually uses it. Now that
177    // Namespace::clone_namespace() is implemented in terms of Mount::clone_mount_recursive, it
178    // won't be trivial to add it back. If you end up needing to find a Mount's Namespace, I
179    // recommend turning the mountpoint field into an enum of Mountpoint or Namespace, maybe called
180    // "parent", and then you can traverse up to the top of the tree.
181}
182type MountHandle = Arc<Mount>;
183
184/// Public representation of the mount options.
185#[derive(Clone, Debug)]
186pub struct MountInfo {
187    handle: Option<MountHandle>,
188}
189
190impl MountInfo {
191    /// `MountInfo` for a element that is not tied to a given mount. Mount flags will be considered
192    /// empty.
193    pub fn detached() -> Self {
194        None.into()
195    }
196
197    /// The mount flags of the represented mount.
198    pub fn flags(&self) -> MountFlags {
199        if let Some(handle) = &self.handle {
200            handle.flags()
201        } else {
202            // Consider not mounted node have the NOATIME flags.
203            MountFlags::NOATIME
204        }
205    }
206
207    /// Checks whether this `MountInfo` represents a writable file system mount.
208    pub fn check_readonly_filesystem(&self) -> Result<(), Errno> {
209        if self.flags().contains(MountFlags::RDONLY) {
210            return error!(EROFS);
211        }
212        Ok(())
213    }
214
215    /// Checks whether this `MountInfo` represents an executable file system mount.
216    pub fn check_noexec_filesystem(&self) -> Result<(), Errno> {
217        if self.flags().contains(MountFlags::NOEXEC) {
218            return error!(EACCES);
219        }
220        Ok(())
221    }
222}
223
224impl Deref for MountInfo {
225    type Target = Option<MountHandle>;
226
227    fn deref(&self) -> &Self::Target {
228        &self.handle
229    }
230}
231
232impl DerefMut for MountInfo {
233    fn deref_mut(&mut self) -> &mut Self::Target {
234        &mut self.handle
235    }
236}
237
238impl std::cmp::PartialEq for MountInfo {
239    fn eq(&self, other: &Self) -> bool {
240        self.handle.as_ref().map(Arc::as_ptr) == other.handle.as_ref().map(Arc::as_ptr)
241    }
242}
243
244impl std::cmp::Eq for MountInfo {}
245
246impl Into<MountInfo> for Option<MountHandle> {
247    fn into(self) -> MountInfo {
248        MountInfo { handle: self }
249    }
250}
251
252#[derive(Default)]
253struct MountRelations {
254    /// The parent mount and the directory entry in the parent where this mount is mounted.
255    mountpoint: RcuBox<Option<(Weak<Mount>, DirEntryHandle)>>,
256    /// The active submounts, keyed by the directory entry in this mount where they are mounted.
257    submounts: RcuRawHashMap<ArcKey<DirEntry>, Arc<Submount>>,
258    /// The membership of this mount in its peer group.
259    peer_group: RcuBox<Option<(Arc<PeerGroup>, PtrKey<Mount>)>>,
260    /// The membership of this mount in a PeerGroup's downstream.
261    upstream: RcuBox<Option<(Weak<PeerGroup>, PtrKey<Mount>)>>,
262}
263
264impl MountRelations {
265    fn get_submount<'a>(
266        &'a self,
267        scope: &'a starnix_rcu::RcuReadScope,
268        key: &ArcKey<DirEntry>,
269    ) -> Option<&'a Arc<Submount>> {
270        self.submounts.get(scope, key)
271    }
272
273    fn insert_submount(
274        &self,
275        _guard: &MountsWriteToken,
276        key: ArcKey<DirEntry>,
277        value: Arc<Submount>,
278    ) -> Option<Arc<Submount>> {
279        let scope = starnix_rcu::RcuReadScope::new();
280        // SAFETY: The MountsWriteToken proves we have exclusive write access.
281        let result = unsafe { self.submounts.insert(&scope, key, value) };
282        match result {
283            fuchsia_rcu_collections::rcu_raw_hash_map::InsertionResult::Inserted(_) => None,
284            fuchsia_rcu_collections::rcu_raw_hash_map::InsertionResult::Updated(old) => Some(old),
285        }
286    }
287
288    fn remove_submount(
289        &self,
290        guard: &MountsWriteToken,
291        key: &ArcKey<DirEntry>,
292    ) -> Result<(), Errno> {
293        // SAFETY: The MountsWriteToken proves we have exclusive write access.
294        let submount = unsafe { self.submounts.remove(key) };
295        let submount = scopeguard::guard(submount, |submount| guard.defer_drop(submount));
296        if submount.is_some() { Ok(()) } else { error!(EINVAL) }
297    }
298
299    fn iter_submounts<'a>(
300        &'a self,
301        scope: &'a starnix_rcu::RcuReadScope,
302    ) -> impl Iterator<Item = (&'a ArcKey<DirEntry>, &'a Arc<Submount>)> {
303        let mut cursor = self.submounts.cursor(scope);
304        std::iter::from_fn(move || {
305            let current = cursor.current();
306            if current.is_some() {
307                cursor.advance();
308            }
309            current
310        })
311    }
312
313    fn submounts_len(&self) -> usize {
314        self.submounts.len()
315    }
316
317    fn set_mountpoint(
318        &self,
319        _guard: &MountsWriteToken,
320        mountpoint: Option<(Weak<Mount>, DirEntryHandle)>,
321    ) {
322        self.mountpoint.update(mountpoint);
323    }
324
325    fn mountpoint<'a>(
326        &'a self,
327        scope: &'a starnix_rcu::RcuReadScope,
328    ) -> Option<&'a (Weak<Mount>, DirEntryHandle)> {
329        self.mountpoint.as_ref(scope).as_ref()
330    }
331
332    fn take_peer_group(
333        &self,
334        _guard: &MountsWriteToken,
335    ) -> Option<(Arc<PeerGroup>, PtrKey<Mount>)> {
336        let peer_group = self.peer_group.cloned();
337        self.peer_group.update(None);
338        peer_group
339    }
340
341    fn take_upstream(&self, _guard: &MountsWriteToken) -> Option<(Weak<PeerGroup>, PtrKey<Mount>)> {
342        let upstream = self.upstream.cloned();
343        self.upstream.update(None);
344        upstream
345    }
346}
347
348/// A group of mounts. Setting MS_SHARED on a mount puts it in its own peer group. Any bind mounts
349/// of a mount in the group are also added to the group. A mount created in any mount in a peer
350/// group will be automatically propagated (recreated) in every other mount in the group.
351#[derive(Default)]
352struct PeerGroup {
353    id: u64,
354    mounts: RcuRawHashMap<WeakKey<Mount>, ()>,
355    downstream: RcuRawHashMap<WeakKey<Mount>, ()>,
356}
357
358pub enum WhatToMount {
359    Fs(FileSystemHandle),
360    Bind(NamespaceNode),
361}
362
363enum WhatSubmount {
364    New(WhatToMount, MountpointFlags),
365    Existing(MountHandle),
366}
367
368impl Mount {
369    pub fn new(
370        mounts_guard: &MountsWriteToken,
371        what: WhatToMount,
372        mut flags: MountpointFlags,
373    ) -> Result<MountHandle, Errno> {
374        match what {
375            WhatToMount::Fs(fs) => {
376                // If `flags` does not explicitly specify an access-time flag then default to `RELATIME`.
377                flags.default_atime_from(MountpointFlags::RELATIME);
378                Ok(Self::new_with_root(fs.root().clone(), flags))
379            }
380            WhatToMount::Bind(node) => {
381                // A target node may not have a mount point if it's an anonymous node. Modern Linux (6.15+)
382                // returns ENOENT in this case, rather than the more intuitive EINVAL.
383                let mount = node.mount.as_ref().ok_or_else(|| errno!(ENOENT))?;
384                Ok(mount.clone_mount(mounts_guard, &node.entry, flags.into()))
385            }
386        }
387    }
388
389    fn new_with_root(root: DirEntryHandle, flags: MountpointFlags) -> MountHandle {
390        let fs = root.node.fs();
391        let kernel = fs.kernel.upgrade().expect("can't create mount without kernel");
392        Arc::new(Self {
393            id: kernel.get_next_mount_id(),
394            flags: (flags & MountpointFlags::STORED_ON_MOUNT).into(),
395            flags_lock: Default::default(),
396            root,
397            active_client_counter: Default::default(),
398            fs,
399            relations: Default::default(),
400        })
401    }
402
403    /// A namespace node referring to the root of the mount.
404    pub fn root(self: &MountHandle) -> NamespaceNode {
405        NamespaceNode::new(Arc::clone(self), Arc::clone(&self.root))
406    }
407
408    fn kernel(&self) -> Arc<Kernel> {
409        self.fs.kernel.upgrade().expect("No Kernel")
410    }
411
412    /// Create the specified mount as a child. Also propagate it to the mount's peer group.
413    fn create_submount(
414        self: &MountHandle,
415        mounts_guard: &MountsWriteToken,
416        dir: &DirEntryHandle,
417        what: WhatSubmount,
418    ) -> Result<(), Errno> {
419        // Necessary to make a copy to prevent excess replication, see the comment on the
420        // following Mount::new call.
421        let peers = self.peer_group().map(|g| g.copy_propagation_targets()).unwrap_or_default();
422        let peers = scopeguard::guard(peers, |peers| mounts_guard.defer_drop(peers));
423
424        // Create the mount after copying the peer list, because in the case of creating a bind
425        // mount inside itself, the new mount would get added to our peer group during the
426        // Mount::new call, but we don't want to replicate into it already. For an example see
427        // MountTest.QuizBRecursion.
428        let mount = match what {
429            WhatSubmount::Existing(mount) => mount,
430            WhatSubmount::New(what, flags) => Mount::new(mounts_guard, what, flags)?,
431        };
432
433        if self.is_shared() {
434            mount.make_shared(mounts_guard);
435        }
436
437        for peer in &*peers {
438            if Arc::ptr_eq(self, peer) {
439                continue;
440            }
441            let clone = mount.clone_mount_recursive(mounts_guard);
442            peer.add_submount_internal(mounts_guard, dir, clone);
443        }
444
445        self.add_submount_internal(mounts_guard, dir, mount);
446        Ok(())
447    }
448
449    fn remove_submount(
450        self: &MountHandle,
451        mounts_guard: &MountsWriteToken,
452        mount_hash_key: &ArcKey<DirEntry>,
453    ) -> Result<(), Errno> {
454        // create_submount explains why we need to make a copy of peers.
455        let peers = self.peer_group().map(|g| g.copy_propagation_targets()).unwrap_or_default();
456        let peers = scopeguard::guard(peers, |peers| mounts_guard.defer_drop(peers));
457
458        for peer in &*peers {
459            if Arc::ptr_eq(self, peer) {
460                continue;
461            }
462            // mount_namespaces(7): If B is shared, then all most-recently-mounted mounts at b on
463            // mounts that receive propagation from mount B and do not have submounts under them are
464            // unmounted.
465            let scope = RcuReadScope::new();
466            if let Some(submount) = peer.relations.submounts.get(&scope, mount_hash_key) {
467                if submount.mount.relations.submounts_len() != 0 {
468                    continue;
469                }
470            }
471            let _ = peer.remove_submount_internal(mounts_guard, mount_hash_key);
472        }
473
474        self.remove_submount_internal(mounts_guard, mount_hash_key)
475    }
476
477    pub fn move_mount(
478        source_mount: &MountHandle,
479        target_mount: &MountHandle,
480        target_dir: &DirEntryHandle,
481    ) -> Result<(), Errno> {
482        let kernel = target_mount.kernel();
483        let mounts_guard = kernel.mounts_lock();
484
485        let source_mountpoint = source_mount.mountpoint().ok_or_else(|| errno!(EIO))?;
486        let source_parent = mounts_guard.retain(
487            source_mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount"),
488        );
489        mounts_guard.retain(&source_mountpoint.entry);
490
491        // First, disconnect the mount from its parent.
492        {
493            if source_parent.peer_group().is_some() {
494                // Sayeth mount(2):
495                // EINVAL A move operation (MS_MOVE) was attempted, but the parent mount of source
496                //        mount has propagation type MS_SHARED.
497                return error!(EINVAL);
498            }
499            source_parent
500                .remove_submount_internal(&mounts_guard, source_mountpoint.mount_hash_key())?;
501            source_mount.relations.set_mountpoint(&mounts_guard, None);
502        }
503
504        target_mount.create_submount(
505            &mounts_guard,
506            target_dir,
507            WhatSubmount::Existing(Arc::clone(source_mount)),
508        )?;
509        Ok(())
510    }
511
512    /// Create a new mount with the same filesystem, flags, and peer group. Used to implement bind
513    /// mounts.
514    fn clone_mount(
515        self: &MountHandle,
516        mounts_guard: &MountsWriteToken,
517        new_root: &DirEntryHandle,
518        flags: MountFlags,
519    ) -> MountHandle {
520        assert!(new_root.is_descendant_of(&self.root));
521        // According to mount(2) on bind mounts, all flags other than MS_REC are ignored when doing
522        // a bind mount.
523        let clone = Self::new_with_root(Arc::clone(new_root), self.mount_flags());
524
525        if flags.contains(MountFlags::REC) {
526            for (dir, submount) in self.relations.iter_submounts(&RcuReadScope::new()) {
527                let submount = submount.mount.clone_mount_recursive(mounts_guard);
528                clone.add_submount_internal(mounts_guard, dir, submount);
529            }
530        }
531
532        // Put the clone in the same peer group
533        let peer_group = self.peer_group();
534        if let Some(peer_group) = peer_group {
535            clone.set_peer_group(mounts_guard, peer_group);
536        }
537
538        clone
539    }
540
541    /// Do a clone of the full mount hierarchy below this mount. Used for creating mount
542    /// namespaces and creating copies to use for propagation.
543    fn clone_mount_recursive(self: &MountHandle, mounts_guard: &MountsWriteToken) -> MountHandle {
544        self.clone_mount(mounts_guard, &self.root, MountFlags::REC)
545    }
546
547    pub fn change_propagation(
548        self: &MountHandle,
549        mounts_guard: &MountsWriteToken,
550        flag: MountFlags,
551        recursive: bool,
552    ) {
553        match flag {
554            MountFlags::SHARED => self.make_shared(mounts_guard),
555            MountFlags::PRIVATE => self.make_private(mounts_guard),
556            MountFlags::DOWNSTREAM => self.make_downstream(mounts_guard),
557            _ => {
558                log_warn!("mount propagation {:?}", flag);
559            }
560        }
561
562        if recursive {
563            for (_, submount) in self.relations.iter_submounts(&starnix_rcu::RcuReadScope::new()) {
564                submount.mount.change_propagation(mounts_guard, flag, recursive);
565            }
566        }
567    }
568
569    /// Returns the effective flags for the `Mount`, calculated as the union of the mount flags
570    /// associated with the `FileSystem`, and with the `Mount` itself.
571    fn flags(&self) -> MountFlags {
572        MountFlags::from(self.mount_flags()) | self.fs_flags().into()
573    }
574
575    /// Returns the mount flags stored unique to this `Mount`.
576    fn mount_flags(&self) -> MountpointFlags {
577        self.flags.load(Ordering::Relaxed)
578    }
579
580    /// Returns the mount flags for the `FileSystem` of this `Mount`.
581    fn fs_flags(&self) -> FileSystemFlags {
582        self.fs.options.flags.load(Ordering::Relaxed)
583    }
584
585    /// Updates the `Mount` with the per-mount flags specified in `flags`, while preserving the
586    /// existing access-time flag if no access-time flag is set in `flags`.
587    pub fn update_flags(self: &MountHandle, mut flags: MountpointFlags) {
588        let _lock = self.flags_lock.lock();
589        // Since Linux 3.17, if none of MS_NOATIME, MS_NODIRATIME,
590        // MS_RELATIME, or MS_STRICTATIME is specified in mountflags, then
591        // the remount operation preserves the existing values of these
592        // flags (rather than defaulting to MS_RELATIME).
593        flags.default_atime_from(self.flags.load(Ordering::Relaxed));
594        flags &= MountpointFlags::STORED_ON_MOUNT;
595        self.flags.store(flags, Ordering::Relaxed);
596    }
597
598    /// The number of active clients of this mount.
599    ///
600    /// The mount cannot be unmounted if there are any active clients.
601    fn active_clients(&self) -> usize {
602        // We need to subtract one for our own reference. We are not a real client.
603        Arc::strong_count(&self.active_client_counter) - 1
604    }
605
606    pub fn unmount(
607        &self,
608        mounts_guard: &MountsWriteToken,
609        flags: UnmountFlags,
610    ) -> Result<(), Errno> {
611        if !flags.contains(UnmountFlags::DETACH) {
612            if self.active_clients() > 0 || self.relations.submounts_len() != 0 {
613                return error!(EBUSY);
614            }
615        }
616
617        let mountpoint = self.mountpoint().ok_or_else(|| errno!(EINVAL))?;
618        let parent_mount = mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount");
619        parent_mount.remove_submount(mounts_guard, mountpoint.mount_hash_key())
620    }
621
622    /// Returns the security state of the fs.
623    pub fn security_state(&self) -> &security::FileSystemState {
624        &self.fs.security_state
625    }
626
627    /// Returns the name of the fs.
628    pub fn fs_name(&self) -> &'static FsStr {
629        self.fs.name()
630    }
631
632    /// Reconfigures the flags for the `FileSystem` backing this mount point.
633    pub fn reconfigure_fs(
634        &self,
635        current_task: &CurrentTask,
636        flags: FileSystemFlags,
637    ) -> Result<(), Errno> {
638        self.fs.update_flags(current_task, flags)
639    }
640
641    /// Returns true if there is a submount on top of `dir_entry`.
642    pub fn has_submount(&self, dir_entry: &DirEntryHandle) -> bool {
643        let scope = RcuReadScope::new();
644        self.relations.get_submount(&scope, ArcKey::ref_cast(dir_entry)).is_some()
645    }
646
647    /// The NamespaceNode on which this Mount is mounted.
648    pub fn mountpoint(&self) -> Option<NamespaceNode> {
649        let scope = RcuReadScope::new();
650        let (mount, entry) = self.relations.mountpoint(&scope)?;
651        Some(NamespaceNode::new(mount.upgrade()?, entry.clone()))
652    }
653
654    /// Add a child mount *without propagating it to the peer group*. For internal use only.
655    pub fn add_submount_internal(
656        self: &MountHandle,
657        guard: &MountsWriteToken,
658        dir: &DirEntryHandle,
659        mount: MountHandle,
660    ) {
661        if !dir.is_descendant_of(&self.root) {
662            return;
663        }
664
665        let submount = mount.kernel().mounts.register_mount(dir, mount.clone());
666
667        let old_mountpoint = {
668            let scope = RcuReadScope::new();
669            mount.relations.mountpoint(&scope).map(|x| x.clone())
670        };
671        mount.relations.set_mountpoint(guard, Some((Arc::downgrade(self), Arc::clone(dir))));
672        assert!(old_mountpoint.is_none(), "add_submount can only take a newly created mount");
673
674        let old_mount = self.relations.insert_submount(
675            guard,
676            ArcKey::ref_cast(dir).clone(),
677            Arc::new(submount),
678        );
679
680        if let Some(old_mount) = old_mount {
681            old_mount
682                .mount
683                .relations
684                .set_mountpoint(guard, Some((Arc::downgrade(&mount), Arc::clone(dir))));
685            let new_old_submount =
686                mount.kernel().mounts.register_mount(&mount.root, old_mount.mount.clone());
687            mount.relations.insert_submount(
688                guard,
689                ArcKey(mount.root.clone()),
690                Arc::new(new_old_submount),
691            );
692        }
693    }
694
695    pub fn remove_submount_internal(
696        self: &MountHandle,
697        guard: &MountsWriteToken,
698        mount_hash_key: &ArcKey<DirEntry>,
699    ) -> Result<(), Errno> {
700        self.relations.remove_submount(guard, mount_hash_key)
701    }
702
703    /// Return this mount's current peer group.
704    fn peer_group(&self) -> Option<Arc<PeerGroup>> {
705        let scope = RcuReadScope::new();
706        self.relations.peer_group.as_ref(&scope).as_ref().map(|(g, _)| g.clone())
707    }
708
709    /// Handles unregistering from both peer group and upstream simultaneously.
710    /// This resolves forwarding the upstream to the next mount in the peer group if necessary.
711    fn unregister_from_peer_group_and_upstream(
712        guard: &MountsWriteToken,
713        peer_group: Option<(Arc<PeerGroup>, PtrKey<Mount>)>,
714        upstream: Option<(Weak<PeerGroup>, PtrKey<Mount>)>,
715    ) {
716        let upstream_group = match upstream {
717            Some((weak_group, mount)) => {
718                if let Some(group) = weak_group.upgrade() {
719                    group.remove_downstream(guard, mount);
720                    Some(group)
721                } else {
722                    None
723                }
724            }
725            None => None,
726        };
727
728        if let Some((group, mount)) = peer_group {
729            group.remove(guard, mount);
730
731            if let Some(upstream_group) = upstream_group {
732                let next_mount = {
733                    let scope = RcuReadScope::new();
734                    group.mounts.keys(&scope).next().map(|w| w.0.upgrade().unwrap())
735                };
736                if let Some(next_mount) = next_mount {
737                    next_mount.set_upstream(guard, upstream_group);
738                }
739            }
740        }
741    }
742
743    /// Remove this mount from its peer group.
744    fn take_from_peer_group(&self, guard: &MountsWriteToken) -> Option<Arc<PeerGroup>> {
745        let peer_group = self.relations.take_peer_group(guard);
746        if peer_group.is_none() {
747            return None;
748        }
749        let upstream = self.relations.take_upstream(guard);
750        let return_group = peer_group.as_ref().map(|(g, _)| g.clone());
751        Mount::unregister_from_peer_group_and_upstream(guard, peer_group, upstream);
752        return_group
753    }
754
755    fn upstream(&self) -> Option<Arc<PeerGroup>> {
756        let scope = RcuReadScope::new();
757        let (group, _) = self.relations.upstream.as_ref(&scope).as_ref()?;
758        group.upgrade()
759    }
760
761    fn remove_from_upstream(&self, guard: &MountsWriteToken) {
762        let upstream = self.relations.take_upstream(guard);
763        if let Some((weak_group, mount)) = upstream {
764            if let Some(group) = weak_group.upgrade() {
765                group.remove_downstream(guard, mount);
766            }
767        }
768    }
769
770    /// Set this mount's peer group.
771    fn set_peer_group(self: &Arc<Mount>, guard: &MountsWriteToken, group: Arc<PeerGroup>) {
772        self.take_from_peer_group(guard);
773        group.add(guard, self);
774        self.relations.peer_group.update(Some((group, Arc::as_ptr(self).into())));
775    }
776
777    fn set_upstream(self: &Arc<Mount>, guard: &MountsWriteToken, group: Arc<PeerGroup>) {
778        self.remove_from_upstream(guard);
779        group.add_downstream(guard, self);
780        self.relations.upstream.update(Some((Arc::downgrade(&group), Arc::as_ptr(self).into())));
781    }
782
783    /// Is the mount in a peer group? Corresponds to MS_SHARED.
784    pub fn is_shared(&self) -> bool {
785        self.peer_group().is_some()
786    }
787
788    /// Put the mount in a peer group. Implements MS_SHARED.
789    fn make_shared(self: &Arc<Mount>, guard: &MountsWriteToken) {
790        if self.is_shared() {
791            return;
792        }
793        let kernel = self.kernel();
794        self.set_peer_group(guard, PeerGroup::new(kernel.get_next_peer_group_id()))
795    }
796
797    /// Take the mount out of its peer group, also remove upstream if any. Implements MS_PRIVATE.
798    fn make_private(&self, guard: &MountsWriteToken) {
799        let peer_group = self.relations.take_peer_group(guard);
800        let upstream = self.relations.take_upstream(guard);
801        Mount::unregister_from_peer_group_and_upstream(guard, peer_group, upstream);
802    }
803
804    /// Take the mount out of its peer group and make it downstream instead. Implements
805    /// MountFlags::DOWNSTREAM (MS_SLAVE).
806    fn make_downstream(self: &Arc<Mount>, guard: &MountsWriteToken) {
807        if let Some(peer_group) = self.take_from_peer_group(guard) {
808            self.set_upstream(guard, peer_group);
809        }
810    }
811}
812
813impl PeerGroup {
814    fn new(id: u64) -> Arc<Self> {
815        Arc::new(Self {
816            id,
817            mounts: RcuRawHashMap::default(),
818            downstream: RcuRawHashMap::default(),
819        })
820    }
821
822    fn add(&self, _guard: &MountsWriteToken, mount: &Arc<Mount>) {
823        // SAFETY: The MountsWriteToken proves we have exclusive write access.
824        unsafe { self.mounts.insert(&starnix_rcu::RcuReadScope::new(), WeakKey::from(mount), ()) };
825    }
826
827    fn remove(&self, _guard: &MountsWriteToken, mount: PtrKey<Mount>) {
828        // SAFETY: The MountsWriteToken proves we have exclusive write access.
829        unsafe { self.mounts.remove(&mount) };
830    }
831
832    fn add_downstream(&self, _guard: &MountsWriteToken, mount: &Arc<Mount>) {
833        // SAFETY: The MountsWriteToken proves we have exclusive write access.
834        unsafe {
835            self.downstream.insert(&starnix_rcu::RcuReadScope::new(), WeakKey::from(mount), ())
836        };
837    }
838
839    fn remove_downstream(&self, _guard: &MountsWriteToken, mount: PtrKey<Mount>) {
840        // SAFETY: The MountsWriteToken proves we have exclusive write access.
841        unsafe { self.downstream.remove(&mount) };
842    }
843
844    fn copy_propagation_targets(&self) -> Vec<MountHandle> {
845        let mut buf = vec![];
846        self.collect_propagation_targets(&mut buf);
847        buf
848    }
849
850    fn collect_propagation_targets(&self, buf: &mut Vec<MountHandle>) {
851        let downstream_mounts: Vec<_> = {
852            let scope = RcuReadScope::new();
853            buf.extend(self.mounts.keys(&scope).filter_map(|m| m.0.upgrade()));
854            self.downstream.keys(&scope).filter_map(|m| m.0.upgrade()).collect()
855        };
856        for mount in downstream_mounts {
857            let peer_group = mount.peer_group();
858            match peer_group {
859                Some(group) => group.collect_propagation_targets(buf),
860                None => buf.push(mount),
861            }
862        }
863    }
864}
865
866impl Kernel {
867    pub fn get_next_mount_id(&self) -> u64 {
868        self.next_mount_id.next()
869    }
870
871    pub fn get_next_peer_group_id(&self) -> u64 {
872        self.next_peer_group_id.next()
873    }
874
875    pub fn get_next_namespace_id(&self) -> u64 {
876        self.next_namespace_id.next()
877    }
878}
879
880impl CurrentTask {
881    pub fn create_filesystem(
882        &self,
883        fs_type: &FsStr,
884        options: FileSystemOptions,
885    ) -> Result<FileSystemHandle, Errno> {
886        // Please register new file systems via //src/starnix/modules/lib.rs, even if the file
887        // system is implemented inside starnix_core.
888        //
889        // Most file systems should be implemented as modules. The VFS provides various traits that
890        // let starnix_core integrate file systems without needing to depend on the file systems
891        // directly.
892        self.kernel()
893            .expando
894            .get::<FsRegistry>()
895            .create(self, fs_type, options)
896            .ok_or_else(|| errno!(ENODEV, fs_type))?
897    }
898}
899
900struct ProcMountsFileSource(Weak<Task>);
901
902impl DynamicFileSource for ProcMountsFileSource {
903    fn generate(
904        &self,
905        _current_task: &CurrentTask,
906        sink: &mut DynamicFileBuf,
907    ) -> Result<(), Errno> {
908        // TODO(tbodt): We should figure out a way to have a real iterator instead of grabbing the
909        // entire list in one go. Should we have a BTreeMap<u64, Weak<Mount>> in the Namespace?
910        // Also has the benefit of correct (i.e. chronological) ordering. But then we have to do
911        // extra work to maintain it.
912        let task = Task::from_weak(&self.0)?;
913        let task_fs = task.running_state()?.fs.read();
914        let root = task_fs.root();
915        let ns = task_fs.namespace();
916        for_each_mount(&ns.root_mount, &mut |mount| {
917            let mountpoint = mount.mountpoint().unwrap_or_else(|| mount.root());
918            if !mountpoint.is_descendant_of(&root) {
919                return Ok(());
920            }
921            write!(
922                sink,
923                "{} {} {} {}{}",
924                mount.fs.options.source_for_display(),
925                mountpoint.path(&task_fs),
926                mount.fs.name(),
927                // Report the union of the FileSystem and Mount flags, as well as any FileSystem-
928                // or LSM-specific options.
929                mount.flags(),
930                security::sb_show_options(&task.kernel(), &mount.fs)?,
931            )?;
932            writeln!(sink, " 0 0")?;
933            Ok(())
934        })?;
935        Ok(())
936    }
937}
938
939pub struct ProcMountsFile {
940    dynamic_file: DynamicFile<ProcMountsFileSource>,
941}
942
943impl ProcMountsFile {
944    pub fn new_node(task: Weak<Task>) -> impl FsNodeOps {
945        SimpleFileNode::new(move |_| {
946            Ok(Self { dynamic_file: DynamicFile::new(ProcMountsFileSource(task.clone())) })
947        })
948    }
949}
950
951impl FileOps for ProcMountsFile {
952    fileops_impl_delegate_read_write_and_seek!(self, self.dynamic_file);
953    fileops_impl_noop_sync!();
954
955    fn wait_async(
956        &self,
957        _file: &FileObject,
958        _current_task: &CurrentTask,
959        waiter: &Waiter,
960        _events: FdEvents,
961        _handler: EventHandler,
962    ) -> Option<WaitCanceler> {
963        // Polling this file gives notifications when any change to mounts occurs. This is not
964        // implemented yet, but stubbed for Android init.
965        Some(waiter.fake_wait())
966    }
967
968    fn query_events(
969        &self,
970        _file: &FileObject,
971        _current_task: &CurrentTask,
972    ) -> Result<FdEvents, Errno> {
973        Ok(FdEvents::empty())
974    }
975}
976
977#[derive(Clone)]
978pub struct ProcMountinfoFile(Weak<Task>);
979impl ProcMountinfoFile {
980    pub fn new_node(task: Weak<Task>) -> impl FsNodeOps {
981        DynamicFile::new_node(Self(task))
982    }
983}
984impl DynamicFileSource for ProcMountinfoFile {
985    fn generate(
986        &self,
987        _current_task: &CurrentTask,
988        sink: &mut DynamicFileBuf,
989    ) -> Result<(), Errno> {
990        // Returns path to the `dir` from the root of the file system.
991        fn path_from_fs_root(dir: &DirEntryHandle) -> FsString {
992            let mut path = PathBuilder::new();
993            if dir.is_dead() {
994                // Return `/foo/dir//deleted` if the dir was deleted.
995                path.prepend_element("/deleted".into());
996            }
997            let scope = RcuReadScope::new();
998            let mut current = dir.deref();
999            while let Some(parent) = current.parent_ref(&scope) {
1000                path.prepend_element(current.local_name(&scope));
1001                current = parent;
1002            }
1003            path.build_absolute()
1004        }
1005
1006        // TODO(tbodt): We should figure out a way to have a real iterator instead of grabbing the
1007        // entire list in one go. Should we have a BTreeMap<u64, Weak<Mount>> in the Namespace?
1008        // Also has the benefit of correct (i.e. chronological) ordering. But then we have to do
1009        // extra work to maintain it.
1010        let task = Task::from_weak(&self.0)?;
1011        let task_fs = task.running_state()?.fs.read();
1012        let root = task_fs.root();
1013        let ns = task_fs.namespace();
1014        for_each_mount(&ns.root_mount, &mut |mount| {
1015            let mountpoint = mount.mountpoint().unwrap_or_else(|| mount.root());
1016            if !mountpoint.is_descendant_of(&root) {
1017                return Ok(());
1018            }
1019            // Can't fail, mountpoint() and root() can't return a NamespaceNode with no mount
1020            let parent = mountpoint.mount.as_ref().unwrap();
1021            write!(
1022                sink,
1023                "{} {} {} {} {} {}",
1024                mount.id,
1025                parent.id,
1026                mount.root.node.fs().dev_id,
1027                path_from_fs_root(&mount.root),
1028                mountpoint.path(&task_fs),
1029                mount.mount_flags(),
1030            )?;
1031            if let Some(peer_group) = mount.peer_group() {
1032                write!(sink, " shared:{}", peer_group.id)?;
1033            }
1034            if let Some(upstream) = mount.upstream() {
1035                write!(sink, " master:{}", upstream.id)?;
1036            }
1037            writeln!(
1038                sink,
1039                " - {} {} {}{}",
1040                mount.fs.name(),
1041                mount.fs.options.source_for_display(),
1042                mount.fs_flags(),
1043                // LSM options are associated with the FileSystem rather than the Mount.
1044                security::sb_show_options(&task.kernel(), &mount.fs)?
1045            )?;
1046            Ok(())
1047        })?;
1048        Ok(())
1049    }
1050}
1051
1052fn for_each_mount<E>(
1053    mount: &MountHandle,
1054    callback: &mut impl FnMut(&MountHandle) -> Result<(), E>,
1055) -> Result<(), E> {
1056    callback(mount)?;
1057    for (_, s) in mount.relations.iter_submounts(&RcuReadScope::new()) {
1058        for_each_mount(&s.mount, callback)?;
1059    }
1060    Ok(())
1061}
1062
1063/// The `SymlinkMode` enum encodes how symlinks are followed during path traversal.
1064#[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
1065pub enum SymlinkMode {
1066    /// Follow a symlink at the end of a path resolution.
1067    #[default]
1068    Follow,
1069
1070    /// Do not follow a symlink at the end of a path resolution.
1071    NoFollow,
1072}
1073
1074/// The maximum number of symlink traversals that can be made during path resolution.
1075pub const MAX_SYMLINK_FOLLOWS: u8 = 40;
1076
1077/// The context passed during namespace lookups.
1078///
1079/// Namespace lookups need to mutate a shared context in order to correctly
1080/// count the number of remaining symlink traversals.
1081pub struct LookupContext {
1082    /// The SymlinkMode for the lookup.
1083    ///
1084    /// As the lookup proceeds, the follow count is decremented each time the
1085    /// lookup traverses a symlink.
1086    pub symlink_mode: SymlinkMode,
1087
1088    /// The number of symlinks remaining the follow.
1089    ///
1090    /// Each time path resolution calls readlink, this value is decremented.
1091    pub remaining_follows: u8,
1092
1093    /// Whether the result of the lookup must be a directory.
1094    ///
1095    /// For example, if the path ends with a `/` or if userspace passes
1096    /// O_DIRECTORY. This flag can be set to true if the lookup encounters a
1097    /// symlink that ends with a `/`.
1098    pub must_be_directory: bool,
1099
1100    /// Resolve flags passed to `openat2`. Empty if the lookup originated in any other syscall.
1101    pub resolve_flags: ResolveFlags,
1102
1103    /// Base directory for the lookup. Set only when either `RESOLVE_BENEATH` or `RESOLVE_IN_ROOT`
1104    /// is passed to `openat2`.
1105    pub resolve_base: ResolveBase,
1106}
1107
1108/// Used to specify base directory in `LookupContext` for lookups originating in the `openat2`
1109/// syscall with either `RESOLVE_BENEATH` or `RESOLVE_IN_ROOT` flag.
1110#[derive(Clone, Eq, PartialEq)]
1111pub enum ResolveBase {
1112    None,
1113
1114    /// The lookup is not allowed to traverse any node that's not beneath the specified node.
1115    Beneath(NamespaceNode),
1116
1117    /// The lookup should be handled as if the root specified node is the file-system root.
1118    InRoot(NamespaceNode),
1119}
1120
1121impl LookupContext {
1122    pub fn new(symlink_mode: SymlinkMode) -> LookupContext {
1123        LookupContext {
1124            symlink_mode,
1125            remaining_follows: MAX_SYMLINK_FOLLOWS,
1126            must_be_directory: false,
1127            resolve_flags: ResolveFlags::empty(),
1128            resolve_base: ResolveBase::None,
1129        }
1130    }
1131
1132    pub fn with(&self, symlink_mode: SymlinkMode) -> LookupContext {
1133        LookupContext { symlink_mode, resolve_base: self.resolve_base.clone(), ..*self }
1134    }
1135
1136    pub fn update_for_path(&mut self, path: &FsStr) {
1137        if path.last() == Some(&b'/') {
1138            // The last path element must resolve to a directory. This is because a trailing slash
1139            // was found in the path.
1140            self.must_be_directory = true;
1141            // If the last path element is a symlink, we should follow it.
1142            // See https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap03.html#tag_21_03_00_75
1143            self.symlink_mode = SymlinkMode::Follow;
1144        }
1145    }
1146}
1147
1148impl Default for LookupContext {
1149    fn default() -> Self {
1150        LookupContext::new(SymlinkMode::Follow)
1151    }
1152}
1153
1154/// Whether the path is reachable from the given root.
1155pub enum PathWithReachability {
1156    /// The path is reachable from the given root.
1157    Reachable(FsString),
1158
1159    /// The path is not reachable from the given root.
1160    Unreachable(FsString),
1161}
1162
1163impl PathWithReachability {
1164    pub fn into_path(self) -> FsString {
1165        match self {
1166            PathWithReachability::Reachable(path) => path,
1167            PathWithReachability::Unreachable(path) => path,
1168        }
1169    }
1170}
1171
1172/// A node in a mount namespace.
1173///
1174/// This tree is a composite of the mount tree and the FsNode tree.
1175///
1176/// These nodes are used when traversing paths in a namespace in order to
1177/// present the client the directory structure that includes the mounted
1178/// filesystems.
1179#[derive(Clone)]
1180pub struct NamespaceNode {
1181    /// The mount where this namespace node is mounted.
1182    ///
1183    /// A given FsNode can be mounted in multiple places in a namespace. This
1184    /// field distinguishes between them.
1185    pub mount: MountInfo,
1186
1187    /// The FsNode that corresponds to this namespace entry.
1188    pub entry: DirEntryHandle,
1189}
1190
1191impl NamespaceNode {
1192    pub fn new(mount: MountHandle, entry: DirEntryHandle) -> Self {
1193        Self { mount: Some(mount).into(), entry }
1194    }
1195
1196    /// Create a namespace node that is not mounted in a namespace.
1197    pub fn new_anonymous(entry: DirEntryHandle) -> Self {
1198        Self { mount: None.into(), entry }
1199    }
1200
1201    /// Create a namespace node that is not mounted in a namespace and that refers to a node that
1202    /// is not rooted in a hierarchy and has no name.
1203    pub fn new_anonymous_unrooted(current_task: &CurrentTask, node: FsNodeHandle) -> Self {
1204        let dir_entry = DirEntry::new_unrooted(node);
1205        let _ = security::fs_node_init_with_dentry_no_xattr(current_task, &dir_entry);
1206        Self::new_anonymous(dir_entry)
1207    }
1208
1209    /// Create a FileObject corresponding to this namespace node.
1210    ///
1211    /// This function is the primary way of instantiating FileObjects. Each
1212    /// FileObject records the NamespaceNode that created it in order to
1213    /// remember its path in the Namespace.
1214    pub fn open(
1215        &self,
1216        current_task: &CurrentTask,
1217        flags: OpenFlags,
1218        access_check: AccessCheck,
1219    ) -> Result<FileHandle, Errno> {
1220        let ops = self.entry.node.open(current_task, self, flags, access_check)?;
1221        FileObject::new(current_task, ops, self.clone(), flags)
1222    }
1223
1224    /// Create or open a node in the file system.
1225    ///
1226    /// Works for any type of node other than a symlink.
1227    ///
1228    /// Will return an existing node unless `flags` contains `OpenFlags::EXCL`.
1229    pub fn open_create_node(
1230        &self,
1231        current_task: &CurrentTask,
1232        name: &FsStr,
1233        mode: FileMode,
1234        dev: DeviceId,
1235        flags: OpenFlags,
1236    ) -> Result<NamespaceNode, Errno> {
1237        let owner = current_task.current_fscred();
1238        let mode = current_task.fs().apply_umask(mode);
1239        let create_fn = |dir: &FsNodeHandle, mount: &MountInfo, name: &_| {
1240            dir.create_node(current_task, mount, name, mode, dev, owner)
1241        };
1242        let entry = if flags.contains(OpenFlags::EXCL) {
1243            self.entry.create_entry(current_task, &self.mount, name, create_fn)
1244        } else {
1245            self.entry.get_or_create_entry(current_task, &self.mount, name, create_fn)
1246        }?;
1247        Ok(self.with_new_entry(entry))
1248    }
1249
1250    pub fn into_active(self) -> ActiveNamespaceNode {
1251        ActiveNamespaceNode::new(self)
1252    }
1253
1254    pub fn into_mapping(self, mode: Option<FileWriteGuardMode>) -> Result<Arc<FileMapping>, Errno> {
1255        self.into_active().into_mapping(mode)
1256    }
1257
1258    /// Create a node in the file system.
1259    ///
1260    /// Works for any type of node other than a symlink.
1261    ///
1262    /// Does not return an existing node.
1263    pub fn create_node(
1264        &self,
1265        current_task: &CurrentTask,
1266        name: &FsStr,
1267        mode: FileMode,
1268        dev: DeviceId,
1269    ) -> Result<NamespaceNode, Errno> {
1270        let owner = current_task.current_fscred();
1271        let mode = current_task.fs().apply_umask(mode);
1272        let entry =
1273            self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1274                dir.create_node(current_task, mount, name, mode, dev, owner)
1275            })?;
1276        Ok(self.with_new_entry(entry))
1277    }
1278
1279    /// Create a symlink in the file system.
1280    ///
1281    /// To create another type of node, use `create_node`.
1282    pub fn create_symlink(
1283        &self,
1284        current_task: &CurrentTask,
1285        name: &FsStr,
1286        target: &FsStr,
1287    ) -> Result<NamespaceNode, Errno> {
1288        let owner = current_task.current_fscred();
1289        let entry =
1290            self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1291                dir.create_symlink(current_task, mount, name, target, owner)
1292            })?;
1293        Ok(self.with_new_entry(entry))
1294    }
1295
1296    /// Creates an anonymous file.
1297    ///
1298    /// The FileMode::IFMT of the FileMode is always FileMode::IFREG.
1299    ///
1300    /// Used by O_TMPFILE.
1301    pub fn create_tmpfile(
1302        &self,
1303        current_task: &CurrentTask,
1304        mode: FileMode,
1305        flags: OpenFlags,
1306    ) -> Result<NamespaceNode, Errno> {
1307        let owner = current_task.current_fscred();
1308        let mode = current_task.fs().apply_umask(mode);
1309        Ok(self.with_new_entry(self.entry.create_tmpfile(
1310            current_task,
1311            &self.mount,
1312            mode,
1313            owner,
1314            flags,
1315        )?))
1316    }
1317
1318    pub fn link(
1319        &self,
1320        current_task: &CurrentTask,
1321        name: &FsStr,
1322        child: &FsNodeHandle,
1323    ) -> Result<NamespaceNode, Errno> {
1324        let dir_entry =
1325            self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1326                dir.link(current_task, mount, name, child)
1327            })?;
1328        Ok(self.with_new_entry(dir_entry))
1329    }
1330
1331    pub fn bind_socket(
1332        &self,
1333        current_task: &CurrentTask,
1334        name: &FsStr,
1335        socket: SocketHandle,
1336        socket_address: SocketAddress,
1337        mode: FileMode,
1338    ) -> Result<NamespaceNode, Errno> {
1339        let dir_entry =
1340            self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1341                let node = dir.create_node(
1342                    current_task,
1343                    mount,
1344                    name,
1345                    mode,
1346                    DeviceId::NONE,
1347                    current_task.current_fscred(),
1348                )?;
1349                if let Some(unix_socket) = socket.downcast_socket::<UnixSocket>() {
1350                    unix_socket.bind_socket_to_node(&socket, socket_address, &node)?;
1351                } else {
1352                    return error!(ENOTSUP);
1353                }
1354                Ok(node)
1355            })?;
1356        Ok(self.with_new_entry(dir_entry))
1357    }
1358
1359    pub fn unlink(
1360        &self,
1361        current_task: &CurrentTask,
1362        name: &FsStr,
1363        kind: UnlinkKind,
1364        must_be_directory: bool,
1365    ) -> Result<(), Errno> {
1366        if DirEntry::is_reserved_name(name) {
1367            match kind {
1368                UnlinkKind::Directory => {
1369                    if name == ".." {
1370                        error!(ENOTEMPTY)
1371                    } else if self.parent().is_none() {
1372                        // The client is attempting to remove the root.
1373                        error!(EBUSY)
1374                    } else {
1375                        error!(EINVAL)
1376                    }
1377                }
1378                UnlinkKind::NonDirectory => error!(ENOTDIR),
1379            }
1380        } else {
1381            self.entry.unlink(current_task, &self.mount, name, kind, must_be_directory)
1382        }
1383    }
1384
1385    // Resolve the current node.
1386    //
1387    // Depending on context, this will resolve symlink and mount point.
1388    fn resolve(
1389        self,
1390        current_task: &CurrentTask,
1391        context: &mut LookupContext,
1392    ) -> Result<NamespaceNode, Errno> {
1393        let mut node = self;
1394
1395        loop {
1396            if !node.entry.node.is_lnk() || context.symlink_mode == SymlinkMode::NoFollow {
1397                break;
1398            }
1399            if context.remaining_follows == 0
1400                || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
1401            {
1402                return error!(ELOOP);
1403            }
1404            context.remaining_follows -= 1;
1405            node = match node.readlink(current_task)? {
1406                SymlinkTarget::Path(link_target) => {
1407                    let link_directory = if link_target[0] == b'/' {
1408                        // If the path is absolute, we'll resolve the root directory.
1409                        match &context.resolve_base {
1410                            ResolveBase::None => current_task.fs().root(),
1411                            ResolveBase::Beneath(_) => return error!(EXDEV),
1412                            ResolveBase::InRoot(root) => root.clone(),
1413                        }
1414                    } else {
1415                        // If the path is not absolute, it's a relative directory.
1416                        // Let's try to get the parent of the current node, or in the case that
1417                        // the node is the root we can just use that directly.
1418                        node.parent().unwrap_or(node)
1419                    };
1420                    current_task.lookup_path(context, link_directory, link_target.as_ref())?
1421                }
1422                SymlinkTarget::Node(node) => {
1423                    if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS) {
1424                        return error!(ELOOP);
1425                    }
1426                    node
1427                }
1428            };
1429        }
1430        Ok(node.enter_mount())
1431    }
1432
1433    /// Traverse down a parent-to-child link in the namespace.
1434    pub fn lookup_child(
1435        &self,
1436        current_task: &CurrentTask,
1437        context: &mut LookupContext,
1438        basename: &FsStr,
1439    ) -> Result<NamespaceNode, Errno> {
1440        self.lookup_children(current_task, context, &[basename])
1441    }
1442
1443    /// Traverse down a parent-to-child link in the namespace.
1444    pub fn lookup_children(
1445        &self,
1446        current_task: &CurrentTask,
1447        context: &mut LookupContext,
1448        mut basenames: &[&FsStr],
1449    ) -> Result<NamespaceNode, Errno> {
1450        for name in basenames {
1451            if name.len() > NAME_MAX as usize {
1452                return error!(ENAMETOOLONG);
1453            }
1454        }
1455
1456        let mut current_namespace_node = self.clone();
1457
1458        while basenames.len() > 0 {
1459            if !current_namespace_node.entry.node.is_dir() {
1460                return error!(ENOTDIR);
1461            }
1462
1463            let basename = basenames[0];
1464            if basename.is_empty() || basename == "." {
1465                basenames = &basenames[1..];
1466                continue;
1467            }
1468            if basename == ".." {
1469                let root = match &context.resolve_base {
1470                    ResolveBase::None => current_task.fs().root(),
1471                    ResolveBase::Beneath(node) => {
1472                        // Do not allow traversal out of the 'node'.
1473                        if current_namespace_node == *node {
1474                            return error!(EXDEV);
1475                        }
1476                        current_task.fs().root()
1477                    }
1478                    ResolveBase::InRoot(root) => root.clone(),
1479                };
1480
1481                // Make sure this can't escape a chroot.
1482                if current_namespace_node != root {
1483                    current_namespace_node =
1484                        current_namespace_node.parent().unwrap_or(current_namespace_node)
1485                }
1486                if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1487                    && current_namespace_node.mount != self.mount
1488                {
1489                    return error!(EXDEV);
1490                }
1491
1492                if context.must_be_directory && !current_namespace_node.entry.node.is_dir() {
1493                    return error!(ENOTDIR);
1494                }
1495                basenames = &basenames[1..];
1496                continue;
1497            }
1498            if basenames.len() == 1
1499                || !current_namespace_node.entry.node.ops().has_lookup_pipelined()
1500            {
1501                current_namespace_node = current_namespace_node.with_new_entry(
1502                    current_namespace_node.entry.component_lookup(
1503                        current_task,
1504                        &current_namespace_node.mount,
1505                        basename,
1506                    )?,
1507                );
1508
1509                current_namespace_node = current_namespace_node.resolve(current_task, context)?;
1510
1511                if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1512                    && current_namespace_node.mount != self.mount
1513                {
1514                    return error!(EXDEV);
1515                }
1516
1517                if context.must_be_directory && !current_namespace_node.entry.node.is_dir() {
1518                    return error!(ENOTDIR);
1519                }
1520
1521                basenames = &basenames[1..];
1522                continue;
1523            }
1524
1525            let pipelined_basenames = if let Some(pos) =
1526                basenames.iter().position(|&name| name.is_empty() || name == "." || name == "..")
1527            {
1528                &basenames[..pos]
1529            } else {
1530                basenames
1531            };
1532            let precomputed_entries = current_namespace_node.entry.get_children_pipelined(
1533                current_task,
1534                &current_namespace_node.mount,
1535                pipelined_basenames,
1536            );
1537            for entry in precomputed_entries {
1538                basenames = &basenames[1..];
1539                let child = current_namespace_node.with_new_entry(entry?);
1540
1541                current_namespace_node = child.clone().resolve(current_task, context)?;
1542
1543                if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1544                    && current_namespace_node.mount != self.mount
1545                {
1546                    return error!(EXDEV);
1547                }
1548
1549                if context.must_be_directory && !current_namespace_node.entry.node.is_dir() {
1550                    return error!(ENOTDIR);
1551                }
1552
1553                if current_namespace_node != child {
1554                    break;
1555                }
1556            }
1557        }
1558
1559        Ok(current_namespace_node)
1560    }
1561
1562    /// Traverse up a child-to-parent link in the namespace.
1563    ///
1564    /// This traversal matches the child-to-parent link in the underlying
1565    /// FsNode except at mountpoints, where the link switches from one
1566    /// filesystem to another.
1567    pub fn parent(&self) -> Option<NamespaceNode> {
1568        let mountpoint_or_self = self.escape_mount();
1569        let parent = mountpoint_or_self.entry.parent()?;
1570        Some(mountpoint_or_self.with_new_entry(parent))
1571    }
1572
1573    /// Returns the parent, but does not escape mounts i.e. returns None if this node
1574    /// is the root of a mount.
1575    pub fn parent_within_mount(&self) -> Option<DirEntryHandle> {
1576        if let Ok(_) = self.mount_if_root() {
1577            return None;
1578        }
1579        self.entry.parent()
1580    }
1581
1582    /// Whether this namespace node is a descendant of the given node.
1583    ///
1584    /// Walks up the namespace node tree looking for ancestor. If ancestor is
1585    /// found, returns true. Otherwise, returns false.
1586    pub fn is_descendant_of(&self, ancestor: &NamespaceNode) -> bool {
1587        let ancestor = ancestor.escape_mount();
1588        let mut current = self.escape_mount();
1589        while current != ancestor {
1590            if let Some(parent) = current.parent() {
1591                current = parent.escape_mount();
1592            } else {
1593                return false;
1594            }
1595        }
1596        true
1597    }
1598
1599    /// If this node is a mountpoint, returns the root of the submount.
1600    ///
1601    /// This only traverses one level of mount, even if the submount's root
1602    /// is itself a mountpoint for another mount.
1603    fn enter_one_mount(&self) -> Option<NamespaceNode> {
1604        if let Some(mount) = self.mount.deref() {
1605            if let Some(submount) =
1606                mount.relations.get_submount(&RcuReadScope::new(), ArcKey::ref_cast(&self.entry))
1607            {
1608                return Some(submount.mount.root());
1609            }
1610        }
1611        None
1612    }
1613
1614    /// If this is a mount point, return the root of the mount. Otherwise return self.
1615    ///
1616    /// This function traverses multiple mounts if there are mounts layered on top of each other.
1617    /// It handles its own synchronization by acquiring the mounts sequence lock for reading.
1618    fn enter_mount(&self) -> NamespaceNode {
1619        // While the child is a mountpoint, replace child with the mount's root.
1620        let kernel = self.entry.node.fs().kernel.upgrade().expect("kernel");
1621        kernel.mounts_lock.read_seq(|| {
1622            let mut inner = self.clone();
1623            while let Some(inner_root) = inner.enter_one_mount() {
1624                inner = inner_root;
1625            }
1626            inner
1627        })
1628    }
1629
1630    /// If this is a mount point, return the root of the mount. Otherwise return self.
1631    ///
1632    /// This function traverses multiple mounts if there are mounts layered on top of each other.
1633    /// It requires the caller to hold the mounts write lock (proved by `MountsWriteToken`),
1634    /// unlike `enter_mount` which uses a sequence lock for reading.
1635    fn enter_mount_locked(&self, _mounts_guard: &MountsWriteToken) -> NamespaceNode {
1636        // While the child is a mountpoint, replace child with the mount's root.
1637        let mut inner = self.clone();
1638        while let Some(inner_root) = inner.enter_one_mount() {
1639            inner = inner_root;
1640        }
1641        inner
1642    }
1643
1644    /// If this is the root of a mount, return the mount point. Otherwise return self.
1645    ///
1646    /// This is not exactly the same as parent(). If parent() is called on a root, it will escape
1647    /// the mount, but then return the parent of the mount point instead of the mount point.
1648    fn escape_mount(&self) -> NamespaceNode {
1649        let kernel = self.entry.node.fs().kernel.upgrade().expect("kernel");
1650        kernel.mounts_lock.read_seq(|| {
1651            let mut mountpoint_or_self = self.clone();
1652            while let Some(mountpoint) = mountpoint_or_self.mountpoint() {
1653                mountpoint_or_self = mountpoint;
1654            }
1655            mountpoint_or_self
1656        })
1657    }
1658
1659    /// If this node is the root of a mount, return it. Otherwise EINVAL.
1660    pub fn mount_if_root(&self) -> Result<&MountHandle, Errno> {
1661        if let Some(mount) = self.mount.deref() {
1662            if Arc::ptr_eq(&self.entry, &mount.root) {
1663                return Ok(mount);
1664            }
1665        }
1666        error!(EINVAL)
1667    }
1668
1669    /// Returns the mountpoint at this location in the namespace.
1670    ///
1671    /// If this node is mounted in another node, this function returns the node
1672    /// at which this node is mounted. Otherwise, returns None.
1673    fn mountpoint(&self) -> Option<NamespaceNode> {
1674        self.mount_if_root().ok()?.mountpoint()
1675    }
1676
1677    /// The path from the filesystem root to this node.
1678    pub fn path(&self, fs: &FsContext) -> FsString {
1679        self.path_from_root(Some(&fs.root())).into_path()
1680    }
1681
1682    /// The path from the root of the namespace to this node.
1683    pub fn path_escaping_chroot(&self) -> FsString {
1684        self.path_from_root(None).into_path()
1685    }
1686
1687    /// Returns the path to this node, accounting for a custom root.
1688    /// A task may have a custom root set by `chroot`.
1689    pub fn path_from_root(&self, root: Option<&NamespaceNode>) -> PathWithReachability {
1690        if self.mount.is_none() {
1691            return self.unrooted_path();
1692        }
1693
1694        let mut path = PathBuilder::new();
1695        let mut current = self.escape_mount();
1696        if let Some(root) = root {
1697            let scope = RcuReadScope::new();
1698            // The current node is expected to intersect with the custom root as we travel up the tree.
1699            let root = root.escape_mount();
1700            while current != root {
1701                if let Some(parent) = current.parent() {
1702                    path.prepend_element(current.entry.local_name(&scope));
1703                    current = parent.escape_mount();
1704                } else {
1705                    // This node hasn't intersected with the custom root and has reached the namespace root.
1706                    let mut absolute_path = path.build_absolute();
1707                    if self.entry.is_dead() {
1708                        absolute_path.extend_from_slice(b" (deleted)");
1709                    }
1710
1711                    return PathWithReachability::Unreachable(absolute_path);
1712                }
1713            }
1714        } else {
1715            // No custom root, so travel up the tree to the namespace root.
1716            let scope = RcuReadScope::new();
1717            while let Some(parent) = current.parent() {
1718                path.prepend_element(current.entry.local_name(&scope));
1719                current = parent.escape_mount();
1720            }
1721        }
1722
1723        let mut absolute_path = path.build_absolute();
1724        if self.entry.is_dead() {
1725            absolute_path.extend_from_slice(b" (deleted)");
1726        }
1727
1728        PathWithReachability::Reachable(absolute_path)
1729    }
1730
1731    fn unrooted_path(&self) -> PathWithReachability {
1732        let scope = RcuReadScope::new();
1733        let mode = self.entry.node.info().mode;
1734        let local_name = self.entry.local_name(&scope);
1735        let path = if !local_name.is_empty() {
1736            format!("anon_inode:{}", local_name)
1737        } else if mode.is_sock() {
1738            format!("socket:[{}]", self.entry.node.ino)
1739        } else if mode.is_fifo() {
1740            format!("pipe:[{}]", self.entry.node.ino)
1741        } else {
1742            format!("file:[{}]", self.entry.node.ino)
1743        };
1744        PathWithReachability::Reachable(path.into())
1745    }
1746
1747    pub fn mount(&self, what: WhatToMount, flags: MountpointFlags) -> Result<(), Errno> {
1748        let target = self.enter_mount();
1749
1750        // A target node may not have a mount point if it's an anonymous node. Modern Linux (6.15+)
1751        // returns ENOENT in this case, rather than the more intuitive EINVAL.
1752        if target.mount.is_none() {
1753            return error!(ENOENT);
1754        }
1755
1756        let source_is_dir = match &what {
1757            WhatToMount::Fs(fs) => fs.root().node.is_dir(),
1758            WhatToMount::Bind(node) => node.entry.node.is_dir(),
1759        };
1760
1761        // The source and target need to both be identical types. In other words, if attempting to
1762        // mount a source file onto a target directory (or vice versa), we should err.
1763        if source_is_dir != target.entry.node.is_dir() {
1764            return error!(ENOTDIR);
1765        }
1766
1767        let kernel = self.entry.node.fs().kernel.upgrade().expect("can't mount without a kernel");
1768        let mounts_guard = kernel.mounts_lock();
1769        let mountpoint = self.enter_mount_locked(&mounts_guard);
1770
1771        let mount = mountpoint.mount.as_ref().ok_or_else(|| errno!(ENOENT))?;
1772        let writeable_mount = mounts_guard.retain(mount);
1773        let writeable_entry = mounts_guard.retain(&mountpoint.entry);
1774        writeable_mount.create_submount(
1775            &mounts_guard,
1776            &writeable_entry,
1777            WhatSubmount::New(what, flags),
1778        )
1779    }
1780
1781    /// If this is the root of a filesystem, unmount. Otherwise return EINVAL.
1782    pub fn unmount(&self, flags: UnmountFlags) -> Result<(), Errno> {
1783        let kernel = self.entry.node.fs().kernel.upgrade().expect("can't mount without a kernel");
1784        let mounts_guard = kernel.mounts_lock();
1785
1786        let mountpoint = self.enter_mount_locked(&mounts_guard);
1787        mounts_guard.retain(&mountpoint.entry);
1788        mountpoint.mount.as_ref().map(|mount| mounts_guard.retain(mount));
1789        let mount = mounts_guard.retain(mountpoint.mount_if_root()?);
1790        mount.unmount(&mounts_guard, flags)
1791    }
1792
1793    pub fn rename(
1794        current_task: &CurrentTask,
1795        old_parent: &NamespaceNode,
1796        old_name: &FsStr,
1797        new_parent: &NamespaceNode,
1798        new_name: &FsStr,
1799        flags: RenameFlags,
1800    ) -> Result<(), Errno> {
1801        DirEntry::rename(
1802            current_task,
1803            &old_parent.entry,
1804            &old_parent.mount,
1805            old_name,
1806            &new_parent.entry,
1807            &new_parent.mount,
1808            new_name,
1809            flags,
1810        )
1811    }
1812
1813    fn with_new_entry(&self, entry: DirEntryHandle) -> NamespaceNode {
1814        Self { mount: self.mount.clone(), entry }
1815    }
1816
1817    fn mount_hash_key(&self) -> &ArcKey<DirEntry> {
1818        ArcKey::ref_cast(&self.entry)
1819    }
1820
1821    pub fn apply_suid_and_sgid(&self, creds: &mut Credentials) {
1822        // From <https://man7.org/linux/man-pages/man2/execve.2.html>:
1823        //
1824        //   The aforementioned transformations of the effective IDs are not
1825        //   performed ... if ... the underlying filesystem is mounted nosuid
1826        //   (the MS_NOSUID flag for mount(2)).
1827        if self.mount.flags().contains(MountFlags::NOSUID) {
1828            return;
1829        }
1830        self.entry.node.info().apply_suid_and_sgid(creds)
1831    }
1832
1833    pub fn update_atime(&self) {
1834        // Do not update the atime of this node if it is mounted with the NOATIME flag.
1835        if !self.mount.flags().contains(MountFlags::NOATIME) {
1836            self.entry.node.update_info(|info| {
1837                let now = utc::utc_now();
1838                info.time_access = now;
1839                info.pending_time_access_update = true;
1840            });
1841        }
1842    }
1843
1844    pub fn readlink(&self, current_task: &CurrentTask) -> Result<SymlinkTarget, Errno> {
1845        self.update_atime();
1846        self.entry.node.readlink(current_task)
1847    }
1848
1849    pub fn notify(&self, event_mask: InotifyMask) {
1850        if self.mount.is_some() {
1851            self.entry.notify(event_mask);
1852        }
1853    }
1854
1855    /// Check whether the node can be accessed in the current context with the specified access
1856    /// flags (read, write, or exec). Accounts for capabilities and whether the current user is the
1857    /// owner or is in the file's group.
1858    pub fn check_access(
1859        &self,
1860        current_task: &CurrentTask,
1861        permission_flags: impl Into<security::PermissionFlags>,
1862        reason: CheckAccessReason,
1863    ) -> Result<(), Errno> {
1864        self.entry.node.check_access(current_task, &self.mount, permission_flags, reason, self)
1865    }
1866
1867    /// Checks if O_NOATIME is allowed,
1868    pub fn check_o_noatime_allowed(&self, current_task: &CurrentTask) -> Result<(), Errno> {
1869        self.entry.node.check_o_noatime_allowed(current_task)
1870    }
1871
1872    pub fn truncate(&self, current_task: &CurrentTask, length: u64) -> Result<(), Errno> {
1873        self.entry.node.truncate(current_task, &self.mount, length)?;
1874        self.entry.notify_ignoring_excl_unlink(InotifyMask::MODIFY);
1875        Ok(())
1876    }
1877}
1878
1879impl fmt::Debug for NamespaceNode {
1880    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1881        f.debug_struct("NamespaceNode")
1882            .field("path", &self.path_escaping_chroot())
1883            .field("mount", &self.mount)
1884            .field("entry", &self.entry)
1885            .finish()
1886    }
1887}
1888
1889// Eq/Hash impls intended for the MOUNT_POINTS hash
1890impl PartialEq for NamespaceNode {
1891    fn eq(&self, other: &Self) -> bool {
1892        self.mount.as_ref().map(Arc::as_ptr).eq(&other.mount.as_ref().map(Arc::as_ptr))
1893            && Arc::ptr_eq(&self.entry, &other.entry)
1894    }
1895}
1896impl Eq for NamespaceNode {}
1897impl Hash for NamespaceNode {
1898    fn hash<H: Hasher>(&self, state: &mut H) {
1899        self.mount.as_ref().map(Arc::as_ptr).hash(state);
1900        Arc::as_ptr(&self.entry).hash(state);
1901    }
1902}
1903
1904/// A namespace node that keeps the underly mount busy.
1905#[derive(Debug, Clone)]
1906pub struct ActiveNamespaceNode {
1907    /// The underlying namespace node.
1908    name: NamespaceNode,
1909
1910    /// Adds a reference to the mount client marker to prevent the mount from
1911    /// being removed while the NamespaceNode is active. Is None iff mount is
1912    /// None.
1913    _marker: Option<MountClientMarker>,
1914}
1915
1916impl ActiveNamespaceNode {
1917    pub fn new(name: NamespaceNode) -> Self {
1918        let marker = name.mount.as_ref().map(|mount| mount.active_client_counter.clone());
1919        Self { name, _marker: marker }
1920    }
1921
1922    pub fn to_passive(&self) -> NamespaceNode {
1923        self.deref().clone()
1924    }
1925
1926    pub fn into_mapping(self, mode: Option<FileWriteGuardMode>) -> Result<Arc<FileMapping>, Errno> {
1927        if let Some(mode) = mode {
1928            self.entry.node.write_guard_state.lock().acquire(mode)?;
1929        }
1930        Ok(Arc::new(FileMapping { name: self, mode }))
1931    }
1932}
1933
1934impl Deref for ActiveNamespaceNode {
1935    type Target = NamespaceNode;
1936
1937    fn deref(&self) -> &Self::Target {
1938        &self.name
1939    }
1940}
1941
1942impl PartialEq for ActiveNamespaceNode {
1943    fn eq(&self, other: &Self) -> bool {
1944        self.deref().eq(other.deref())
1945    }
1946}
1947impl Eq for ActiveNamespaceNode {}
1948impl Hash for ActiveNamespaceNode {
1949    fn hash<H: Hasher>(&self, state: &mut H) {
1950        self.deref().hash(state)
1951    }
1952}
1953
1954#[derive(Debug, Clone, PartialEq, Eq)]
1955#[must_use]
1956pub struct FileMapping {
1957    pub name: ActiveNamespaceNode,
1958    mode: Option<FileWriteGuardMode>,
1959}
1960
1961impl Drop for FileMapping {
1962    fn drop(&mut self) {
1963        if let Some(mode) = self.mode {
1964            self.name.entry.node.write_guard_state.lock().release(mode);
1965        }
1966    }
1967}
1968
1969/// Tracks all mounts, keyed by mount point.
1970pub struct Mounts {
1971    mounts: RcuHashMap<WeakKey<DirEntry>, Vec<ArcKey<Mount>>>,
1972}
1973
1974impl Mounts {
1975    pub fn new() -> Self {
1976        Mounts { mounts: RcuHashMap::default() }
1977    }
1978
1979    /// Registers the mount in the global mounts map.
1980    fn register_mount(&self, dir_entry: &Arc<DirEntry>, mount: MountHandle) -> Submount {
1981        let mut mounts = self.mounts.lock();
1982        let key = WeakKey::from(dir_entry);
1983        let mut vec = mounts.get(&key).unwrap_or_else(|| {
1984            dir_entry.set_has_mounts(true);
1985            Vec::new()
1986        });
1987        vec.push(ArcKey(mount.clone()));
1988        mounts.insert(key, vec);
1989        Submount { dir: ArcKey(dir_entry.clone()), mount }
1990    }
1991
1992    /// Unregisters the mount. This is called by `Submount::drop`.
1993    fn unregister_mount(&self, dir_entry: &Arc<DirEntry>, mount: &MountHandle) {
1994        let mut mounts = self.mounts.lock();
1995        let key = WeakKey::from(dir_entry);
1996        if let Some(mut vec) = mounts.get(&key) {
1997            let index = vec.iter().position(|e| e == ArcKey::ref_cast(mount)).unwrap();
1998            if vec.len() == 1 {
1999                mounts.remove(&key);
2000                dir_entry.set_has_mounts(false);
2001            } else {
2002                vec.swap_remove(index);
2003                mounts.insert(key, vec);
2004            }
2005        }
2006    }
2007
2008    /// Unmounts all mounts associated with `dir_entry`. This is called when `dir_entry` is
2009    /// unlinked (which would normally result in EBUSY, but not if it isn't mounted in the local
2010    /// namespace).
2011    pub fn unmount(&self, dir_entry: &DirEntry) {
2012        let mounts = self.mounts.lock().remove(&PtrKey::from(dir_entry as *const _));
2013        if let Some(mounts) = mounts {
2014            if let Some(kernel) = mounts.get(0).map(|m| m.kernel()) {
2015                let mounts_guard = kernel.mounts_lock();
2016                let mounts = scopeguard::guard(mounts, |mounts| mounts_guard.defer_drop(mounts));
2017                for mount in &*mounts {
2018                    // Ignore errors.
2019                    let _ = mount.unmount(&mounts_guard, UnmountFlags::DETACH);
2020                }
2021            }
2022        }
2023    }
2024
2025    /// Drain mounts. For each drained mount, force a FileSystem unmount.
2026    // TODO(https://fxbug.dev/295073633): Graceful shutdown should try to first unmount the mounts
2027    // and only force a FileSystem unmount on failure.
2028    pub fn clear(&self) {
2029        for (_dir_entry, mounts) in self.mounts.lock().drain() {
2030            for mount in mounts {
2031                mount.fs.force_unmount_ops();
2032            }
2033        }
2034    }
2035
2036    pub fn sync_all(&self, current_task: &CurrentTask) -> Result<(), Errno> {
2037        let mut filesystems = Vec::new();
2038        {
2039            let scope = RcuReadScope::new();
2040            let mut seen = HashSet::new();
2041            for (_dir_entry, m_list) in self.mounts.iter(&scope) {
2042                for m in m_list {
2043                    if seen.insert(Arc::as_ptr(&m.fs)) {
2044                        filesystems.push(m.fs.clone());
2045                    }
2046                }
2047            }
2048        }
2049
2050        for fs in filesystems {
2051            if let Err(e) = fs.sync(current_task) {
2052                log_warn!("sync failed for filesystem {:?}: {:?}", fs.name(), e);
2053            }
2054        }
2055        Ok(())
2056    }
2057}
2058
2059impl Drop for Mount {
2060    fn drop(&mut self) {
2061        // Updating the RCU object without lock is acceptable because this Mount is not available
2062        // anymore by anything.
2063        let kernel = self.kernel();
2064        let peer_group = self.relations.peer_group.cloned();
2065        let upstream = self.relations.upstream.cloned();
2066        self.relations.peer_group.update(None);
2067        self.relations.upstream.update(None);
2068        if peer_group.is_some() || upstream.is_some() {
2069            register_delayed_call(move |_current_task| {
2070                let guard = kernel.mounts_lock();
2071                Mount::unregister_from_peer_group_and_upstream(&guard, peer_group, upstream);
2072            });
2073        }
2074    }
2075}
2076
2077impl fmt::Debug for Mount {
2078    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2079        let scope = RcuReadScope::new();
2080        f.debug_struct("Mount")
2081            .field("id", &(self as *const Mount))
2082            .field("root", &self.root)
2083            .field("mountpoint", &self.relations.mountpoint(&scope))
2084            .field("submounts", &self.relations.iter_submounts(&scope).collect::<Vec<_>>())
2085            .finish()
2086    }
2087}
2088
2089/// A RAII object that unregisters a mount when dropped.
2090#[derive(Debug)]
2091struct Submount {
2092    dir: ArcKey<DirEntry>,
2093    mount: MountHandle,
2094}
2095
2096impl Drop for Submount {
2097    fn drop(&mut self) {
2098        self.mount.kernel().mounts.unregister_mount(&self.dir, &self.mount)
2099    }
2100}
2101
2102/// Submount is stored in a mount's submounts hash set, which is keyed by the mountpoint.
2103impl Eq for Submount {}
2104impl PartialEq<Self> for Submount {
2105    fn eq(&self, other: &Self) -> bool {
2106        self.dir == other.dir
2107    }
2108}
2109impl Hash for Submount {
2110    fn hash<H: Hasher>(&self, state: &mut H) {
2111        self.dir.hash(state)
2112    }
2113}
2114
2115impl Borrow<ArcKey<DirEntry>> for Submount {
2116    fn borrow(&self) -> &ArcKey<DirEntry> {
2117        &self.dir
2118    }
2119}
2120
2121#[cfg(test)]
2122mod test {
2123    use crate::fs::tmpfs::TmpFs;
2124    use crate::testing::spawn_kernel_and_run;
2125    use crate::vfs::namespace::DeviceId;
2126    use crate::vfs::{
2127        CallbackSymlinkNode, FsNodeInfo, LookupContext, MountInfo, Namespace, NamespaceNode,
2128        RenameFlags, SymlinkMode, SymlinkTarget, UnlinkKind, WhatToMount,
2129    };
2130    use starnix_uapi::mount_flags::MountpointFlags;
2131    use starnix_uapi::{errno, mode};
2132    use std::sync::Arc;
2133
2134    #[::fuchsia::test]
2135    async fn test_namespace() {
2136        spawn_kernel_and_run(async |current_task| {
2137            let kernel = current_task.kernel();
2138            let root_fs = TmpFs::new_fs(&kernel);
2139            let root_node = Arc::clone(root_fs.root());
2140            let _dev_node =
2141                root_node.create_dir(&current_task, "dev".into()).expect("failed to mkdir dev");
2142            let dev_fs = TmpFs::new_fs(&kernel);
2143            let dev_root_node = Arc::clone(dev_fs.root());
2144            let _dev_pts_node =
2145                dev_root_node.create_dir(&current_task, "pts".into()).expect("failed to mkdir pts");
2146
2147            let ns = Namespace::new(root_fs);
2148            let mut context = LookupContext::default();
2149            let dev = ns
2150                .root()
2151                .lookup_child(&current_task, &mut context, "dev".into())
2152                .expect("failed to lookup dev");
2153            dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2154                .expect("failed to mount dev root node");
2155
2156            let mut context = LookupContext::default();
2157            let dev = ns
2158                .root()
2159                .lookup_child(&current_task, &mut context, "dev".into())
2160                .expect("failed to lookup dev");
2161            let mut context = LookupContext::default();
2162            let pts = dev
2163                .lookup_child(&current_task, &mut context, "pts".into())
2164                .expect("failed to lookup pts");
2165            let pts_parent =
2166                pts.parent().ok_or_else(|| errno!(ENOENT)).expect("failed to get parent of pts");
2167            assert!(Arc::ptr_eq(&pts_parent.entry, &dev.entry));
2168
2169            let dev_parent =
2170                dev.parent().ok_or_else(|| errno!(ENOENT)).expect("failed to get parent of dev");
2171            assert!(Arc::ptr_eq(&dev_parent.entry, &ns.root().entry));
2172        })
2173        .await;
2174    }
2175
2176    #[::fuchsia::test]
2177    async fn test_mount_does_not_upgrade() {
2178        spawn_kernel_and_run(async |current_task| {
2179            let kernel = current_task.kernel();
2180            let root_fs = TmpFs::new_fs(&kernel);
2181            let root_node = Arc::clone(root_fs.root());
2182            let _dev_node =
2183                root_node.create_dir(&current_task, "dev".into()).expect("failed to mkdir dev");
2184            let dev_fs = TmpFs::new_fs(&kernel);
2185            let dev_root_node = Arc::clone(dev_fs.root());
2186            let _dev_pts_node =
2187                dev_root_node.create_dir(&current_task, "pts".into()).expect("failed to mkdir pts");
2188
2189            let ns = Namespace::new(root_fs);
2190            let mut context = LookupContext::default();
2191            let dev = ns
2192                .root()
2193                .lookup_child(&current_task, &mut context, "dev".into())
2194                .expect("failed to lookup dev");
2195            dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2196                .expect("failed to mount dev root node");
2197            let mut context = LookupContext::default();
2198            let new_dev = ns
2199                .root()
2200                .lookup_child(&current_task, &mut context, "dev".into())
2201                .expect("failed to lookup dev again");
2202            assert!(!Arc::ptr_eq(&dev.entry, &new_dev.entry));
2203            assert_ne!(&dev, &new_dev);
2204
2205            let mut context = LookupContext::default();
2206            let _new_pts = new_dev
2207                .lookup_child(&current_task, &mut context, "pts".into())
2208                .expect("failed to lookup pts");
2209            let mut context = LookupContext::default();
2210            assert!(dev.lookup_child(&current_task, &mut context, "pts".into()).is_err());
2211        })
2212        .await;
2213    }
2214
2215    #[::fuchsia::test]
2216    async fn test_path() {
2217        spawn_kernel_and_run(async |current_task| {
2218            let kernel = current_task.kernel();
2219            let root_fs = TmpFs::new_fs(&kernel);
2220            let root_node = Arc::clone(root_fs.root());
2221            let _dev_node =
2222                root_node.create_dir(&current_task, "dev".into()).expect("failed to mkdir dev");
2223            let dev_fs = TmpFs::new_fs(&kernel);
2224            let dev_root_node = Arc::clone(dev_fs.root());
2225            let _dev_pts_node =
2226                dev_root_node.create_dir(&current_task, "pts".into()).expect("failed to mkdir pts");
2227
2228            let ns = Namespace::new(root_fs);
2229            let mut context = LookupContext::default();
2230            let dev = ns
2231                .root()
2232                .lookup_child(&current_task, &mut context, "dev".into())
2233                .expect("failed to lookup dev");
2234            dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2235                .expect("failed to mount dev root node");
2236
2237            let mut context = LookupContext::default();
2238            let dev = ns
2239                .root()
2240                .lookup_child(&current_task, &mut context, "dev".into())
2241                .expect("failed to lookup dev");
2242            let mut context = LookupContext::default();
2243            let pts = dev
2244                .lookup_child(&current_task, &mut context, "pts".into())
2245                .expect("failed to lookup pts");
2246
2247            assert_eq!("/", ns.root().path_escaping_chroot());
2248            assert_eq!("/dev", dev.path_escaping_chroot());
2249            assert_eq!("/dev/pts", pts.path_escaping_chroot());
2250        })
2251        .await;
2252    }
2253
2254    #[::fuchsia::test]
2255    async fn test_shadowing() {
2256        spawn_kernel_and_run(async |current_task| {
2257            let kernel = current_task.kernel();
2258            let root_fs = TmpFs::new_fs(&kernel);
2259            let ns = Namespace::new(root_fs.clone());
2260            let _foo_node = root_fs.root().create_dir(&current_task, "foo".into()).unwrap();
2261            let mut context = LookupContext::default();
2262            let foo_dir =
2263                ns.root().lookup_child(&current_task, &mut context, "foo".into()).unwrap();
2264
2265            let foofs1 = TmpFs::new_fs(&kernel);
2266            foo_dir.mount(WhatToMount::Fs(foofs1.clone()), MountpointFlags::empty()).unwrap();
2267            let mut context = LookupContext::default();
2268            assert!(Arc::ptr_eq(
2269                &ns.root().lookup_child(&current_task, &mut context, "foo".into()).unwrap().entry,
2270                foofs1.root()
2271            ));
2272            let foo_dir =
2273                ns.root().lookup_child(&current_task, &mut context, "foo".into()).unwrap();
2274
2275            let ns_clone = ns.clone_namespace(&kernel.mounts_lock());
2276
2277            let foofs2 = TmpFs::new_fs(&kernel);
2278            foo_dir.mount(WhatToMount::Fs(foofs2.clone()), MountpointFlags::empty()).unwrap();
2279            let mut context = LookupContext::default();
2280            assert!(Arc::ptr_eq(
2281                &ns.root().lookup_child(&current_task, &mut context, "foo".into()).unwrap().entry,
2282                foofs2.root()
2283            ));
2284
2285            assert!(Arc::ptr_eq(
2286                &ns_clone
2287                    .root()
2288                    .lookup_child(&current_task, &mut LookupContext::default(), "foo".into())
2289                    .unwrap()
2290                    .entry,
2291                foofs1.root()
2292            ));
2293        })
2294        .await;
2295    }
2296
2297    #[::fuchsia::test]
2298    async fn test_unlink_mounted_directory() {
2299        spawn_kernel_and_run(async |current_task| {
2300            let kernel = current_task.kernel();
2301            let root_fs = TmpFs::new_fs(&kernel);
2302            let ns1 = Namespace::new(root_fs.clone());
2303            let ns2 = Namespace::new(root_fs.clone());
2304            let _foo_node = root_fs.root().create_dir(&current_task, "foo".into()).unwrap();
2305            let mut context = LookupContext::default();
2306            let foo_dir =
2307                ns1.root().lookup_child(&current_task, &mut context, "foo".into()).unwrap();
2308
2309            let foofs = TmpFs::new_fs(&kernel);
2310            foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2311
2312            // Trying to unlink from ns1 should fail.
2313            assert_eq!(
2314                ns1.root()
2315                    .unlink(&current_task, "foo".into(), UnlinkKind::Directory, false)
2316                    .unwrap_err(),
2317                errno!(EBUSY),
2318            );
2319
2320            // But unlinking from ns2 should succeed.
2321            ns2.root()
2322                .unlink(&current_task, "foo".into(), UnlinkKind::Directory, false)
2323                .expect("unlink failed");
2324
2325            // And it should no longer show up in ns1.
2326            assert_eq!(
2327                ns1.root()
2328                    .unlink(&current_task, "foo".into(), UnlinkKind::Directory, false)
2329                    .unwrap_err(),
2330                errno!(ENOENT),
2331            );
2332        })
2333        .await;
2334    }
2335
2336    #[::fuchsia::test]
2337    async fn test_rename_mounted_directory() {
2338        spawn_kernel_and_run(async |current_task| {
2339            let kernel = current_task.kernel();
2340            let root_fs = TmpFs::new_fs(&kernel);
2341            let ns1 = Namespace::new(root_fs.clone());
2342            let ns2 = Namespace::new(root_fs.clone());
2343            let _foo_node = root_fs.root().create_dir(&current_task, "foo".into()).unwrap();
2344            let _bar_node = root_fs.root().create_dir(&current_task, "bar".into()).unwrap();
2345            let _baz_node = root_fs.root().create_dir(&current_task, "baz".into()).unwrap();
2346            let mut context = LookupContext::default();
2347            let foo_dir =
2348                ns1.root().lookup_child(&current_task, &mut context, "foo".into()).unwrap();
2349
2350            let foofs = TmpFs::new_fs(&kernel);
2351            foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2352
2353            // Trying to rename over foo from ns1 should fail.
2354            let root = ns1.root();
2355            assert_eq!(
2356                NamespaceNode::rename(
2357                    &current_task,
2358                    &root,
2359                    "bar".into(),
2360                    &root,
2361                    "foo".into(),
2362                    RenameFlags::empty()
2363                )
2364                .unwrap_err(),
2365                errno!(EBUSY),
2366            );
2367            // Likewise the other way.
2368            assert_eq!(
2369                NamespaceNode::rename(
2370                    &current_task,
2371                    &root,
2372                    "foo".into(),
2373                    &root,
2374                    "bar".into(),
2375                    RenameFlags::empty()
2376                )
2377                .unwrap_err(),
2378                errno!(EBUSY),
2379            );
2380
2381            // But renaming from ns2 should succeed.
2382            let root = ns2.root();
2383
2384            // First rename the directory with the mount.
2385            NamespaceNode::rename(
2386                &current_task,
2387                &root,
2388                "foo".into(),
2389                &root,
2390                "bar".into(),
2391                RenameFlags::empty(),
2392            )
2393            .expect("rename failed");
2394
2395            // Renaming over a directory with a mount should also work.
2396            NamespaceNode::rename(
2397                &current_task,
2398                &root,
2399                "baz".into(),
2400                &root,
2401                "bar".into(),
2402                RenameFlags::empty(),
2403            )
2404            .expect("rename failed");
2405
2406            // "foo" and "baz" should no longer show up in ns1.
2407            assert_eq!(
2408                ns1.root().lookup_child(&current_task, &mut context, "foo".into()).unwrap_err(),
2409                errno!(ENOENT)
2410            );
2411            assert_eq!(
2412                ns1.root().lookup_child(&current_task, &mut context, "baz".into()).unwrap_err(),
2413                errno!(ENOENT)
2414            );
2415        })
2416        .await;
2417    }
2418
2419    /// Symlinks which need to be traversed across types (nodes and paths), as well as across
2420    /// owning directories, can be tricky to get right.
2421    #[::fuchsia::test]
2422    async fn test_lookup_with_symlink_chain() {
2423        spawn_kernel_and_run(async |current_task| {
2424            // Set up the root filesystem
2425            let kernel = current_task.kernel();
2426            let root_fs = TmpFs::new_fs(&kernel);
2427            let root_node = Arc::clone(root_fs.root());
2428            let _first_subdir_node = root_node
2429                .create_dir(&current_task, "first_subdir".into())
2430                .expect("failed to mkdir dev");
2431            let _second_subdir_node = root_node
2432                .create_dir(&current_task, "second_subdir".into())
2433                .expect("failed to mkdir dev");
2434
2435            // Set up two subdirectories under the root filesystem
2436            let first_subdir_fs = TmpFs::new_fs(&kernel);
2437            let second_subdir_fs = TmpFs::new_fs(&kernel);
2438
2439            let ns = Namespace::new(root_fs);
2440            let mut context = LookupContext::default();
2441            let first_subdir = ns
2442                .root()
2443                .lookup_child(&current_task, &mut context, "first_subdir".into())
2444                .expect("failed to lookup first_subdir");
2445            first_subdir
2446                .mount(WhatToMount::Fs(first_subdir_fs), MountpointFlags::empty())
2447                .expect("failed to mount first_subdir fs node");
2448            let second_subdir = ns
2449                .root()
2450                .lookup_child(&current_task, &mut context, "second_subdir".into())
2451                .expect("failed to lookup second_subdir");
2452            second_subdir
2453                .mount(WhatToMount::Fs(second_subdir_fs), MountpointFlags::empty())
2454                .expect("failed to mount second_subdir fs node");
2455
2456            // Create the symlink structure. To trigger potential symlink traversal bugs, we're going
2457            // for the following directory structure:
2458            // / (root)
2459            //     + first_subdir/
2460            //         - real_file
2461            //         - path_symlink (-> real_file)
2462            //     + second_subdir/
2463            //         - node_symlink (-> path_symlink)
2464            let real_file_node = first_subdir
2465                .create_node(&current_task, "real_file".into(), mode!(IFREG, 0o777), DeviceId::NONE)
2466                .expect("failed to create real_file");
2467            first_subdir
2468                .create_symlink(&current_task, "path_symlink".into(), "real_file".into())
2469                .expect("failed to create path_symlink");
2470
2471            let mut no_follow_lookup_context = LookupContext::new(SymlinkMode::NoFollow);
2472            let path_symlink_node = first_subdir
2473                .lookup_child(&current_task, &mut no_follow_lookup_context, "path_symlink".into())
2474                .expect("Failed to lookup path_symlink");
2475
2476            // The second symlink needs to be of type SymlinkTarget::Node in order to trip the sensitive
2477            // code path. There's no easy method for creating this type of symlink target, so we'll need
2478            // to construct a node from scratch and insert it into the directory manually.
2479            let node_symlink_node = second_subdir.entry.node.fs().create_node_and_allocate_node_id(
2480                CallbackSymlinkNode::new(move || {
2481                    let node = path_symlink_node.clone();
2482                    Ok(SymlinkTarget::Node(node))
2483                }),
2484                FsNodeInfo::new(mode!(IFLNK, 0o777), current_task.current_fscred()),
2485            );
2486            second_subdir
2487                .entry
2488                .create_entry(
2489                    &current_task,
2490                    &MountInfo::detached(),
2491                    "node_symlink".into(),
2492                    move |_dir, _mount, _name| Ok(node_symlink_node),
2493                )
2494                .expect("failed to create node_symlink entry");
2495
2496            // Finally, exercise the lookup under test.
2497            let mut follow_lookup_context = LookupContext::new(SymlinkMode::Follow);
2498            let node_symlink_resolution = second_subdir
2499                .lookup_child(&current_task, &mut follow_lookup_context, "node_symlink".into())
2500                .expect("lookup with symlink chain failed");
2501
2502            // The lookup resolution should have correctly followed the symlinks to the real_file node.
2503            assert!(node_symlink_resolution.entry.node.ino == real_file_node.entry.node.ino);
2504        })
2505        .await;
2506    }
2507}