1use crate::security;
6use crate::task::{
7 CurrentTask, EventHandler, Kernel, MountsWriteToken, TaskContainer, WaitCanceler, Waiter,
8 register_delayed_call,
9};
10use crate::time::utc;
11use crate::vfs::fs_args::MountParams;
12use crate::vfs::fs_registry::FsRegistry;
13use crate::vfs::pseudo::dynamic_file::{DynamicFile, DynamicFileBuf, DynamicFileSource};
14use crate::vfs::pseudo::simple_file::SimpleFileNode;
15use crate::vfs::socket::{SocketAddress, SocketHandle, UnixSocket};
16use crate::vfs::{
17 AccessCheck, CreationStatus, DirEntry, DirEntryHandle, FileHandle, FileObject, FileOps,
18 FileSystem, FileSystemHandle, FileSystemOptions, FileWriteGuardMode, FsContext, FsNode,
19 FsNodeHandle, FsNodeOps, FsStr, FsString, OpenAccessCheck, PathBuilder, RenameFlags,
20 SymlinkTarget, UnlinkKind, fileops_impl_dataless, fileops_impl_delegate_read_write_and_seek,
21 fileops_impl_nonseekable, fileops_impl_noop_sync, fs_node_impl_not_dir,
22};
23use fuchsia_rcu::{RcuArc, RcuBox, RcuDroppable, RcuReadScope};
24use fuchsia_rcu_collections::rcu_raw_hash_map::RcuRawHashMap;
25use starnix_logging::log_warn;
26use starnix_sync::{LockDepMutex, MountSubmountsLock, MountsLock, NamespaceFlagsLock};
27use starnix_uapi::arc_key::{ArcKey, PtrKey, WeakKey};
28use starnix_uapi::auth::Credentials;
29use starnix_uapi::device_id::DeviceId;
30use starnix_uapi::errors::Errno;
31use starnix_uapi::file_mode::{Access, FileMode};
32use starnix_uapi::inotify_mask::InotifyMask;
33use starnix_uapi::mount_flags::{
34 AtomicMountpointFlags, FileSystemFlags, MountFlags, MountpointFlags,
35};
36use starnix_uapi::open_flags::OpenFlags;
37use starnix_uapi::unmount_flags::UnmountFlags;
38use starnix_uapi::vfs::{FdEvents, ResolveFlags};
39use starnix_uapi::{NAME_MAX, errno, error};
40use std::collections::{HashMap, HashSet};
41use std::fmt;
42use std::hash::{Hash, Hasher};
43use std::ops::{Deref, DerefMut};
44use std::sync::atomic::Ordering;
45use std::sync::{Arc, Weak};
46
47#[derive(Debug)]
51pub struct Namespace {
52 root_mount: MountHandle,
53
54 pub id: u64,
56}
57
58impl Namespace {
59 pub fn new(fs: FileSystemHandle) -> Arc<Namespace> {
60 Self::new_with_flags(fs, MountpointFlags::empty())
61 }
62
63 pub fn new_with_flags(fs: FileSystemHandle, flags: MountpointFlags) -> Arc<Namespace> {
64 let kernel = fs.kernel.upgrade().expect("can't create namespace without a kernel");
65 let mounts_guard = kernel.mounts_lock();
66
67 let root_mount = Mount::new(&mounts_guard, WhatToMount::Fs(fs), flags)
68 .expect("creating root mount for new filesystem");
69 Arc::new(Self { root_mount, id: kernel.get_next_namespace_id() })
70 }
71
72 pub fn root(&self) -> NamespaceNode {
73 self.root_mount.root()
74 }
75
76 pub(super) fn destroy_bootstrap(self: Arc<Self>) {
79 let ns = Arc::into_inner(self).expect("bootstrap namespace still referenced");
80 let root_mount =
81 Arc::into_inner(ns.root_mount).expect("bootstrap root mount still referenced");
82 assert_eq!(root_mount.active_clients(), 0);
83 assert_eq!(root_mount.relations.submounts_len(), 0);
84 assert_eq!(Arc::strong_count(&root_mount.fs), 1, "bootstrap filesystem still referenced");
85 assert_eq!(
89 Arc::strong_count(&root_mount.root),
90 2,
91 "bootstrap root directory must not have children or external references"
92 );
93 }
94
95 pub fn kernel(&self) -> Arc<Kernel> {
96 self.root_mount.kernel()
97 }
98
99 pub fn clone_namespace(&self, mounts_guard: &MountsWriteToken) -> Arc<Namespace> {
100 Arc::new(Self {
101 root_mount: self.root_mount.clone_mount_recursive(mounts_guard),
102 id: self.kernel().get_next_namespace_id(),
103 })
104 }
105
106 pub fn translate_node(
109 node: NamespaceNode,
110 new_ns: &Namespace,
111 mounts_guard: &MountsWriteToken,
112 ) -> Option<NamespaceNode> {
113 if node.mount.as_ref().is_some_and(|m| m.is_detached(mounts_guard)) {
114 return Some(node);
115 }
116 let mut node = mounts_guard.defer_drop(node);
117 let mut mountpoints = vec![];
119 let mut mount = node.mount.clone();
120 while let Some(mountpoint) = mount.as_ref().and_then(|m| m.mountpoint()) {
121 mountpoints.push(mountpoint.entry);
122 let prev = std::mem::replace(&mut mount, mountpoint.mount);
123 mounts_guard.defer_drop(prev);
124 }
125 mounts_guard.defer_drop(mount);
126 let mountpoints = mounts_guard.defer_drop(mountpoints);
127
128 let scope = RcuReadScope::new();
130 let mut mount = Arc::clone(&new_ns.root_mount);
131 for mountpoint in mountpoints.iter().rev() {
132 let next_mount = match mount.relations.get_submount(&scope, &PtrKey::from(mountpoint)) {
133 Some(m) => m,
134 None => {
135 mounts_guard.defer_drop(mount);
136 return None;
137 }
138 };
139 mounts_guard.defer_drop(std::mem::replace(&mut mount, next_mount));
140 }
141 mounts_guard.defer_drop(std::mem::replace(&mut node.mount, Some(mount).into()));
142 Some(scopeguard::ScopeGuard::into_inner(node))
143 }
144
145 pub fn pivot_root(
146 self: &Arc<Namespace>,
147 current_root: &NamespaceNode,
148 new_root: &NamespaceNode,
149 put_old: &NamespaceNode,
150 ) -> Result<(), Errno> {
151 debug_assert!(new_root.entry.node.is_dir());
152 debug_assert!(put_old.entry.node.is_dir());
153
154 let new_root_mount = new_root.mount.as_ref().ok_or_else(|| errno!(EINVAL))?;
155 let current_root_mount = current_root.mount.as_ref().ok_or_else(|| errno!(EINVAL))?;
156 let put_old_mount = put_old.mount.as_ref().ok_or_else(|| errno!(EINVAL))?;
157
158 if Arc::ptr_eq(new_root_mount, current_root_mount)
159 || Arc::ptr_eq(put_old_mount, current_root_mount)
160 {
161 return error!(EBUSY);
162 }
163
164 let current_root_mount = current_root.mount_if_root()?;
165 let new_root_mount = new_root.mount_if_root()?;
166
167 if !new_root.is_descendant_of(current_root) {
168 return error!(EINVAL);
169 }
170 if !put_old.is_descendant_of(new_root) {
171 return error!(EINVAL);
172 }
173
174 let kernel = self.kernel();
175 let mounts_guard = kernel.mounts_lock();
176
177 if put_old_mount.is_detached(&mounts_guard) {
180 return error!(EINVAL);
181 }
182
183 let current_root_mountpoint =
184 mounts_guard.defer_drop(current_root_mount.mountpoint().ok_or_else(|| errno!(EINVAL))?);
185 let new_root_mountpoint =
186 mounts_guard.defer_drop(new_root_mount.mountpoint().ok_or_else(|| errno!(EINVAL))?);
187
188 let new_root_parent = mounts_guard.retain(
193 new_root_mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount"),
194 );
195 mounts_guard.retain(&new_root_mountpoint.entry);
196
197 if new_root_mount.peer_group().is_some() || new_root_parent.peer_group().is_some() {
198 return error!(EINVAL);
199 }
200
201 if put_old_mount.peer_group().is_some() {
202 return error!(EINVAL);
203 }
204
205 if current_root_mount.peer_group().is_some() {
206 return error!(EINVAL);
207 }
208
209 let current_root_parent = mounts_guard.retain(
210 current_root_mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount"),
211 );
212 mounts_guard.retain(¤t_root_mountpoint.entry);
213 if current_root_parent.peer_group().is_some() {
214 return error!(EINVAL);
215 }
216
217 mounts_guard.retain(current_root_mount);
220 mounts_guard.retain(new_root_mount);
221 mounts_guard.retain(put_old_mount);
222 mounts_guard.retain(&put_old.entry);
223
224 new_root_parent
226 .remove_submount_internal(&mounts_guard, &new_root_mountpoint.mount_hash_key())?;
227
228 current_root_parent
230 .remove_submount_internal(&mounts_guard, ¤t_root_mountpoint.mount_hash_key())?;
231 current_root_parent.create_submount(
232 &mounts_guard,
233 ¤t_root_mountpoint.entry,
234 WhatSubmount::Existing(Arc::clone(new_root_mount)),
235 )?;
236
237 put_old_mount.create_submount(
239 &mounts_guard,
240 &put_old.entry,
241 WhatSubmount::Existing(Arc::clone(current_root_mount)),
242 )?;
243
244 Ok(())
245 }
246}
247
248impl FsNodeOps for Arc<Namespace> {
249 fs_node_impl_not_dir!();
250
251 fn create_file_ops(
252 &self,
253 _node: &FsNode,
254 _current_task: &CurrentTask,
255 _flags: OpenFlags,
256 ) -> Result<Box<dyn FileOps>, Errno> {
257 Ok(Box::new(MountNamespaceFile(self.clone())))
258 }
259}
260
261pub struct MountNamespaceFile(pub Arc<Namespace>);
262
263impl FileOps for MountNamespaceFile {
264 fileops_impl_nonseekable!();
265 fileops_impl_dataless!();
266 fileops_impl_noop_sync!();
267}
268
269type MountClientMarker = Arc<()>;
274
275pub struct Mount {
284 root: DirEntryHandle,
285 fs: FileSystemHandle,
286
287 flags: AtomicMountpointFlags,
289
290 flags_lock: LockDepMutex<(), NamespaceFlagsLock>,
292
293 id: u64,
295
296 active_client_counter: MountClientMarker,
298
299 relations: MountRelations,
306 }
313
314type MountHandle = Arc<Mount>;
315
316#[derive(Clone, Debug)]
318pub struct MountInfo {
319 handle: Option<MountHandle>,
320}
321
322impl MountInfo {
323 pub fn detached() -> Self {
326 None.into()
327 }
328
329 pub fn flags(&self) -> MountFlags {
331 if let Some(handle) = &self.handle {
332 handle.flags()
333 } else {
334 MountFlags::NOATIME
336 }
337 }
338
339 pub fn check_readonly_filesystem(&self) -> Result<(), Errno> {
341 if self.flags().contains(MountFlags::RDONLY) {
342 return error!(EROFS);
343 }
344 Ok(())
345 }
346
347 pub fn check_noexec_filesystem(&self) -> Result<(), Errno> {
349 if self.flags().contains(MountFlags::NOEXEC) {
350 return error!(EACCES);
351 }
352 Ok(())
353 }
354}
355
356impl Deref for MountInfo {
357 type Target = Option<MountHandle>;
358
359 fn deref(&self) -> &Self::Target {
360 &self.handle
361 }
362}
363
364impl DerefMut for MountInfo {
365 fn deref_mut(&mut self) -> &mut Self::Target {
366 &mut self.handle
367 }
368}
369
370impl std::cmp::PartialEq for MountInfo {
371 fn eq(&self, other: &Self) -> bool {
372 self.handle.as_ref().map(Arc::as_ptr) == other.handle.as_ref().map(Arc::as_ptr)
373 }
374}
375
376impl std::cmp::Eq for MountInfo {}
377
378impl Into<MountInfo> for Option<MountHandle> {
379 fn into(self) -> MountInfo {
380 MountInfo { handle: self }
381 }
382}
383
384#[derive(Clone, Debug, Default, RcuDroppable)]
386enum MountpointState {
387 #[default]
389 Root,
390 Attached { parent: Weak<Mount>, entry: Weak<DirEntry> },
392 Detached,
394}
395
396#[derive(Default)]
397struct MountRelations {
398 mountpoint: RcuBox<MountpointState>,
400 submounts: LockDepMutex<HashMap<PtrKey<DirEntry>, Submount>, MountSubmountsLock>,
402 submount_lookup: RcuRawHashMap<WeakKey<DirEntry>, Weak<Mount>>,
404 peer_group: RcuArc<PeerGroup>,
406 upstream: RcuBox<Option<(Weak<PeerGroup>, PtrKey<Mount>)>>,
408}
409
410impl MountRelations {
411 fn get_submount(
412 &self,
413 scope: &starnix_rcu::RcuReadScope,
414 key: &PtrKey<DirEntry>,
415 ) -> Option<MountHandle> {
416 self.submount_lookup.get(scope, key).and_then(|weak| weak.upgrade())
417 }
418
419 fn insert_submount(
420 &self,
421 _guard: &MountsWriteToken,
422 key: WeakKey<DirEntry>,
423 value: Weak<Mount>,
424 submount: Submount,
425 ) -> Option<Submount> {
426 let ptr_key = PtrKey::from(key.0.as_ptr());
427 let old_submount = self.submounts.lock().insert(ptr_key, submount);
428 let scope = starnix_rcu::RcuReadScope::new();
429 unsafe { self.submount_lookup.insert(&scope, key, value) };
431 old_submount
432 }
433
434 fn remove_submount(
435 &self,
436 guard: &MountsWriteToken,
437 key: &PtrKey<DirEntry>,
438 ) -> Result<Submount, Errno> {
439 let _ = unsafe { self.submount_lookup.remove(key) };
441 let submount = self.submounts.lock().remove(key).ok_or_else(|| errno!(EINVAL))?;
442 submount.mount.relations.detach_mountpoint(guard);
443 Ok(submount)
444 }
445
446 fn detach_submounts_recursive(&self, guard: &MountsWriteToken) {
452 let submounts: Vec<_> =
453 self.submounts.lock().drain().map(|(_, submount)| submount).collect();
454 if submounts.is_empty() {
455 return;
456 }
457 for submount in &submounts {
458 let key = PtrKey::from(&submount.dir);
459 let _ = unsafe { self.submount_lookup.remove(&key) };
461 submount.mount.relations.detach_mountpoint(guard);
462 submount.mount.make_private(guard);
463 submount.mount.relations.detach_submounts_recursive(guard);
464 }
465 guard.defer_drop(submounts);
466 }
467
468 fn iter_submounts<'a>(
469 &'a self,
470 scope: &'a starnix_rcu::RcuReadScope,
471 ) -> impl Iterator<Item = (&'a WeakKey<DirEntry>, &'a Weak<Mount>)> {
472 let mut cursor = self.submount_lookup.cursor(scope);
473 std::iter::from_fn(move || {
474 let current = cursor.current();
475 if current.is_some() {
476 cursor.advance();
477 }
478 current
479 })
480 }
481
482 fn submounts_len(&self) -> usize {
483 self.submount_lookup.len()
484 }
485
486 fn set_mountpoint(
487 &self,
488 _guard: &MountsWriteToken,
489 parent: Weak<Mount>,
490 entry: Weak<DirEntry>,
491 ) {
492 self.mountpoint.update(MountpointState::Attached { parent, entry });
493 }
494
495 fn detach_mountpoint(&self, _guard: &MountsWriteToken) {
496 self.mountpoint.update(MountpointState::Detached);
497 }
498
499 fn mountpoint<'a>(&'a self, scope: &'a starnix_rcu::RcuReadScope) -> &'a MountpointState {
500 self.mountpoint.as_ref(scope)
501 }
502
503 fn take_peer_group(&self, _guard: &MountsWriteToken) -> Option<Arc<PeerGroup>> {
504 let peer_group = self.peer_group.upgrade();
505 self.peer_group.update(None);
506 peer_group
507 }
508
509 fn take_upstream(&self, _guard: &MountsWriteToken) -> Option<(Weak<PeerGroup>, PtrKey<Mount>)> {
510 let upstream = self.upstream.cloned();
511 self.upstream.update(None);
512 upstream
513 }
514}
515
516#[derive(Default)]
520struct PeerGroup {
521 id: u64,
522 mounts: RcuRawHashMap<WeakKey<Mount>, ()>,
523 downstream: RcuRawHashMap<WeakKey<Mount>, ()>,
524}
525
526pub enum WhatToMount {
527 Fs(FileSystemHandle),
528 Bind(NamespaceNode),
529}
530
531enum WhatSubmount {
532 New(WhatToMount, MountpointFlags),
533 Existing(MountHandle),
534}
535
536impl Mount {
537 pub fn new(
538 mounts_guard: &MountsWriteToken,
539 what: WhatToMount,
540 mut flags: MountpointFlags,
541 ) -> Result<MountHandle, Errno> {
542 let what = mounts_guard.defer_drop(what);
543 match &*what {
544 WhatToMount::Fs(fs) => {
545 flags.default_atime_from(MountpointFlags::RELATIME);
547 Ok(Self::new_with_root(fs.root().clone(), flags))
548 }
549 WhatToMount::Bind(node) => {
550 let mount = node.mount.as_ref().ok_or_else(|| errno!(ENOENT))?;
553 if mount.is_detached(mounts_guard) {
555 return error!(EINVAL);
556 }
557 Ok(mount.clone_mount(mounts_guard, &node.entry, flags.into()))
558 }
559 }
560 }
561
562 fn new_with_root(root: DirEntryHandle, flags: MountpointFlags) -> MountHandle {
563 let fs = root.node.fs();
564 let kernel = fs.kernel.upgrade().expect("can't create mount without kernel");
565 Arc::new(Self {
566 id: kernel.get_next_mount_id(),
567 flags: (flags & MountpointFlags::STORED_ON_MOUNT).into(),
568 flags_lock: Default::default(),
569 root,
570 active_client_counter: Default::default(),
571 fs,
572 relations: Default::default(),
573 })
574 }
575
576 pub fn root(self: &MountHandle) -> NamespaceNode {
578 NamespaceNode::new(Arc::clone(self), Arc::clone(&self.root))
579 }
580
581 fn kernel(&self) -> Arc<Kernel> {
582 self.fs.kernel.upgrade().expect("No Kernel")
583 }
584
585 fn create_submount(
587 self: &MountHandle,
588 mounts_guard: &MountsWriteToken,
589 dir: &DirEntryHandle,
590 what: WhatSubmount,
591 ) -> Result<(), Errno> {
592 let peers = self.peer_group().map(|g| g.copy_propagation_targets()).unwrap_or_default();
595 let peers = mounts_guard.defer_drop(peers);
596
597 let mount = match what {
602 WhatSubmount::Existing(mount) => mount,
603 WhatSubmount::New(what, flags) => Mount::new(mounts_guard, what, flags)?,
604 };
605
606 if self.is_shared() {
607 mount.make_shared(mounts_guard);
608 }
609
610 for peer in &*peers {
611 if Arc::ptr_eq(self, peer) {
612 continue;
613 }
614 let clone = mount.clone_mount_recursive(mounts_guard);
615 peer.add_submount_internal(mounts_guard, dir, clone);
616 }
617
618 self.add_submount_internal(mounts_guard, dir, mount);
619 Ok(())
620 }
621
622 fn remove_submount(
623 self: &MountHandle,
624 mounts_guard: &MountsWriteToken,
625 mount_hash_key: &PtrKey<DirEntry>,
626 ) -> Result<(), Errno> {
627 let peers = self.peer_group().map(|g| g.copy_propagation_targets()).unwrap_or_default();
629 let peers = mounts_guard.defer_drop(peers);
630
631 for peer in &*peers {
632 if Arc::ptr_eq(self, peer) {
633 continue;
634 }
635 let submount = {
639 let scope = RcuReadScope::new();
640 peer.relations.get_submount(&scope, mount_hash_key)
641 };
642 if let Some(submount) = submount {
643 let submount = mounts_guard.defer_drop(submount);
644 if submount.relations.submounts_len() != 0 {
645 continue;
646 }
647 submount.make_private(mounts_guard);
648 }
649 let _ = peer.remove_submount_internal(mounts_guard, mount_hash_key);
650 }
651
652 let submount = self.relations.remove_submount(mounts_guard, mount_hash_key)?;
653 submount.mount.make_private(mounts_guard);
654 submount.mount.relations.detach_submounts_recursive(mounts_guard);
655 mounts_guard.defer_drop(submount);
656 Ok(())
657 }
658
659 pub fn move_mount(
660 source_mount: &MountHandle,
661 target_mount: &MountHandle,
662 target_dir: &DirEntryHandle,
663 ) -> Result<(), Errno> {
664 let kernel = target_mount.kernel();
665 let mounts_guard = kernel.mounts_lock();
666 if source_mount.is_detached(&mounts_guard) || target_mount.is_detached(&mounts_guard) {
668 return error!(EINVAL);
669 }
670
671 let source_mountpoint = source_mount.mountpoint().ok_or_else(|| errno!(EIO))?;
672 let source_mountpoint = mounts_guard.defer_drop(source_mountpoint);
673 let source_parent = mounts_guard.retain(
674 source_mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount"),
675 );
676
677 {
679 if source_parent.peer_group().is_some() {
680 return error!(EINVAL);
684 }
685 source_parent
686 .remove_submount_internal(&mounts_guard, &source_mountpoint.mount_hash_key())?;
687 }
688
689 target_mount.create_submount(
690 &mounts_guard,
691 target_dir,
692 WhatSubmount::Existing(Arc::clone(source_mount)),
693 )?;
694 Ok(())
695 }
696
697 fn clone_mount(
700 self: &MountHandle,
701 mounts_guard: &MountsWriteToken,
702 new_root: &DirEntryHandle,
703 flags: MountFlags,
704 ) -> MountHandle {
705 assert!(new_root.is_descendant_of(&self.root));
706 let clone = Self::new_with_root(Arc::clone(new_root), self.mount_flags());
709
710 if flags.contains(MountFlags::REC) {
711 let submounts: Vec<_> = {
712 let scope = RcuReadScope::new();
713 self.relations
714 .iter_submounts(&scope)
715 .filter_map(|(dir, submount)| {
716 let dir = dir.0.upgrade()?;
717 if !dir.is_descendant_of(new_root) {
718 return None;
719 }
720 Some((dir, submount.upgrade()?))
721 })
722 .collect()
723 };
724 if !submounts.is_empty() {
725 let submounts = mounts_guard.defer_drop(submounts);
726 for (dir, submount) in &*submounts {
727 let submount = submount.clone_mount_recursive(mounts_guard);
728 clone.add_submount_internal_unchecked(mounts_guard, dir, submount);
729 }
730 }
731 }
732
733 let peer_group = self.peer_group();
735 if let Some(peer_group) = peer_group {
736 let peer_group = mounts_guard.defer_drop(peer_group);
737 clone.set_peer_group(mounts_guard, Arc::clone(&peer_group));
738 }
739
740 clone
741 }
742
743 fn clone_mount_recursive(self: &MountHandle, mounts_guard: &MountsWriteToken) -> MountHandle {
746 self.clone_mount(mounts_guard, &self.root, MountFlags::REC)
747 }
748
749 pub fn change_propagation(
750 self: &MountHandle,
751 mounts_guard: &MountsWriteToken,
752 flag: MountFlags,
753 recursive: bool,
754 ) {
755 match flag {
756 MountFlags::SHARED => self.make_shared(mounts_guard),
757 MountFlags::PRIVATE => self.make_private(mounts_guard),
758 MountFlags::DOWNSTREAM => self.make_downstream(mounts_guard),
759 _ => {
760 log_warn!("mount propagation {:?}", flag);
761 }
762 }
763
764 if recursive {
765 let submounts: Vec<_> = {
766 let scope = starnix_rcu::RcuReadScope::new();
767 self.relations
768 .iter_submounts(&scope)
769 .filter_map(|(_, submount)| submount.upgrade())
770 .collect()
771 };
772 let submounts = mounts_guard.defer_drop(submounts);
773 for submount in &*submounts {
774 submount.change_propagation(mounts_guard, flag, recursive);
775 }
776 }
777 }
778
779 fn flags(&self) -> MountFlags {
782 MountFlags::from(self.mount_flags()) | self.fs_flags().into()
783 }
784
785 fn mount_flags(&self) -> MountpointFlags {
787 self.flags.load(Ordering::Relaxed)
788 }
789
790 fn fs_flags(&self) -> FileSystemFlags {
792 self.fs.options.flags.load(Ordering::Relaxed)
793 }
794
795 pub fn update_flags(self: &MountHandle, mut flags: MountpointFlags) {
798 let _lock = self.flags_lock.lock();
799 flags.default_atime_from(self.flags.load(Ordering::Relaxed));
804 flags &= MountpointFlags::STORED_ON_MOUNT;
805 self.flags.store(flags, Ordering::Relaxed);
806 }
807
808 fn active_clients(&self) -> usize {
812 Arc::strong_count(&self.active_client_counter) - 1
814 }
815
816 pub fn unmount(
817 &self,
818 mounts_guard: &MountsWriteToken,
819 flags: UnmountFlags,
820 ) -> Result<(), Errno> {
821 if self.is_detached(mounts_guard) {
824 return error!(EINVAL);
825 }
826 if !flags.contains(UnmountFlags::DETACH) {
827 if self.active_clients() > 0 || self.relations.submounts_len() != 0 {
828 return error!(EBUSY);
829 }
830 }
831
832 let mountpoint = self.mountpoint().ok_or_else(|| errno!(EINVAL))?;
833 let mountpoint = mounts_guard.defer_drop(mountpoint);
834 let parent_mount = mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount");
835 parent_mount.remove_submount(mounts_guard, &mountpoint.mount_hash_key())
836 }
837
838 pub fn security_state(&self) -> &security::FileSystemState {
840 &self.fs.security_state
841 }
842
843 pub fn fs_name(&self) -> &'static FsStr {
845 self.fs.name()
846 }
847
848 pub fn reconfigure_fs(
850 &self,
851 current_task: &CurrentTask,
852 flags: FileSystemFlags,
853 params: &MountParams,
854 ) -> Result<(), Errno> {
855 self.fs.reconfigure(current_task, flags, params)
856 }
857
858 pub fn has_submount(&self, dir_entry: &DirEntryHandle) -> bool {
860 let scope = RcuReadScope::new();
861 self.relations.get_submount(&scope, &PtrKey::from(dir_entry)).is_some()
862 }
863
864 pub(super) fn is_detached(&self, _mounts_guard: &MountsWriteToken) -> bool {
866 let scope = RcuReadScope::new();
872 matches!(self.relations.mountpoint(&scope), MountpointState::Detached)
873 }
874
875 pub fn mountpoint(&self) -> Option<NamespaceNode> {
877 let scope = RcuReadScope::new();
878 match self.relations.mountpoint(&scope) {
879 MountpointState::Attached { parent, entry } => {
880 Some(NamespaceNode::new(parent.upgrade()?, entry.upgrade()?))
881 }
882 MountpointState::Root | MountpointState::Detached => None,
883 }
884 }
885
886 pub fn add_submount_internal(
888 self: &MountHandle,
889 guard: &MountsWriteToken,
890 dir: &DirEntryHandle,
891 mount: MountHandle,
892 ) {
893 if !dir.is_descendant_of(&self.root) {
894 guard.defer_drop(mount);
895 return;
896 }
897 self.add_submount_internal_unchecked(guard, dir, mount);
898 }
899
900 fn add_submount_internal_unchecked(
902 self: &MountHandle,
903 guard: &MountsWriteToken,
904 dir: &DirEntryHandle,
905 mount: MountHandle,
906 ) {
907 debug_assert!(dir.is_descendant_of(&self.root));
908 let mount = guard.defer_drop(mount);
909
910 let submount = mount.kernel().mounts.register_mount(dir, Arc::clone(&mount));
911
912 assert!(
916 !matches!(
917 mount.relations.mountpoint(&RcuReadScope::new()),
918 MountpointState::Attached { .. }
919 ),
920 "add_submount can only take an unattached mount"
921 );
922 mount.relations.set_mountpoint(guard, Arc::downgrade(self), Arc::downgrade(dir));
923
924 let old_mount = self.relations.insert_submount(
925 guard,
926 WeakKey::from(dir),
927 Arc::downgrade(&mount),
928 submount,
929 );
930 if let Some(old_mount) = old_mount {
931 let old_mount = guard.defer_drop(old_mount);
932 old_mount.mount.relations.set_mountpoint(
933 guard,
934 Arc::downgrade(&mount),
935 Arc::downgrade(&mount.root),
936 );
937 let new_old_submount =
938 mount.kernel().mounts.register_mount(&mount.root, old_mount.mount.clone());
939 let replaced = mount.relations.insert_submount(
940 guard,
941 WeakKey::from(&mount.root),
942 Arc::downgrade(&old_mount.mount),
943 new_old_submount,
944 );
945 if let Some(replaced) = replaced {
946 guard.defer_drop(replaced);
947 }
948 }
949 }
950
951 pub fn remove_submount_internal(
952 self: &MountHandle,
953 guard: &MountsWriteToken,
954 mount_hash_key: &PtrKey<DirEntry>,
955 ) -> Result<(), Errno> {
956 let submount = self.relations.remove_submount(guard, mount_hash_key)?;
957 guard.defer_drop(submount);
958 Ok(())
959 }
960
961 fn peer_group(&self) -> Option<Arc<PeerGroup>> {
963 self.relations.peer_group.upgrade()
964 }
965
966 fn unregister_from_peer_group_and_upstream(
969 guard: &MountsWriteToken,
970 peer_group: Option<Arc<PeerGroup>>,
971 upstream: Option<(Weak<PeerGroup>, PtrKey<Mount>)>,
972 mount_ptr: PtrKey<Mount>,
973 ) {
974 let peer_group = guard.defer_drop(peer_group);
975 let upstream_group = match upstream {
976 Some((weak_group, mount)) => {
977 if let Some(group) = weak_group.upgrade() {
978 group.remove_downstream(guard, mount);
979 Some(group)
980 } else {
981 None
982 }
983 }
984 None => None,
985 };
986 let upstream_group = guard.defer_drop(upstream_group);
987
988 if let Some(group) = &*peer_group {
989 group.remove(guard, mount_ptr);
990
991 if let Some(upstream_group) = &*upstream_group {
992 let next_mount = {
993 let scope = RcuReadScope::new();
994 group.mounts.keys(&scope).next().and_then(|w| w.0.upgrade())
995 };
996 if let Some(next_mount) = next_mount {
997 let next_mount = guard.defer_drop(next_mount);
998 next_mount.set_upstream(guard, upstream_group);
999 }
1000 }
1001 }
1002 }
1003
1004 fn take_from_peer_group(&self, guard: &MountsWriteToken) -> Option<Arc<PeerGroup>> {
1006 let peer_group = self.relations.take_peer_group(guard);
1007 if peer_group.is_none() {
1008 return None;
1009 }
1010 let upstream = self.relations.take_upstream(guard);
1011 let return_group = peer_group.clone();
1012 Mount::unregister_from_peer_group_and_upstream(
1013 guard,
1014 peer_group,
1015 upstream,
1016 PtrKey::from(self),
1017 );
1018 return_group
1019 }
1020
1021 fn upstream(&self) -> Option<Arc<PeerGroup>> {
1022 let scope = RcuReadScope::new();
1023 let (group, _) = self.relations.upstream.as_ref(&scope).as_ref()?;
1024 group.upgrade()
1025 }
1026
1027 fn remove_from_upstream(&self, guard: &MountsWriteToken) {
1028 let upstream = self.relations.take_upstream(guard);
1029 if let Some((weak_group, mount)) = upstream {
1030 if let Some(group) = weak_group.upgrade() {
1031 group.remove_downstream(guard, mount);
1032 guard.defer_drop(group);
1033 }
1034 }
1035 }
1036
1037 fn set_peer_group(self: &Arc<Mount>, guard: &MountsWriteToken, group: Arc<PeerGroup>) {
1039 if let Some(prev) = self.take_from_peer_group(guard) {
1040 guard.defer_drop(prev);
1041 }
1042 group.add(guard, self);
1043 self.relations.peer_group.update(Some(group));
1044 }
1045
1046 fn set_upstream(self: &Arc<Mount>, guard: &MountsWriteToken, group: &Arc<PeerGroup>) {
1047 self.remove_from_upstream(guard);
1048 group.add_downstream(guard, self);
1049 self.relations.upstream.update(Some((Arc::downgrade(group), Arc::as_ptr(self).into())));
1050 }
1051
1052 pub fn is_shared(&self) -> bool {
1054 self.relations.peer_group.is_some()
1055 }
1056
1057 fn make_shared(self: &Arc<Mount>, guard: &MountsWriteToken) {
1059 if self.is_shared() {
1060 return;
1061 }
1062 let kernel = self.kernel();
1063 self.set_peer_group(guard, PeerGroup::new(kernel.get_next_peer_group_id()))
1064 }
1065
1066 fn make_private(&self, guard: &MountsWriteToken) {
1068 let peer_group = self.relations.take_peer_group(guard);
1069 let upstream = self.relations.take_upstream(guard);
1070 Mount::unregister_from_peer_group_and_upstream(
1071 guard,
1072 peer_group,
1073 upstream,
1074 PtrKey::from(self),
1075 );
1076 }
1077
1078 fn make_downstream(self: &Arc<Mount>, guard: &MountsWriteToken) {
1081 if let Some(peer_group) = self.take_from_peer_group(guard) {
1082 let peer_group = guard.defer_drop(peer_group);
1083 self.set_upstream(guard, &peer_group);
1084 }
1085 }
1086}
1087
1088impl PeerGroup {
1089 fn new(id: u64) -> Arc<Self> {
1090 Arc::new(Self {
1091 id,
1092 mounts: RcuRawHashMap::default(),
1093 downstream: RcuRawHashMap::default(),
1094 })
1095 }
1096
1097 fn add(&self, _guard: &MountsWriteToken, mount: &Arc<Mount>) {
1098 unsafe { self.mounts.insert(&starnix_rcu::RcuReadScope::new(), WeakKey::from(mount), ()) };
1100 }
1101
1102 fn remove(&self, _guard: &MountsWriteToken, mount: PtrKey<Mount>) {
1103 unsafe { self.mounts.remove(&mount) };
1105 }
1106
1107 fn add_downstream(&self, _guard: &MountsWriteToken, mount: &Arc<Mount>) {
1108 unsafe {
1110 self.downstream.insert(&starnix_rcu::RcuReadScope::new(), WeakKey::from(mount), ())
1111 };
1112 }
1113
1114 fn remove_downstream(&self, _guard: &MountsWriteToken, mount: PtrKey<Mount>) {
1115 unsafe { self.downstream.remove(&mount) };
1117 }
1118
1119 fn copy_propagation_targets(&self) -> Vec<MountHandle> {
1120 let mut buf = vec![];
1121 self.collect_propagation_targets(&mut buf);
1122 buf
1123 }
1124
1125 fn collect_propagation_targets(&self, buf: &mut Vec<MountHandle>) {
1126 let downstream_mounts: Vec<_> = {
1127 let scope = RcuReadScope::new();
1128 buf.extend(self.mounts.keys(&scope).filter_map(|m| m.0.upgrade()));
1129 self.downstream.keys(&scope).filter_map(|m| m.0.upgrade()).collect()
1130 };
1131 for mount in downstream_mounts {
1132 let peer_group = mount.peer_group();
1133 match peer_group {
1134 Some(group) => group.collect_propagation_targets(buf),
1135 None => buf.push(mount),
1136 }
1137 }
1138 }
1139}
1140
1141impl Kernel {
1142 pub fn get_next_mount_id(&self) -> u64 {
1143 self.next_mount_id.next()
1144 }
1145
1146 pub fn get_next_peer_group_id(&self) -> u64 {
1147 self.next_peer_group_id.next()
1148 }
1149
1150 pub fn get_next_namespace_id(&self) -> u64 {
1151 self.next_namespace_id.next()
1152 }
1153}
1154
1155impl CurrentTask {
1156 pub fn create_filesystem(
1157 &self,
1158 fs_type: &FsStr,
1159 options: FileSystemOptions,
1160 ) -> Result<FileSystemHandle, Errno> {
1161 self.kernel()
1168 .expando
1169 .get::<FsRegistry>()
1170 .create(self, fs_type, options)
1171 .ok_or_else(|| errno!(ENODEV, fs_type))?
1172 }
1173}
1174
1175struct ProcMountsFileSource {
1176 target: TaskContainer,
1177}
1178
1179impl DynamicFileSource for ProcMountsFileSource {
1180 fn generate(
1181 &self,
1182 _current_task: &CurrentTask,
1183 sink: &mut DynamicFileBuf,
1184 ) -> Result<(), Errno> {
1185 let task = self.target.get_task()?;
1190 let task_fs = task.fs()?;
1191 let root = task_fs.root();
1192 let ns = task_fs.namespace();
1193 for_each_mount(&ns.root_mount, &mut |mount| {
1194 let mountpoint = mount.mountpoint().unwrap_or_else(|| mount.root());
1195 if !mountpoint.is_descendant_of(&root) {
1196 return Ok(());
1197 }
1198 write!(
1199 sink,
1200 "{} {} {} {}{}",
1201 mount.fs.options.source_for_display(),
1202 mountpoint.path(&task_fs),
1203 mount.fs.name(),
1204 mount.flags(),
1207 mount.fs.format_options(&task.kernel())?,
1208 )?;
1209 writeln!(sink, " 0 0")?;
1210 Ok(())
1211 })?;
1212 Ok(())
1213 }
1214}
1215
1216pub struct ProcMountsFile {
1217 dynamic_file: DynamicFile<ProcMountsFileSource>,
1218}
1219
1220impl ProcMountsFile {
1221 pub fn new_node(target: TaskContainer) -> impl FsNodeOps {
1222 SimpleFileNode::new(move |_| {
1223 Ok(Self {
1224 dynamic_file: DynamicFile::new(ProcMountsFileSource { target: target.clone() }),
1225 })
1226 })
1227 }
1228}
1229
1230impl FileOps for ProcMountsFile {
1231 fileops_impl_delegate_read_write_and_seek!(self, self.dynamic_file);
1232 fileops_impl_noop_sync!();
1233
1234 fn wait_async(
1235 &self,
1236 _file: &FileObject,
1237 _current_task: &CurrentTask,
1238 waiter: &Waiter,
1239 _events: FdEvents,
1240 _handler: EventHandler,
1241 ) -> Option<WaitCanceler> {
1242 Some(waiter.fake_wait())
1245 }
1246
1247 fn query_events(
1248 &self,
1249 _file: &FileObject,
1250 _current_task: &CurrentTask,
1251 ) -> Result<FdEvents, Errno> {
1252 Ok(FdEvents::empty())
1253 }
1254}
1255
1256#[derive(Clone)]
1257pub struct ProcMountinfoFile {
1258 target: TaskContainer,
1259}
1260impl ProcMountinfoFile {
1261 pub fn new_node(target: TaskContainer) -> impl FsNodeOps {
1262 DynamicFile::new_node(Self { target })
1263 }
1264}
1265impl DynamicFileSource for ProcMountinfoFile {
1266 fn generate(
1267 &self,
1268 _current_task: &CurrentTask,
1269 sink: &mut DynamicFileBuf,
1270 ) -> Result<(), Errno> {
1271 fn path_from_fs_root(dir: &DirEntryHandle) -> FsString {
1273 let mut path = PathBuilder::new();
1274 if dir.is_dead() {
1275 path.prepend_element("/deleted".into());
1277 }
1278 let scope = RcuReadScope::new();
1279 let mut current = dir.clone();
1280 while let Some(parent) = current.parent() {
1281 path.prepend_element(current.local_name(&scope));
1282 current = parent;
1283 }
1284 path.build_absolute()
1285 }
1286
1287 let task = self.target.get_task()?;
1292 let task_fs = task.fs()?;
1293 let root = task_fs.root();
1294 let ns = task_fs.namespace();
1295 for_each_mount(&ns.root_mount, &mut |mount| {
1296 let mountpoint = mount.mountpoint().unwrap_or_else(|| mount.root());
1297 if !mountpoint.is_descendant_of(&root) {
1298 return Ok(());
1299 }
1300 let parent = mountpoint.mount.as_ref().unwrap();
1302 write!(
1303 sink,
1304 "{} {} {} {} {} {}",
1305 mount.id,
1306 parent.id,
1307 mount.root.node.fs().dev_id,
1308 path_from_fs_root(&mount.root),
1309 mountpoint.path(&task_fs),
1310 mount.mount_flags(),
1311 )?;
1312 if let Some(peer_group) = mount.peer_group() {
1313 write!(sink, " shared:{}", peer_group.id)?;
1314 }
1315 if let Some(upstream) = mount.upstream() {
1316 write!(sink, " master:{}", upstream.id)?;
1317 }
1318 writeln!(
1319 sink,
1320 " - {} {} {}{}",
1321 mount.fs.name(),
1322 mount.fs.options.source_for_display(),
1323 mount.fs_flags(),
1324 mount.fs.format_options(&task.kernel())?,
1327 )?;
1328 Ok(())
1329 })?;
1330 Ok(())
1331 }
1332}
1333
1334fn for_each_mount<E>(
1335 mount: &MountHandle,
1336 callback: &mut impl FnMut(&MountHandle) -> Result<(), E>,
1337) -> Result<(), E> {
1338 callback(mount)?;
1339 for (_, s) in mount.relations.iter_submounts(&RcuReadScope::new()) {
1340 if let Some(submount) = s.upgrade() {
1341 for_each_mount(&submount, callback)?;
1342 }
1343 }
1344 Ok(())
1345}
1346
1347#[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
1349pub enum SymlinkMode {
1350 #[default]
1352 Follow,
1353
1354 NoFollow,
1356}
1357
1358#[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
1360pub enum DirectoryMode {
1361 #[default]
1363 AllowAny,
1364
1365 MustBeDirectory,
1367}
1368
1369pub const MAX_SYMLINK_FOLLOWS: u8 = 40;
1371
1372pub struct LookupContext {
1377 pub symlink_mode: SymlinkMode,
1382
1383 pub remaining_follows: u8,
1387
1388 pub directory_mode: DirectoryMode,
1394
1395 pub resolve_flags: ResolveFlags,
1397
1398 pub resolve_base: ResolveBase,
1401}
1402
1403#[derive(Clone, Eq, PartialEq)]
1406pub enum ResolveBase {
1407 None,
1408
1409 Beneath(NamespaceNode),
1411
1412 InRoot(NamespaceNode),
1414}
1415
1416impl LookupContext {
1417 pub fn new(symlink_mode: SymlinkMode) -> LookupContext {
1418 LookupContext {
1419 symlink_mode,
1420 remaining_follows: MAX_SYMLINK_FOLLOWS,
1421 directory_mode: DirectoryMode::default(),
1422 resolve_flags: ResolveFlags::empty(),
1423 resolve_base: ResolveBase::None,
1424 }
1425 }
1426
1427 pub fn with(&self, symlink_mode: SymlinkMode, directory_mode: DirectoryMode) -> LookupContext {
1428 LookupContext {
1429 symlink_mode,
1430 directory_mode,
1431 resolve_base: self.resolve_base.clone(),
1432 ..*self
1433 }
1434 }
1435
1436 pub fn update_for_path(&mut self, path: &FsStr) {
1437 if path.last() == Some(&b'/') {
1438 self.directory_mode = DirectoryMode::MustBeDirectory;
1441 self.symlink_mode = SymlinkMode::Follow;
1444 }
1445 }
1446}
1447
1448impl Default for LookupContext {
1449 fn default() -> Self {
1450 LookupContext::new(SymlinkMode::Follow)
1451 }
1452}
1453
1454pub enum PathWithReachability {
1456 Reachable(FsString),
1458
1459 Unreachable(FsString),
1461}
1462
1463impl PathWithReachability {
1464 pub fn into_path(self) -> FsString {
1465 match self {
1466 PathWithReachability::Reachable(path) => path,
1467 PathWithReachability::Unreachable(path) => path,
1468 }
1469 }
1470}
1471
1472#[derive(Clone)]
1480pub struct NamespaceNode {
1481 pub mount: MountInfo,
1486
1487 pub entry: DirEntryHandle,
1489}
1490
1491impl NamespaceNode {
1492 pub fn new(mount: MountHandle, entry: DirEntryHandle) -> Self {
1493 Self { mount: Some(mount).into(), entry }
1494 }
1495
1496 pub fn new_anonymous(entry: DirEntryHandle) -> Self {
1498 Self { mount: None.into(), entry }
1499 }
1500
1501 pub fn new_anonymous_unrooted(current_task: &CurrentTask, node: FsNodeHandle) -> Self {
1504 let dir_entry = DirEntry::new_unrooted(node);
1505 let _ = security::fs_node_init_with_dentry_no_xattr(current_task, &dir_entry);
1506 Self::new_anonymous(dir_entry)
1507 }
1508
1509 pub fn open(
1515 &self,
1516 current_task: &CurrentTask,
1517 open_check: impl Into<OpenAccessCheck>,
1518 ) -> Result<FileHandle, Errno> {
1519 let open_check = open_check.into();
1520 let ops = self.entry.node.open(current_task, self, open_check)?;
1521 FileObject::new(current_task, ops, self.clone(), open_check.open_flags())
1522 }
1523
1524 pub fn open_create_node(
1532 &self,
1533 current_task: &CurrentTask,
1534 name: &FsStr,
1535 mode: FileMode,
1536 dev: DeviceId,
1537 ) -> Result<(NamespaceNode, CreationStatus), Errno> {
1538 let owner = current_task.current_fscred();
1539 let mode = current_task.fs().apply_umask(mode);
1540 let (entry, status) = self.entry.get_or_create_entry(
1541 current_task,
1542 &self.mount,
1543 name,
1544 |dir, mount, name| dir.create_node(current_task, mount, name, mode, dev, owner),
1545 )?;
1546 Ok((self.with_new_entry(entry), status))
1547 }
1548
1549 pub fn into_active(self) -> ActiveNamespaceNode {
1550 ActiveNamespaceNode::new(self)
1551 }
1552
1553 pub fn create_node(
1559 &self,
1560 current_task: &CurrentTask,
1561 name: &FsStr,
1562 mode: FileMode,
1563 dev: DeviceId,
1564 ) -> Result<NamespaceNode, Errno> {
1565 let owner = current_task.current_fscred();
1566 let mode = current_task.fs().apply_umask(mode);
1567 let entry =
1568 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1569 dir.create_node(current_task, mount, name, mode, dev, owner)
1570 })?;
1571 Ok(self.with_new_entry(entry))
1572 }
1573
1574 pub fn create_symlink(
1578 &self,
1579 current_task: &CurrentTask,
1580 name: &FsStr,
1581 target: &FsStr,
1582 ) -> Result<NamespaceNode, Errno> {
1583 let owner = current_task.current_fscred();
1584 let entry =
1585 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1586 dir.create_symlink(current_task, mount, name, target, owner)
1587 })?;
1588 Ok(self.with_new_entry(entry))
1589 }
1590
1591 pub fn create_tmpfile(
1597 &self,
1598 current_task: &CurrentTask,
1599 mode: FileMode,
1600 flags: OpenFlags,
1601 ) -> Result<NamespaceNode, Errno> {
1602 let owner = current_task.current_fscred();
1603 let mode = current_task.fs().apply_umask(mode);
1604 Ok(self.with_new_entry(self.entry.create_tmpfile(
1605 current_task,
1606 &self.mount,
1607 mode,
1608 owner,
1609 flags,
1610 )?))
1611 }
1612
1613 pub fn link(
1614 &self,
1615 current_task: &CurrentTask,
1616 name: &FsStr,
1617 child: &FsNodeHandle,
1618 ) -> Result<NamespaceNode, Errno> {
1619 let dir_entry =
1620 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1621 dir.link(current_task, mount, name, child)
1622 })?;
1623 Ok(self.with_new_entry(dir_entry))
1624 }
1625
1626 pub fn bind_socket(
1629 &self,
1630 current_task: &CurrentTask,
1631 name: &FsStr,
1632 socket: SocketHandle,
1633 socket_address: SocketAddress,
1634 mode: FileMode,
1635 ) -> Result<NamespaceNode, Errno> {
1636 let dir_entry =
1637 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1638 let node = dir.create_node(
1639 current_task,
1640 mount,
1641 name,
1642 mode,
1643 DeviceId::NONE,
1644 current_task.current_fscred(),
1645 )?;
1646 if let Some(unix_socket) = socket.downcast_socket::<UnixSocket>() {
1647 unix_socket.bind_socket_to_node(&socket, socket_address, &node)?;
1648 } else {
1649 return error!(ENOTSUP);
1650 }
1651 Ok(node)
1652 })?;
1653 Ok(self.with_new_entry(dir_entry))
1654 }
1655
1656 pub fn unlink(
1657 &self,
1658 current_task: &CurrentTask,
1659 name: &FsStr,
1660 kind: UnlinkKind,
1661 directory_mode: DirectoryMode,
1662 ) -> Result<(), Errno> {
1663 if DirEntry::is_reserved_name(name) {
1664 match kind {
1665 UnlinkKind::Directory => {
1666 if name == ".." {
1667 error!(ENOTEMPTY)
1668 } else if self.parent().is_none() {
1669 error!(EBUSY)
1671 } else {
1672 error!(EINVAL)
1673 }
1674 }
1675 UnlinkKind::NonDirectory => error!(ENOTDIR),
1676 }
1677 } else {
1678 self.entry.unlink(current_task, &self.mount, name, kind, directory_mode)
1679 }
1680 }
1681
1682 fn resolve(
1686 self,
1687 current_task: &CurrentTask,
1688 context: &mut LookupContext,
1689 ) -> Result<NamespaceNode, Errno> {
1690 let mut node = self;
1691
1692 loop {
1693 if !node.entry.node.is_lnk() || context.symlink_mode == SymlinkMode::NoFollow {
1694 break;
1695 }
1696 if context.remaining_follows == 0
1697 || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
1698 {
1699 return error!(ELOOP);
1700 }
1701 context.remaining_follows -= 1;
1702 node = match node.readlink(current_task)? {
1703 SymlinkTarget::Path(link_target) => {
1704 let link_directory = if link_target[0] == b'/' {
1705 match &context.resolve_base {
1707 ResolveBase::None => current_task.fs().root(),
1708 ResolveBase::Beneath(_) => return error!(EXDEV),
1709 ResolveBase::InRoot(root) => root.clone(),
1710 }
1711 } else {
1712 node.parent().unwrap_or(node)
1716 };
1717 current_task.lookup_path(context, link_directory, link_target.as_ref())?
1718 }
1719 SymlinkTarget::Node(node) => {
1720 if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS) {
1721 return error!(ELOOP);
1722 }
1723 node
1724 }
1725 };
1726 }
1727 Ok(node.enter_mount())
1728 }
1729
1730 pub fn lookup_child(
1732 &self,
1733 current_task: &CurrentTask,
1734 context: &mut LookupContext,
1735 basename: &FsStr,
1736 ) -> Result<NamespaceNode, Errno> {
1737 self.lookup_children(current_task, context, &[basename])
1738 }
1739
1740 pub fn resolve_child(
1746 &self,
1747 current_task: &CurrentTask,
1748 context: &mut LookupContext,
1749 child: NamespaceNode,
1750 ) -> Result<NamespaceNode, Errno> {
1751 let child = child.resolve(current_task, context)?;
1752 if context.resolve_flags.contains(ResolveFlags::NO_XDEV) && child.mount != self.mount {
1753 return error!(EXDEV);
1754 }
1755 if context.directory_mode == DirectoryMode::MustBeDirectory && !child.entry.node.is_dir() {
1756 return error!(ENOTDIR);
1757 }
1758 Ok(child)
1759 }
1760
1761 pub fn lookup_children(
1763 &self,
1764 current_task: &CurrentTask,
1765 context: &mut LookupContext,
1766 mut basenames: &[&FsStr],
1767 ) -> Result<NamespaceNode, Errno> {
1768 for name in basenames {
1769 if name.len() > NAME_MAX as usize {
1770 return error!(ENAMETOOLONG);
1771 }
1772 }
1773
1774 let mut current_namespace_node = self.clone();
1775
1776 while basenames.len() > 0 {
1777 if !current_namespace_node.entry.node.is_dir() {
1778 return error!(ENOTDIR);
1779 }
1780
1781 let basename = basenames[0];
1782 if basename.is_empty() {
1783 basenames = &basenames[1..];
1784 continue;
1785 }
1786 if basename == "." {
1787 current_namespace_node
1788 .check_access(current_task, AccessCheck::for_internal(Access::EXEC))?;
1789 basenames = &basenames[1..];
1790 continue;
1791 }
1792 if basename == ".." {
1793 current_namespace_node
1794 .check_access(current_task, AccessCheck::for_internal(Access::EXEC))?;
1795 let root = match &context.resolve_base {
1796 ResolveBase::None => current_task.fs().root(),
1797 ResolveBase::Beneath(node) => {
1798 if current_namespace_node == *node {
1800 return error!(EXDEV);
1801 }
1802 current_task.fs().root()
1803 }
1804 ResolveBase::InRoot(root) => root.clone(),
1805 };
1806
1807 if current_namespace_node != root {
1809 current_namespace_node =
1810 current_namespace_node.parent().unwrap_or(current_namespace_node)
1811 }
1812 if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1813 && current_namespace_node.mount != self.mount
1814 {
1815 return error!(EXDEV);
1816 }
1817
1818 if context.directory_mode == DirectoryMode::MustBeDirectory
1819 && !current_namespace_node.entry.node.is_dir()
1820 {
1821 return error!(ENOTDIR);
1822 }
1823 basenames = &basenames[1..];
1824 continue;
1825 }
1826 if basenames.len() == 1
1827 || !current_namespace_node.entry.node.ops().has_lookup_pipelined()
1828 {
1829 let child = current_namespace_node.with_new_entry(
1830 current_namespace_node.entry.component_lookup(
1831 current_task,
1832 ¤t_namespace_node.mount,
1833 basename,
1834 )?,
1835 );
1836 current_namespace_node =
1837 current_namespace_node.resolve_child(current_task, context, child)?;
1838 basenames = &basenames[1..];
1839 continue;
1840 }
1841
1842 let pipelined_basenames = if let Some(pos) =
1843 basenames.iter().position(|&name| name.is_empty() || name == "." || name == "..")
1844 {
1845 &basenames[..pos]
1846 } else {
1847 basenames
1848 };
1849 let precomputed_entries = current_namespace_node.entry.get_children_pipelined(
1850 current_task,
1851 ¤t_namespace_node.mount,
1852 pipelined_basenames,
1853 );
1854 for entry in precomputed_entries {
1855 basenames = &basenames[1..];
1856 let child = current_namespace_node.with_new_entry(entry?);
1857 current_namespace_node =
1858 current_namespace_node.resolve_child(current_task, context, child.clone())?;
1859 if current_namespace_node != child {
1860 break;
1861 }
1862 }
1863 }
1864
1865 Ok(current_namespace_node)
1866 }
1867
1868 pub fn parent(&self) -> Option<NamespaceNode> {
1874 let mountpoint_or_self = self.escape_mount();
1875 let parent = mountpoint_or_self.entry.parent()?;
1876 Some(mountpoint_or_self.with_new_entry(parent))
1877 }
1878
1879 pub fn parent_within_mount(&self) -> Option<DirEntryHandle> {
1882 if let Ok(_) = self.mount_if_root() {
1883 return None;
1884 }
1885 self.entry.parent()
1886 }
1887
1888 pub fn is_descendant_of(&self, ancestor: &NamespaceNode) -> bool {
1893 let ancestor = ancestor.escape_mount();
1894 let mut current = self.escape_mount();
1895 while current != ancestor {
1896 if let Some(parent) = current.parent() {
1897 current = parent.escape_mount();
1898 } else {
1899 return false;
1900 }
1901 }
1902 true
1903 }
1904
1905 fn enter_one_mount(&self) -> Option<NamespaceNode> {
1910 if !self.entry.has_mounts() {
1911 return None;
1912 }
1913 if let Some(mount) = self.mount.deref() {
1914 if let Some(submount) =
1915 mount.relations.get_submount(&RcuReadScope::new(), &PtrKey::from(&self.entry))
1916 {
1917 return Some(submount.root());
1918 }
1919 }
1920 None
1921 }
1922
1923 fn enter_mount(self) -> NamespaceNode {
1928 if !self.entry.has_mounts() {
1935 return self;
1936 }
1937 let kernel = self.entry.node.fs().kernel.upgrade().expect("kernel");
1939 kernel.mounts_lock.read_seq(|| {
1940 let mut inner = self.clone();
1941 while let Some(inner_root) = inner.enter_one_mount() {
1942 inner = inner_root;
1943 }
1944 inner
1945 })
1946 }
1947
1948 fn enter_mount_locked(&self, _mounts_guard: &MountsWriteToken) -> NamespaceNode {
1954 let mut inner = self.clone();
1956 while let Some(inner_root) = inner.enter_one_mount() {
1957 inner = inner_root;
1958 }
1959 inner
1960 }
1961
1962 fn escape_mount(&self) -> NamespaceNode {
1967 let kernel = self.entry.node.fs().kernel.upgrade().expect("kernel");
1968 kernel.mounts_lock.read_seq(|| {
1969 let mut mountpoint_or_self = self.clone();
1970 while let Some(mountpoint) = mountpoint_or_self.mountpoint() {
1971 mountpoint_or_self = mountpoint;
1972 }
1973 mountpoint_or_self
1974 })
1975 }
1976
1977 pub fn mount_if_root(&self) -> Result<&MountHandle, Errno> {
1979 if let Some(mount) = self.mount.deref() {
1980 if Arc::ptr_eq(&self.entry, &mount.root) {
1981 return Ok(mount);
1982 }
1983 }
1984 error!(EINVAL)
1985 }
1986
1987 fn mountpoint(&self) -> Option<NamespaceNode> {
1992 self.mount_if_root().ok()?.mountpoint()
1993 }
1994
1995 pub fn path(&self, fs: &FsContext) -> FsString {
1997 self.path_from_root(Some(&fs.root())).into_path()
1998 }
1999
2000 pub fn path_escaping_chroot(&self) -> FsString {
2002 self.path_from_root(None).into_path()
2003 }
2004
2005 pub fn path_from_root(&self, root: Option<&NamespaceNode>) -> PathWithReachability {
2008 if self.mount.is_none() {
2009 return self.unrooted_path();
2010 }
2011
2012 let mut path = PathBuilder::new();
2013 let mut current = self.escape_mount();
2014 if let Some(root) = root {
2015 let scope = RcuReadScope::new();
2016 let root = root.escape_mount();
2018 while current != root {
2019 if let Some(parent) = current.parent() {
2020 path.prepend_element(current.entry.local_name(&scope));
2021 current = parent.escape_mount();
2022 } else {
2023 let mut absolute_path = path.build_absolute();
2025 if self.entry.is_dead() {
2026 absolute_path.extend_from_slice(b" (deleted)");
2027 }
2028
2029 return PathWithReachability::Unreachable(absolute_path);
2030 }
2031 }
2032 } else {
2033 let scope = RcuReadScope::new();
2035 while let Some(parent) = current.parent() {
2036 path.prepend_element(current.entry.local_name(&scope));
2037 current = parent.escape_mount();
2038 }
2039 }
2040
2041 let mut absolute_path = path.build_absolute();
2042 if self.entry.is_dead() {
2043 absolute_path.extend_from_slice(b" (deleted)");
2044 }
2045
2046 PathWithReachability::Reachable(absolute_path)
2047 }
2048
2049 fn unrooted_path(&self) -> PathWithReachability {
2050 let scope = RcuReadScope::new();
2051 let mode = self.entry.node.info().mode;
2052 let local_name = self.entry.local_name(&scope);
2053 let path = if !local_name.is_empty() {
2054 format!("anon_inode:{}", local_name)
2055 } else if mode.is_sock() {
2056 format!("socket:[{}]", self.entry.node.ino)
2057 } else if mode.is_fifo() {
2058 format!("pipe:[{}]", self.entry.node.ino)
2059 } else {
2060 format!("file:[{}]", self.entry.node.ino)
2061 };
2062 PathWithReachability::Reachable(path.into())
2063 }
2064
2065 pub fn mount(&self, what: WhatToMount, flags: MountpointFlags) -> Result<(), Errno> {
2066 let target = self.clone().enter_mount();
2067
2068 if target.mount.is_none() {
2071 return error!(ENOENT);
2072 }
2073
2074 let source_is_dir = match &what {
2075 WhatToMount::Fs(fs) => fs.root().node.is_dir(),
2076 WhatToMount::Bind(node) => node.entry.node.is_dir(),
2077 };
2078
2079 if source_is_dir != target.entry.node.is_dir() {
2082 return error!(ENOTDIR);
2083 }
2084
2085 let kernel = self.entry.node.fs().kernel.upgrade().expect("can't mount without a kernel");
2086 let mounts_guard = kernel.mounts_lock();
2087 let what = mounts_guard.defer_drop(what);
2088 let mountpoint = self.enter_mount_locked(&mounts_guard);
2089 let mountpoint = mounts_guard.defer_drop(mountpoint);
2090
2091 let mount = mountpoint.mount.as_ref().ok_or_else(|| errno!(ENOENT))?;
2092 if mount.is_detached(&mounts_guard) {
2094 return error!(EINVAL);
2095 }
2096 let writeable_mount = mounts_guard.retain(mount);
2097 let writeable_entry = mounts_guard.retain(&mountpoint.entry);
2098 writeable_mount.create_submount(
2099 &mounts_guard,
2100 &writeable_entry,
2101 WhatSubmount::New(scopeguard::ScopeGuard::into_inner(what), flags),
2102 )
2103 }
2104
2105 pub fn unmount(&self, flags: UnmountFlags) -> Result<(), Errno> {
2107 let kernel = self.entry.node.fs().kernel.upgrade().expect("can't mount without a kernel");
2108 let mounts_guard = kernel.mounts_lock();
2109
2110 let mountpoint = self.enter_mount_locked(&mounts_guard);
2111 let mountpoint = mounts_guard.defer_drop(mountpoint);
2112 let mount = mounts_guard.retain(mountpoint.mount_if_root()?);
2113 mount.unmount(&mounts_guard, flags)
2114 }
2115
2116 pub fn rename(
2117 current_task: &CurrentTask,
2118 old_parent: &NamespaceNode,
2119 old_name: &FsStr,
2120 new_parent: &NamespaceNode,
2121 new_name: &FsStr,
2122 flags: RenameFlags,
2123 ) -> Result<(), Errno> {
2124 DirEntry::rename(
2125 current_task,
2126 &old_parent.entry,
2127 &old_parent.mount,
2128 old_name,
2129 &new_parent.entry,
2130 &new_parent.mount,
2131 new_name,
2132 flags,
2133 )
2134 }
2135
2136 fn with_new_entry(&self, entry: DirEntryHandle) -> NamespaceNode {
2137 Self { mount: self.mount.clone(), entry }
2138 }
2139
2140 fn mount_hash_key(&self) -> PtrKey<DirEntry> {
2141 PtrKey::from(&self.entry)
2142 }
2143
2144 pub fn apply_suid_and_sgid(&self, creds: &mut Credentials) {
2145 if self.mount.flags().contains(MountFlags::NOSUID) {
2151 return;
2152 }
2153 self.entry.node.info().apply_suid_and_sgid(creds)
2154 }
2155
2156 pub fn update_atime(&self) {
2157 if !self.mount.flags().intersects(MountFlags::NOATIME | MountFlags::RDONLY) {
2159 self.entry.node.update_info(|info| {
2160 let now = utc::utc_now();
2161 info.time_access = now;
2162 info.pending_time_access_update = true;
2163 });
2164 }
2165 }
2166
2167 pub fn readlink(&self, current_task: &CurrentTask) -> Result<SymlinkTarget, Errno> {
2168 self.update_atime();
2169 self.entry.node.readlink(current_task)
2170 }
2171
2172 pub fn notify(&self, event_mask: InotifyMask) {
2173 if self.mount.is_some() {
2174 self.entry.notify(event_mask);
2175 }
2176 }
2177
2178 pub fn check_access(
2182 &self,
2183 current_task: &CurrentTask,
2184 access_check: AccessCheck,
2185 ) -> Result<(), Errno> {
2186 self.entry.node.check_access(
2187 current_task,
2188 &self.mount,
2189 access_check.permission_flags(),
2190 access_check.reason(),
2191 self,
2192 )
2193 }
2194
2195 pub fn check_o_noatime_allowed(&self, current_task: &CurrentTask) -> Result<(), Errno> {
2197 self.entry.node.check_o_noatime_allowed(current_task)
2198 }
2199
2200 pub fn truncate(&self, current_task: &CurrentTask, length: u64) -> Result<(), Errno> {
2201 self.entry.node.truncate(current_task, &self.mount, length)?;
2202 self.entry.notify_ignoring_excl_unlink(InotifyMask::MODIFY);
2203 Ok(())
2204 }
2205}
2206
2207impl fmt::Debug for NamespaceNode {
2208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2209 f.debug_struct("NamespaceNode")
2210 .field("path", &self.path_escaping_chroot())
2211 .field("mount", &self.mount)
2212 .field("entry", &self.entry)
2213 .finish()
2214 }
2215}
2216
2217impl PartialEq for NamespaceNode {
2219 fn eq(&self, other: &Self) -> bool {
2220 self.mount.as_ref().map(Arc::as_ptr).eq(&other.mount.as_ref().map(Arc::as_ptr))
2221 && Arc::ptr_eq(&self.entry, &other.entry)
2222 }
2223}
2224impl Eq for NamespaceNode {}
2225impl Hash for NamespaceNode {
2226 fn hash<H: Hasher>(&self, state: &mut H) {
2227 self.mount.as_ref().map(Arc::as_ptr).hash(state);
2228 Arc::as_ptr(&self.entry).hash(state);
2229 }
2230}
2231
2232#[derive(Debug, Clone)]
2234pub struct ActiveNamespaceNode {
2235 name: NamespaceNode,
2237
2238 _marker: Option<MountClientMarker>,
2242}
2243
2244impl ActiveNamespaceNode {
2245 pub fn new(name: NamespaceNode) -> Self {
2246 let marker = name.mount.as_ref().map(|mount| mount.active_client_counter.clone());
2247 Self { name, _marker: marker }
2248 }
2249
2250 pub fn to_passive(&self) -> NamespaceNode {
2251 self.deref().clone()
2252 }
2253}
2254
2255impl Deref for ActiveNamespaceNode {
2256 type Target = NamespaceNode;
2257
2258 fn deref(&self) -> &Self::Target {
2259 &self.name
2260 }
2261}
2262
2263impl PartialEq for ActiveNamespaceNode {
2264 fn eq(&self, other: &Self) -> bool {
2265 self.deref().eq(other.deref())
2266 }
2267}
2268impl Eq for ActiveNamespaceNode {}
2269impl Hash for ActiveNamespaceNode {
2270 fn hash<H: Hasher>(&self, state: &mut H) {
2271 self.deref().hash(state)
2272 }
2273}
2274
2275#[derive(Debug, Clone)]
2278#[must_use]
2279pub struct FileMapping {
2280 file: FileHandle,
2281 mode: Option<FileWriteGuardMode>,
2282}
2283
2284impl FileMapping {
2285 pub fn new(file: FileHandle, mode: Option<FileWriteGuardMode>) -> Result<Arc<Self>, Errno> {
2287 if let Some(mode) = mode {
2288 file.name.entry.node.write_guard_state.lock().acquire(mode)?;
2289 }
2290 Ok(Arc::new(Self { file, mode }))
2291 }
2292
2293 pub fn file(&self) -> &FileHandle {
2295 &self.file
2296 }
2297
2298 pub fn name(&self) -> &ActiveNamespaceNode {
2300 &self.file.name
2301 }
2302
2303 pub fn node(&self) -> &FsNodeHandle {
2305 self.file.node()
2306 }
2307}
2308
2309impl PartialEq for FileMapping {
2310 fn eq(&self, other: &Self) -> bool {
2311 Arc::ptr_eq(&self.file, &other.file) && self.mode == other.mode
2312 }
2313}
2314
2315impl Eq for FileMapping {}
2316
2317impl Drop for FileMapping {
2318 fn drop(&mut self) {
2319 if let Some(mode) = self.mode {
2320 self.file.name.entry.node.write_guard_state.lock().release(mode);
2321 }
2322 }
2323}
2324
2325pub struct Mounts {
2327 mounts: LockDepMutex<HashMap<PtrKey<DirEntry>, Vec<Weak<Mount>>>, MountsLock>,
2328}
2329
2330impl Mounts {
2331 pub fn new() -> Self {
2332 Mounts { mounts: LockDepMutex::default() }
2333 }
2334
2335 fn register_mount(&self, dir_entry: &DirEntryHandle, mount: MountHandle) -> Submount {
2337 let mut mounts = self.mounts.lock();
2338 if let Some(vec) = mounts.get_mut(&PtrKey::from(dir_entry)) {
2339 vec.push(Arc::downgrade(&mount));
2340 } else {
2341 dir_entry.set_has_mounts(true);
2342 mounts.insert(PtrKey::from(dir_entry), vec![Arc::downgrade(&mount)]);
2343 }
2344 Submount { dir: dir_entry.clone(), mount }
2345 }
2346
2347 fn unregister_mount(&self, dir_entry: &DirEntryHandle, mount: &MountHandle) {
2349 let mut mounts = self.mounts.lock();
2350 let key = PtrKey::from(dir_entry);
2351 let mount_ptr = Arc::as_ptr(mount);
2352 let remove_entry = if let Some(vec) = mounts.get_mut(&key) {
2353 let index = vec.iter().position(|e| e.as_ptr() == mount_ptr).unwrap();
2354 vec.swap_remove(index);
2355 vec.is_empty()
2356 } else {
2357 false
2358 };
2359 if remove_entry {
2360 mounts.remove(&key);
2361 dir_entry.set_has_mounts(false);
2362 }
2363 }
2364
2365 pub fn unmount(&self, dir_entry: &DirEntry) {
2369 let Some(kernel) = dir_entry.node.fs().kernel.upgrade() else {
2370 return;
2371 };
2372 let mounts_guard = kernel.mounts_lock();
2373 let mounts = self.mounts.lock().remove(&PtrKey::from(dir_entry));
2374 if let Some(mounts) = mounts {
2375 let upgraded: Vec<_> = mounts.iter().filter_map(Weak::upgrade).collect();
2376 let mounts = mounts_guard.defer_drop(upgraded);
2377 for mount in &*mounts {
2378 let _ = mount.unmount(&mounts_guard, UnmountFlags::DETACH);
2380 }
2381 }
2382 }
2383
2384 pub fn clear(&self) {
2388 let drained = std::mem::take(&mut *self.mounts.lock());
2389 for (_dir_entry, mounts) in drained {
2390 for mount in mounts {
2391 if let Some(mount) = mount.upgrade() {
2392 mount.fs.force_unmount_ops();
2393 }
2394 }
2395 }
2396 }
2397
2398 fn unique_filesystems(&self) -> HashSet<ArcKey<FileSystem>> {
2401 let mut filesystems = HashSet::new();
2402 let mut queue = Vec::new();
2403 let mounts: Vec<Weak<Mount>> = self.mounts.lock().values().flatten().cloned().collect();
2404 for m in mounts {
2405 if let Some(mount) = m.upgrade() {
2406 if filesystems.insert(ArcKey(mount.fs.clone())) {
2407 queue.push(mount.fs.clone());
2408 }
2409 }
2410 }
2411 while let Some(fs) = queue.pop() {
2412 for sub_fs in fs.sub_filesystems() {
2413 if filesystems.insert(ArcKey(sub_fs.clone())) {
2414 queue.push(sub_fs);
2415 }
2416 }
2417 }
2418 filesystems
2419 }
2420
2421 pub fn sync_all(&self, current_task: &CurrentTask) -> Result<(), Errno> {
2422 for fs in self.unique_filesystems() {
2423 if let Err(e) = fs.sync(current_task) {
2424 log_warn!("sync failed for filesystem {:?}: {:?}", fs.name(), e);
2425 }
2426 }
2427 Ok(())
2428 }
2429
2430 pub fn drop_caches(&self) {
2431 let filesystems = self.unique_filesystems();
2432 for fs in &filesystems {
2435 fs.purge_dcache();
2436 }
2437 for fs in &filesystems {
2438 fs.drop_backend_caches();
2439 }
2440 }
2441}
2442
2443impl Drop for Mount {
2444 fn drop(&mut self) {
2445 let kernel = self.kernel();
2448 let peer_group = self.relations.peer_group.upgrade();
2449 let upstream = self.relations.upstream.cloned();
2450 self.relations.peer_group.update(None);
2451 self.relations.upstream.update(None);
2452 if peer_group.is_some() || upstream.is_some() {
2453 let mount_ptr = PtrKey::from(self as &Mount);
2454 register_delayed_call(move |_current_task| {
2455 let guard = kernel.mounts_lock();
2456 Mount::unregister_from_peer_group_and_upstream(
2457 &guard, peer_group, upstream, mount_ptr,
2458 );
2459 });
2460 }
2461 }
2462}
2463
2464impl fmt::Debug for Mount {
2465 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2466 let scope = RcuReadScope::new();
2467 f.debug_struct("Mount")
2468 .field("id", &(self as *const Mount))
2469 .field("root", &self.root)
2470 .field("mountpoint", &self.relations.mountpoint(&scope))
2471 .field(
2472 "submounts",
2473 &self
2474 .relations
2475 .iter_submounts(&scope)
2476 .filter_map(|(_, m)| m.upgrade())
2477 .collect::<Vec<_>>(),
2478 )
2479 .finish()
2480 }
2481}
2482
2483#[derive(Debug)]
2485struct Submount {
2486 dir: DirEntryHandle,
2487 mount: MountHandle,
2488}
2489
2490impl Drop for Submount {
2491 fn drop(&mut self) {
2492 self.mount.kernel().mounts.unregister_mount(&self.dir, &self.mount)
2493 }
2494}
2495
2496#[cfg(test)]
2497mod test {
2498 use crate::fs::tmpfs::TmpFs;
2499 use crate::testing::spawn_kernel_and_run;
2500 use crate::vfs::namespace::DeviceId;
2501 use crate::vfs::{
2502 CallbackSymlinkNode, DirectoryMode, FsNodeInfo, LookupContext, MountInfo, Namespace,
2503 NamespaceNode, RenameFlags, SymlinkMode, SymlinkTarget, UnlinkKind, WhatToMount,
2504 };
2505 use starnix_uapi::arc_key::PtrKey;
2506 use starnix_uapi::mount_flags::MountpointFlags;
2507 use starnix_uapi::unmount_flags::UnmountFlags;
2508 use starnix_uapi::{errno, mode};
2509 use std::sync::Arc;
2510
2511 #[::fuchsia::test]
2512 async fn test_namespace() {
2513 spawn_kernel_and_run(async |current_task| {
2514 let kernel = current_task.kernel();
2515 let root_fs = TmpFs::new_fs(&kernel);
2516 let root_node = Arc::clone(root_fs.root());
2517 let _dev_node =
2518 root_node.create_dir(¤t_task, "dev".into()).expect("failed to mkdir dev");
2519 let dev_fs = TmpFs::new_fs(&kernel);
2520 let dev_root_node = Arc::clone(dev_fs.root());
2521 let _dev_pts_node =
2522 dev_root_node.create_dir(¤t_task, "pts".into()).expect("failed to mkdir pts");
2523
2524 let ns = Namespace::new(root_fs);
2525 let mut context = LookupContext::default();
2526 let dev = ns
2527 .root()
2528 .lookup_child(¤t_task, &mut context, "dev".into())
2529 .expect("failed to lookup dev");
2530 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2531 .expect("failed to mount dev root node");
2532
2533 let mut context = LookupContext::default();
2534 let dev = ns
2535 .root()
2536 .lookup_child(¤t_task, &mut context, "dev".into())
2537 .expect("failed to lookup dev");
2538 let mut context = LookupContext::default();
2539 let pts = dev
2540 .lookup_child(¤t_task, &mut context, "pts".into())
2541 .expect("failed to lookup pts");
2542 let pts_parent =
2543 pts.parent().ok_or_else(|| errno!(ENOENT)).expect("failed to get parent of pts");
2544 assert!(Arc::ptr_eq(&pts_parent.entry, &dev.entry));
2545
2546 let dev_parent =
2547 dev.parent().ok_or_else(|| errno!(ENOENT)).expect("failed to get parent of dev");
2548 assert!(Arc::ptr_eq(&dev_parent.entry, &ns.root().entry));
2549 })
2550 .await;
2551 }
2552
2553 #[::fuchsia::test]
2554 async fn test_mount_does_not_upgrade() {
2555 spawn_kernel_and_run(async |current_task| {
2556 let kernel = current_task.kernel();
2557 let root_fs = TmpFs::new_fs(&kernel);
2558 let root_node = Arc::clone(root_fs.root());
2559 let _dev_node =
2560 root_node.create_dir(¤t_task, "dev".into()).expect("failed to mkdir dev");
2561 let dev_fs = TmpFs::new_fs(&kernel);
2562 let dev_root_node = Arc::clone(dev_fs.root());
2563 let _dev_pts_node =
2564 dev_root_node.create_dir(¤t_task, "pts".into()).expect("failed to mkdir pts");
2565
2566 let ns = Namespace::new(root_fs);
2567 let mut context = LookupContext::default();
2568 let dev = ns
2569 .root()
2570 .lookup_child(¤t_task, &mut context, "dev".into())
2571 .expect("failed to lookup dev");
2572 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2573 .expect("failed to mount dev root node");
2574 let mut context = LookupContext::default();
2575 let new_dev = ns
2576 .root()
2577 .lookup_child(¤t_task, &mut context, "dev".into())
2578 .expect("failed to lookup dev again");
2579 assert!(!Arc::ptr_eq(&dev.entry, &new_dev.entry));
2580 assert_ne!(&dev, &new_dev);
2581
2582 let mut context = LookupContext::default();
2583 let _new_pts = new_dev
2584 .lookup_child(¤t_task, &mut context, "pts".into())
2585 .expect("failed to lookup pts");
2586 let mut context = LookupContext::default();
2587 assert!(dev.lookup_child(¤t_task, &mut context, "pts".into()).is_err());
2588 })
2589 .await;
2590 }
2591
2592 #[::fuchsia::test]
2593 async fn test_path() {
2594 spawn_kernel_and_run(async |current_task| {
2595 let kernel = current_task.kernel();
2596 let root_fs = TmpFs::new_fs(&kernel);
2597 let root_node = Arc::clone(root_fs.root());
2598 let _dev_node =
2599 root_node.create_dir(¤t_task, "dev".into()).expect("failed to mkdir dev");
2600 let dev_fs = TmpFs::new_fs(&kernel);
2601 let dev_root_node = Arc::clone(dev_fs.root());
2602 let _dev_pts_node =
2603 dev_root_node.create_dir(¤t_task, "pts".into()).expect("failed to mkdir pts");
2604
2605 let ns = Namespace::new(root_fs);
2606 let mut context = LookupContext::default();
2607 let dev = ns
2608 .root()
2609 .lookup_child(¤t_task, &mut context, "dev".into())
2610 .expect("failed to lookup dev");
2611 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2612 .expect("failed to mount dev root node");
2613
2614 let mut context = LookupContext::default();
2615 let dev = ns
2616 .root()
2617 .lookup_child(¤t_task, &mut context, "dev".into())
2618 .expect("failed to lookup dev");
2619 let mut context = LookupContext::default();
2620 let pts = dev
2621 .lookup_child(¤t_task, &mut context, "pts".into())
2622 .expect("failed to lookup pts");
2623
2624 assert_eq!("/", ns.root().path_escaping_chroot());
2625 assert_eq!("/dev", dev.path_escaping_chroot());
2626 assert_eq!("/dev/pts", pts.path_escaping_chroot());
2627 })
2628 .await;
2629 }
2630
2631 #[::fuchsia::test]
2632 async fn test_shadowing() {
2633 spawn_kernel_and_run(async |current_task| {
2634 let kernel = current_task.kernel();
2635 let root_fs = TmpFs::new_fs(&kernel);
2636 let ns = Namespace::new(root_fs.clone());
2637 let _foo_node = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2638 let mut context = LookupContext::default();
2639 let foo_dir =
2640 ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2641
2642 let foofs1 = TmpFs::new_fs(&kernel);
2643 foo_dir.mount(WhatToMount::Fs(foofs1.clone()), MountpointFlags::empty()).unwrap();
2644 let mut context = LookupContext::default();
2645 assert!(Arc::ptr_eq(
2646 &ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap().entry,
2647 foofs1.root()
2648 ));
2649 let foo_dir =
2650 ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2651
2652 let ns_clone = ns.clone_namespace(&kernel.mounts_lock());
2653
2654 let foofs2 = TmpFs::new_fs(&kernel);
2655 foo_dir.mount(WhatToMount::Fs(foofs2.clone()), MountpointFlags::empty()).unwrap();
2656 let mut context = LookupContext::default();
2657 assert!(Arc::ptr_eq(
2658 &ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap().entry,
2659 foofs2.root()
2660 ));
2661
2662 assert!(Arc::ptr_eq(
2663 &ns_clone
2664 .root()
2665 .lookup_child(¤t_task, &mut LookupContext::default(), "foo".into())
2666 .unwrap()
2667 .entry,
2668 foofs1.root()
2669 ));
2670 })
2671 .await;
2672 }
2673
2674 #[::fuchsia::test]
2675 async fn test_unlink_mounted_directory() {
2676 spawn_kernel_and_run(async |current_task| {
2677 let kernel = current_task.kernel();
2678 let root_fs = TmpFs::new_fs(&kernel);
2679 let ns1 = Namespace::new(root_fs.clone());
2680 let ns2 = Namespace::new(root_fs.clone());
2681 let _foo_node = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2682 let mut context = LookupContext::default();
2683 let foo_dir =
2684 ns1.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2685
2686 let foofs = TmpFs::new_fs(&kernel);
2687 foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2688
2689 assert_eq!(
2691 ns1.root()
2692 .unlink(
2693 ¤t_task,
2694 "foo".into(),
2695 UnlinkKind::Directory,
2696 DirectoryMode::AllowAny
2697 )
2698 .unwrap_err(),
2699 errno!(EBUSY),
2700 );
2701
2702 ns2.root()
2704 .unlink(¤t_task, "foo".into(), UnlinkKind::Directory, DirectoryMode::AllowAny)
2705 .expect("unlink failed");
2706
2707 assert_eq!(
2709 ns1.root()
2710 .unlink(
2711 ¤t_task,
2712 "foo".into(),
2713 UnlinkKind::Directory,
2714 DirectoryMode::AllowAny
2715 )
2716 .unwrap_err(),
2717 errno!(ENOENT),
2718 );
2719 })
2720 .await;
2721 }
2722
2723 #[::fuchsia::test]
2724 async fn test_rename_mounted_directory() {
2725 spawn_kernel_and_run(async |current_task| {
2726 let kernel = current_task.kernel();
2727 let root_fs = TmpFs::new_fs(&kernel);
2728 let ns1 = Namespace::new(root_fs.clone());
2729 let ns2 = Namespace::new(root_fs.clone());
2730 let _foo_node = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2731 let _bar_node = root_fs.root().create_dir(¤t_task, "bar".into()).unwrap();
2732 let _baz_node = root_fs.root().create_dir(¤t_task, "baz".into()).unwrap();
2733 let mut context = LookupContext::default();
2734 let foo_dir =
2735 ns1.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2736
2737 let foofs = TmpFs::new_fs(&kernel);
2738 foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2739
2740 let root = ns1.root();
2742 assert_eq!(
2743 NamespaceNode::rename(
2744 ¤t_task,
2745 &root,
2746 "bar".into(),
2747 &root,
2748 "foo".into(),
2749 RenameFlags::empty()
2750 )
2751 .unwrap_err(),
2752 errno!(EBUSY),
2753 );
2754 assert_eq!(
2756 NamespaceNode::rename(
2757 ¤t_task,
2758 &root,
2759 "foo".into(),
2760 &root,
2761 "bar".into(),
2762 RenameFlags::empty()
2763 )
2764 .unwrap_err(),
2765 errno!(EBUSY),
2766 );
2767
2768 let root = ns2.root();
2770
2771 NamespaceNode::rename(
2773 ¤t_task,
2774 &root,
2775 "foo".into(),
2776 &root,
2777 "bar".into(),
2778 RenameFlags::empty(),
2779 )
2780 .expect("rename failed");
2781
2782 NamespaceNode::rename(
2784 ¤t_task,
2785 &root,
2786 "baz".into(),
2787 &root,
2788 "bar".into(),
2789 RenameFlags::empty(),
2790 )
2791 .expect("rename failed");
2792
2793 assert_eq!(
2795 ns1.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap_err(),
2796 errno!(ENOENT)
2797 );
2798 assert_eq!(
2799 ns1.root().lookup_child(¤t_task, &mut context, "baz".into()).unwrap_err(),
2800 errno!(ENOENT)
2801 );
2802 })
2803 .await;
2804 }
2805
2806 #[::fuchsia::test]
2809 async fn test_lookup_with_symlink_chain() {
2810 spawn_kernel_and_run(async |current_task| {
2811 let kernel = current_task.kernel();
2813 let root_fs = TmpFs::new_fs(&kernel);
2814 let root_node = Arc::clone(root_fs.root());
2815 let _first_subdir_node = root_node
2816 .create_dir(¤t_task, "first_subdir".into())
2817 .expect("failed to mkdir dev");
2818 let _second_subdir_node = root_node
2819 .create_dir(¤t_task, "second_subdir".into())
2820 .expect("failed to mkdir dev");
2821
2822 let first_subdir_fs = TmpFs::new_fs(&kernel);
2824 let second_subdir_fs = TmpFs::new_fs(&kernel);
2825
2826 let ns = Namespace::new(root_fs);
2827 let mut context = LookupContext::default();
2828 let first_subdir = ns
2829 .root()
2830 .lookup_child(¤t_task, &mut context, "first_subdir".into())
2831 .expect("failed to lookup first_subdir");
2832 first_subdir
2833 .mount(WhatToMount::Fs(first_subdir_fs), MountpointFlags::empty())
2834 .expect("failed to mount first_subdir fs node");
2835 let second_subdir = ns
2836 .root()
2837 .lookup_child(¤t_task, &mut context, "second_subdir".into())
2838 .expect("failed to lookup second_subdir");
2839 second_subdir
2840 .mount(WhatToMount::Fs(second_subdir_fs), MountpointFlags::empty())
2841 .expect("failed to mount second_subdir fs node");
2842
2843 let real_file_node = first_subdir
2852 .create_node(¤t_task, "real_file".into(), mode!(IFREG, 0o777), DeviceId::NONE)
2853 .expect("failed to create real_file");
2854 first_subdir
2855 .create_symlink(¤t_task, "path_symlink".into(), "real_file".into())
2856 .expect("failed to create path_symlink");
2857
2858 let mut no_follow_lookup_context = LookupContext::new(SymlinkMode::NoFollow);
2859 let path_symlink_node = first_subdir
2860 .lookup_child(¤t_task, &mut no_follow_lookup_context, "path_symlink".into())
2861 .expect("Failed to lookup path_symlink");
2862
2863 let node_symlink_node = second_subdir.entry.node.fs().create_node_and_allocate_node_id(
2867 CallbackSymlinkNode::new(move || {
2868 let node = path_symlink_node.clone();
2869 Ok(SymlinkTarget::Node(node))
2870 }),
2871 FsNodeInfo::new(mode!(IFLNK, 0o777), current_task.current_fscred()),
2872 );
2873 second_subdir
2874 .entry
2875 .create_entry(
2876 ¤t_task,
2877 &MountInfo::detached(),
2878 "node_symlink".into(),
2879 move |_dir, _mount, _name| Ok(node_symlink_node),
2880 )
2881 .expect("failed to create node_symlink entry");
2882
2883 let mut follow_lookup_context = LookupContext::new(SymlinkMode::Follow);
2885 let node_symlink_resolution = second_subdir
2886 .lookup_child(¤t_task, &mut follow_lookup_context, "node_symlink".into())
2887 .expect("lookup with symlink chain failed");
2888
2889 assert!(node_symlink_resolution.entry.node.ino == real_file_node.entry.node.ino);
2891 })
2892 .await;
2893 }
2894
2895 #[::fuchsia::test]
2896 async fn test_mounts_registration_and_unmount_updates_has_mounts() {
2897 spawn_kernel_and_run(async |current_task| {
2898 let kernel = current_task.kernel();
2899 let root_fs = TmpFs::new_fs(&kernel);
2900 let ns1 = Namespace::new(root_fs.clone());
2901 let _foo_node = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2902 let mut context = LookupContext::default();
2903 let foo_dir =
2904 ns1.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2905 let mountpoint_entry = Arc::clone(&foo_dir.entry);
2906 assert!(!mountpoint_entry.has_mounts());
2907
2908 let foofs = TmpFs::new_fs(&kernel);
2909 foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2910 assert!(mountpoint_entry.has_mounts());
2911
2912 let ns1_clone = ns1.clone_namespace(&kernel.mounts_lock());
2914 assert!(mountpoint_entry.has_mounts());
2915
2916 drop(ns1_clone);
2918 assert!(mountpoint_entry.has_mounts());
2919
2920 let mounted_foo = ns1
2923 .root()
2924 .lookup_child(¤t_task, &mut LookupContext::default(), "foo".into())
2925 .unwrap();
2926 mounted_foo.unmount(UnmountFlags::empty()).unwrap();
2927 assert!(!mountpoint_entry.has_mounts());
2928
2929 let _sub_node = root_fs.root().create_dir(¤t_task, "sub".into()).unwrap();
2932 let _dst_node = root_fs.root().create_dir(¤t_task, "dst".into()).unwrap();
2933 let sub_dir = ns1
2934 .root()
2935 .lookup_child(¤t_task, &mut LookupContext::default(), "sub".into())
2936 .unwrap();
2937 let _inner_node = sub_dir.entry.create_dir(¤t_task, "inner".into()).unwrap();
2938 let inner_dir = sub_dir
2939 .lookup_child(¤t_task, &mut LookupContext::default(), "inner".into())
2940 .unwrap();
2941 let inner_fs = TmpFs::new_fs(&kernel);
2942 let _inner_marker = inner_fs.root().create_dir(¤t_task, "marker".into()).unwrap();
2943 inner_dir.mount(WhatToMount::Fs(inner_fs), MountpointFlags::empty()).unwrap();
2944
2945 let sibling_fs = TmpFs::new_fs(&kernel);
2946 foo_dir.mount(WhatToMount::Fs(sibling_fs), MountpointFlags::empty()).unwrap();
2947
2948 let dst_dir = ns1
2949 .root()
2950 .lookup_child(¤t_task, &mut LookupContext::default(), "dst".into())
2951 .unwrap();
2952 dst_dir.mount(WhatToMount::Bind(sub_dir), MountpointFlags::REC).unwrap();
2953
2954 let dst_inner = ns1
2955 .root()
2956 .lookup_child(¤t_task, &mut LookupContext::default(), "dst".into())
2957 .unwrap()
2958 .lookup_child(¤t_task, &mut LookupContext::default(), "inner".into())
2959 .unwrap();
2960 assert!(
2961 dst_inner
2962 .lookup_child(¤t_task, &mut LookupContext::default(), "marker".into())
2963 .is_ok()
2964 );
2965 assert_eq!(
2966 kernel.mounts.mounts.lock().get(&PtrKey::from(&foo_dir.entry)).unwrap().len(),
2967 1
2968 );
2969 })
2970 .await;
2971 }
2972
2973 #[::fuchsia::test]
2974 async fn test_enter_mount_has_mounts_lifecycle() {
2975 spawn_kernel_and_run(async |current_task| {
2976 let kernel = current_task.kernel();
2977 let root_fs = TmpFs::new_fs(&kernel);
2978 let ns1 = Namespace::new(root_fs.clone());
2979 let ns2 = Namespace::new(root_fs.clone());
2980 let foo_entry = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2981 assert!(!foo_entry.has_mounts());
2982
2983 let foo_ns1 = ns1
2985 .root()
2986 .lookup_child(¤t_task, &mut LookupContext::default(), "foo".into())
2987 .unwrap();
2988 assert!(Arc::ptr_eq(&foo_ns1.entry, &foo_entry));
2989
2990 let foofs1 = TmpFs::new_fs(&kernel);
2993 foo_ns1.mount(WhatToMount::Fs(foofs1.clone()), MountpointFlags::empty()).unwrap();
2994 assert!(foo_entry.has_mounts());
2995 assert!(!foofs1.root().has_mounts());
2996
2997 let mounted1 = ns1
2998 .root()
2999 .lookup_child(¤t_task, &mut LookupContext::default(), "foo".into())
3000 .unwrap();
3001 assert!(Arc::ptr_eq(&mounted1.entry, foofs1.root()));
3002 let foo_ns2 = ns2
3003 .root()
3004 .lookup_child(¤t_task, &mut LookupContext::default(), "foo".into())
3005 .unwrap();
3006 assert!(Arc::ptr_eq(&foo_ns2.entry, &foo_entry));
3007
3008 let foofs2 = TmpFs::new_fs(&kernel);
3010 mounted1.mount(WhatToMount::Fs(foofs2.clone()), MountpointFlags::empty()).unwrap();
3011 assert!(foofs1.root().has_mounts());
3012 assert!(!foofs2.root().has_mounts());
3013
3014 let mounted2 = ns1
3015 .root()
3016 .lookup_child(¤t_task, &mut LookupContext::default(), "foo".into())
3017 .unwrap();
3018 assert!(Arc::ptr_eq(&mounted2.entry, foofs2.root()));
3019
3020 mounted2.unmount(UnmountFlags::empty()).unwrap();
3022 assert!(!foofs1.root().has_mounts());
3023 assert!(foo_entry.has_mounts());
3024 let after_unmount2 = ns1
3025 .root()
3026 .lookup_child(¤t_task, &mut LookupContext::default(), "foo".into())
3027 .unwrap();
3028 assert!(Arc::ptr_eq(&after_unmount2.entry, foofs1.root()));
3029
3030 after_unmount2.unmount(UnmountFlags::empty()).unwrap();
3032 assert!(!foo_entry.has_mounts());
3033 let after_unmount1 = ns1
3034 .root()
3035 .lookup_child(¤t_task, &mut LookupContext::default(), "foo".into())
3036 .unwrap();
3037 assert!(Arc::ptr_eq(&after_unmount1.entry, &foo_entry));
3038 })
3039 .await;
3040 }
3041}