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