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