1use crate::mutable_state::{state_accessor, state_implementation};
6use crate::security;
7use crate::task::{CurrentTask, EventHandler, Kernel, Task, WaitCanceler, Waiter};
8use crate::time::utc;
9use crate::vfs::fs_registry::FsRegistry;
10use crate::vfs::pseudo::dynamic_file::{DynamicFile, DynamicFileBuf, DynamicFileSource};
11use crate::vfs::pseudo::simple_file::SimpleFileNode;
12use crate::vfs::socket::{SocketAddress, SocketHandle, UnixSocket};
13use crate::vfs::{
14 CheckAccessReason, DirEntry, DirEntryHandle, FileHandle, FileObject, FileOps, FileSystemHandle,
15 FileSystemOptions, FileWriteGuardMode, FsContext, FsNode, FsNodeHandle, FsNodeOps, FsStr,
16 FsString, PathBuilder, RenameFlags, SymlinkTarget, UnlinkKind, fileops_impl_dataless,
17 fileops_impl_delegate_read_write_and_seek, fileops_impl_nonseekable, fileops_impl_noop_sync,
18 fs_node_impl_not_dir,
19};
20use fuchsia_rcu::RcuReadScope;
21use macro_rules_attribute::apply;
22use ref_cast::RefCast;
23use starnix_logging::log_warn;
24use starnix_rcu::RcuHashMap;
25use starnix_sync::{
26 BeforeFsNodeAppend, FileOpsCore, LockEqualOrBefore, Locked, Mutex, RwLock, Unlocked,
27};
28use starnix_types::ownership::WeakRef;
29use starnix_uapi::arc_key::{ArcKey, PtrKey, WeakKey};
30use starnix_uapi::auth::UserAndOrGroupId;
31use starnix_uapi::device_id::DeviceId;
32use starnix_uapi::errors::Errno;
33use starnix_uapi::file_mode::{AccessCheck, FileMode};
34use starnix_uapi::inotify_mask::InotifyMask;
35use starnix_uapi::mount_flags::{
36 AtomicMountpointFlags, FileSystemFlags, MountFlags, MountpointFlags,
37};
38use starnix_uapi::open_flags::OpenFlags;
39use starnix_uapi::unmount_flags::UnmountFlags;
40use starnix_uapi::vfs::{FdEvents, ResolveFlags};
41use starnix_uapi::{NAME_MAX, errno, error};
42use std::borrow::Borrow;
43use std::collections::HashSet;
44use std::fmt;
45use std::hash::{Hash, Hasher};
46use std::ops::{Deref, DerefMut};
47use std::sync::atomic::Ordering;
48use std::sync::{Arc, Weak};
49
50#[derive(Debug)]
54pub struct Namespace {
55 root_mount: MountHandle,
56
57 pub id: u64,
59}
60
61impl Namespace {
62 pub fn new(fs: FileSystemHandle) -> Arc<Namespace> {
63 Self::new_with_flags(fs, MountpointFlags::empty())
64 }
65
66 pub fn new_with_flags(fs: FileSystemHandle, flags: MountpointFlags) -> Arc<Namespace> {
67 let kernel = fs.kernel.upgrade().expect("can't create namespace without a kernel");
68 let root_mount = Mount::new(WhatToMount::Fs(fs), flags);
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 fn clone_namespace(&self) -> Arc<Namespace> {
77 let kernel =
78 self.root_mount.fs.kernel.upgrade().expect("can't clone namespace without a kernel");
79 Arc::new(Self {
80 root_mount: self.root_mount.clone_mount_recursive(),
81 id: kernel.get_next_namespace_id(),
82 })
83 }
84
85 pub fn translate_node(mut node: NamespaceNode, new_ns: &Namespace) -> Option<NamespaceNode> {
88 let mut mountpoints = vec![];
90 let mut mount = node.mount;
91 while let Some(mountpoint) = mount.as_ref().and_then(|m| m.read().mountpoint()) {
92 mountpoints.push(mountpoint.entry);
93 mount = mountpoint.mount;
94 }
95
96 let mut mount = Arc::clone(&new_ns.root_mount);
98 for mountpoint in mountpoints.iter().rev() {
99 let next_mount =
100 mount.read().submounts.get(ArcKey::ref_cast(mountpoint))?.mount.clone();
101 mount = next_mount;
102 }
103 node.mount = Some(mount).into();
104 Some(node)
105 }
106}
107
108impl FsNodeOps for Arc<Namespace> {
109 fs_node_impl_not_dir!();
110
111 fn create_file_ops(
112 &self,
113 _locked: &mut Locked<FileOpsCore>,
114 _node: &FsNode,
115 _current_task: &CurrentTask,
116 _flags: OpenFlags,
117 ) -> Result<Box<dyn FileOps>, Errno> {
118 Ok(Box::new(MountNamespaceFile(self.clone())))
119 }
120}
121
122pub struct MountNamespaceFile(pub Arc<Namespace>);
123
124impl FileOps for MountNamespaceFile {
125 fileops_impl_nonseekable!();
126 fileops_impl_dataless!();
127 fileops_impl_noop_sync!();
128}
129
130type MountClientMarker = Arc<()>;
135
136pub struct Mount {
145 root: DirEntryHandle,
146 fs: FileSystemHandle,
147
148 flags: AtomicMountpointFlags,
150
151 flags_lock: Mutex<()>,
153
154 id: u64,
156
157 active_client_counter: MountClientMarker,
159
160 state: RwLock<MountState>,
162 }
169type MountHandle = Arc<Mount>;
170
171#[derive(Clone, Debug)]
173pub struct MountInfo {
174 handle: Option<MountHandle>,
175}
176
177impl MountInfo {
178 pub fn detached() -> Self {
181 None.into()
182 }
183
184 pub fn flags(&self) -> MountFlags {
186 if let Some(handle) = &self.handle {
187 handle.flags()
188 } else {
189 MountFlags::NOATIME
191 }
192 }
193
194 pub fn check_readonly_filesystem(&self) -> Result<(), Errno> {
196 if self.flags().contains(MountFlags::RDONLY) {
197 return error!(EROFS);
198 }
199 Ok(())
200 }
201
202 pub fn check_noexec_filesystem(&self) -> Result<(), Errno> {
204 if self.flags().contains(MountFlags::NOEXEC) {
205 return error!(EACCES);
206 }
207 Ok(())
208 }
209}
210
211impl Deref for MountInfo {
212 type Target = Option<MountHandle>;
213
214 fn deref(&self) -> &Self::Target {
215 &self.handle
216 }
217}
218
219impl DerefMut for MountInfo {
220 fn deref_mut(&mut self) -> &mut Self::Target {
221 &mut self.handle
222 }
223}
224
225impl std::cmp::PartialEq for MountInfo {
226 fn eq(&self, other: &Self) -> bool {
227 self.handle.as_ref().map(Arc::as_ptr) == other.handle.as_ref().map(Arc::as_ptr)
228 }
229}
230
231impl std::cmp::Eq for MountInfo {}
232
233impl Into<MountInfo> for Option<MountHandle> {
234 fn into(self) -> MountInfo {
235 MountInfo { handle: self }
236 }
237}
238
239#[derive(Default)]
240pub struct MountState {
241 mountpoint: Option<(Weak<Mount>, DirEntryHandle)>,
246
247 submounts: HashSet<Submount>,
256
257 peer_group_: Option<(Arc<PeerGroup>, PtrKey<Mount>)>,
262 upstream_: Option<(Weak<PeerGroup>, PtrKey<Mount>)>,
265}
266
267#[derive(Default)]
271struct PeerGroup {
272 id: u64,
273 state: RwLock<PeerGroupState>,
274}
275#[derive(Default)]
276struct PeerGroupState {
277 mounts: HashSet<WeakKey<Mount>>,
278 downstream: HashSet<WeakKey<Mount>>,
279}
280
281pub enum WhatToMount {
282 Fs(FileSystemHandle),
283 Bind(NamespaceNode),
284}
285
286impl Mount {
287 pub fn new(what: WhatToMount, mut flags: MountpointFlags) -> MountHandle {
288 match what {
289 WhatToMount::Fs(fs) => {
290 flags.default_atime_from(MountpointFlags::RELATIME);
292 Self::new_with_root(fs.root().clone(), flags)
293 }
294 WhatToMount::Bind(node) => {
295 let mount = node.mount.as_ref().expect("can't bind mount from an anonymous node");
296 mount.clone_mount(&node.entry, flags.into())
297 }
298 }
299 }
300
301 fn new_with_root(root: DirEntryHandle, flags: MountpointFlags) -> MountHandle {
302 let fs = root.node.fs();
303 let kernel = fs.kernel.upgrade().expect("can't create mount without kernel");
304 Arc::new(Self {
305 id: kernel.get_next_mount_id(),
306 flags: (flags & MountpointFlags::STORED_ON_MOUNT).into(),
307 flags_lock: Mutex::new(()),
308 root,
309 active_client_counter: Default::default(),
310 fs,
311 state: Default::default(),
312 })
313 }
314
315 pub fn root(self: &MountHandle) -> NamespaceNode {
317 NamespaceNode::new(Arc::clone(self), Arc::clone(&self.root))
318 }
319
320 fn create_submount(
322 self: &MountHandle,
323 dir: &DirEntryHandle,
324 what: WhatToMount,
325 flags: MountpointFlags,
326 ) {
327 let peers = {
340 let state = self.state.read();
341 state.peer_group().map(|g| g.copy_propagation_targets()).unwrap_or_default()
342 };
343
344 let mount = Mount::new(what, flags);
349
350 if self.read().is_shared() {
351 mount.write().make_shared();
352 }
353
354 for peer in peers {
355 if Arc::ptr_eq(self, &peer) {
356 continue;
357 }
358 let clone = mount.clone_mount_recursive();
359 peer.write().add_submount_internal(dir, clone);
360 }
361
362 self.write().add_submount_internal(dir, mount)
363 }
364
365 fn remove_submount(self: &MountHandle, mount_hash_key: &ArcKey<DirEntry>) -> Result<(), Errno> {
366 let peers = {
368 let state = self.state.read();
369 state.peer_group().map(|g| g.copy_propagation_targets()).unwrap_or_default()
370 };
371
372 for peer in peers {
373 if Arc::ptr_eq(self, &peer) {
374 continue;
375 }
376 let mut peer = peer.write();
380 if let Some(submount) = peer.submounts.get(mount_hash_key) {
381 if !submount.mount.read().submounts.is_empty() {
382 continue;
383 }
384 }
385 let _ = peer.remove_submount_internal(mount_hash_key);
386 }
387
388 self.write().remove_submount_internal(mount_hash_key)
389 }
390
391 fn clone_mount(
394 self: &MountHandle,
395 new_root: &DirEntryHandle,
396 flags: MountFlags,
397 ) -> MountHandle {
398 assert!(new_root.is_descendant_of(&self.root));
399 let clone = Self::new_with_root(Arc::clone(new_root), self.mount_flags());
402
403 if flags.contains(MountFlags::REC) {
404 let mut submounts = vec![];
410 for Submount { dir, mount } in &self.state.read().submounts {
411 submounts.push((dir.clone(), mount.clone_mount_recursive()));
412 }
413 let mut clone_state = clone.write();
414 for (dir, submount) in submounts {
415 clone_state.add_submount_internal(&dir, submount);
416 }
417 }
418
419 let peer_group = self.state.read().peer_group().map(Arc::clone);
421 if let Some(peer_group) = peer_group {
422 clone.write().set_peer_group(peer_group);
423 }
424
425 clone
426 }
427
428 fn clone_mount_recursive(self: &MountHandle) -> MountHandle {
431 self.clone_mount(&self.root, MountFlags::REC)
432 }
433
434 pub fn change_propagation(self: &MountHandle, flag: MountFlags, recursive: bool) {
435 let mut state = self.write();
436 match flag {
437 MountFlags::SHARED => state.make_shared(),
438 MountFlags::PRIVATE => state.make_private(),
439 MountFlags::DOWNSTREAM => state.make_downstream(),
440 _ => {
441 log_warn!("mount propagation {:?}", flag);
442 return;
443 }
444 }
445
446 if recursive {
447 for submount in &state.submounts {
448 submount.mount.change_propagation(flag, recursive);
449 }
450 }
451 }
452
453 fn flags(&self) -> MountFlags {
456 MountFlags::from(self.mount_flags()) | self.fs_flags().into()
457 }
458
459 fn mount_flags(&self) -> MountpointFlags {
461 self.flags.load(Ordering::Relaxed)
462 }
463
464 fn fs_flags(&self) -> FileSystemFlags {
466 self.fs.options.flags
467 }
468
469 pub fn update_flags(self: &MountHandle, mut flags: MountpointFlags) {
472 let _lock = self.flags_lock.lock();
473 flags.default_atime_from(self.flags.load(Ordering::Relaxed));
478 flags &= MountpointFlags::STORED_ON_MOUNT;
479 self.flags.store(flags, Ordering::Relaxed);
480 }
481
482 fn active_clients(&self) -> usize {
486 Arc::strong_count(&self.active_client_counter) - 1
488 }
489
490 pub fn unmount(&self, flags: UnmountFlags) -> Result<(), Errno> {
491 if !flags.contains(UnmountFlags::DETACH) {
492 if self.active_clients() > 0 || !self.state.read().submounts.is_empty() {
493 return error!(EBUSY);
494 }
495 }
496 let mountpoint = self.state.read().mountpoint().ok_or_else(|| errno!(EINVAL))?;
497 let parent_mount = mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount");
498 parent_mount.remove_submount(mountpoint.mount_hash_key())
499 }
500
501 pub fn security_state(&self) -> &security::FileSystemState {
503 &self.fs.security_state
504 }
505
506 pub fn fs_name(&self) -> &'static FsStr {
508 self.fs.name()
509 }
510
511 state_accessor!(Mount, state, Arc<Mount>);
512}
513
514impl MountState {
515 pub fn has_submount(&self, dir_entry: &DirEntryHandle) -> bool {
517 self.submounts.contains(ArcKey::ref_cast(dir_entry))
518 }
519
520 fn mountpoint(&self) -> Option<NamespaceNode> {
522 let (mount, entry) = self.mountpoint.as_ref()?;
523 Some(NamespaceNode::new(mount.upgrade()?, entry.clone()))
524 }
525
526 fn peer_group(&self) -> Option<&Arc<PeerGroup>> {
528 let (group, _) = self.peer_group_.as_ref()?;
529 Some(group)
530 }
531
532 fn take_from_peer_group(&mut self) -> Option<Arc<PeerGroup>> {
534 let (old_group, old_mount) = self.peer_group_.take()?;
535 old_group.remove(old_mount);
536 if let Some(upstream) = self.take_from_upstream() {
537 let next_mount =
538 old_group.state.read().mounts.iter().next().map(|w| w.0.upgrade().unwrap());
539 if let Some(next_mount) = next_mount {
540 next_mount.write().set_upstream(upstream);
544 }
545 }
546 Some(old_group)
547 }
548
549 fn upstream(&self) -> Option<Arc<PeerGroup>> {
550 self.upstream_.as_ref().and_then(|g| g.0.upgrade())
551 }
552
553 fn take_from_upstream(&mut self) -> Option<Arc<PeerGroup>> {
554 let (old_upstream, old_mount) = self.upstream_.take()?;
555 let old_upstream = old_upstream.upgrade()?;
558 old_upstream.remove_downstream(old_mount);
559 Some(old_upstream)
560 }
561}
562
563#[apply(state_implementation!)]
564impl MountState<Base = Mount, BaseType = Arc<Mount>> {
565 fn add_submount_internal(&mut self, dir: &DirEntryHandle, mount: MountHandle) {
567 if !dir.is_descendant_of(&self.base.root) {
568 return;
569 }
570
571 let submount = mount.fs.kernel.upgrade().unwrap().mounts.register_mount(dir, mount.clone());
572 let old_mountpoint =
573 mount.state.write().mountpoint.replace((Arc::downgrade(self.base), Arc::clone(dir)));
574 assert!(old_mountpoint.is_none(), "add_submount can only take a newly created mount");
575 let old_mount = self.submounts.replace(submount);
578
579 if let Some(mut old_mount) = old_mount {
583 old_mount.mount.write().mountpoint = Some((Arc::downgrade(&mount), Arc::clone(dir)));
588 old_mount.dir = ArcKey(mount.root.clone());
589 mount.write().submounts.insert(old_mount);
590 }
591 }
592
593 fn remove_submount_internal(&mut self, mount_hash_key: &ArcKey<DirEntry>) -> Result<(), Errno> {
594 if self.submounts.remove(mount_hash_key) { Ok(()) } else { error!(EINVAL) }
595 }
596
597 fn set_peer_group(&mut self, group: Arc<PeerGroup>) {
599 self.take_from_peer_group();
600 group.add(self.base);
601 self.peer_group_ = Some((group, Arc::as_ptr(self.base).into()));
602 }
603
604 fn set_upstream(&mut self, group: Arc<PeerGroup>) {
605 self.take_from_upstream();
606 group.add_downstream(self.base);
607 self.upstream_ = Some((Arc::downgrade(&group), Arc::as_ptr(self.base).into()));
608 }
609
610 pub fn is_shared(&self) -> bool {
612 self.peer_group().is_some()
613 }
614
615 pub fn make_shared(&mut self) {
617 if self.is_shared() {
618 return;
619 }
620 let kernel =
621 self.base.fs.kernel.upgrade().expect("can't create new peer group without kernel");
622 self.set_peer_group(PeerGroup::new(kernel.get_next_peer_group_id()));
623 }
624
625 pub fn make_private(&mut self) {
627 self.take_from_peer_group();
628 self.take_from_upstream();
629 }
630
631 pub fn make_downstream(&mut self) {
634 if let Some(peer_group) = self.take_from_peer_group() {
635 self.set_upstream(peer_group);
636 }
637 }
638}
639
640impl PeerGroup {
641 fn new(id: u64) -> Arc<Self> {
642 Arc::new(Self { id, state: Default::default() })
643 }
644
645 fn add(&self, mount: &Arc<Mount>) {
646 self.state.write().mounts.insert(WeakKey::from(mount));
647 }
648
649 fn remove(&self, mount: PtrKey<Mount>) {
650 self.state.write().mounts.remove(&mount);
651 }
652
653 fn add_downstream(&self, mount: &Arc<Mount>) {
654 self.state.write().downstream.insert(WeakKey::from(mount));
655 }
656
657 fn remove_downstream(&self, mount: PtrKey<Mount>) {
658 self.state.write().downstream.remove(&mount);
659 }
660
661 fn copy_propagation_targets(&self) -> Vec<MountHandle> {
662 let mut buf = vec![];
663 self.collect_propagation_targets(&mut buf);
664 buf
665 }
666
667 fn collect_propagation_targets(&self, buf: &mut Vec<MountHandle>) {
668 let downstream_mounts: Vec<_> = {
669 let state = self.state.read();
670 buf.extend(state.mounts.iter().filter_map(|m| m.0.upgrade()));
671 state.downstream.iter().filter_map(|m| m.0.upgrade()).collect()
672 };
673 for mount in downstream_mounts {
674 let peer_group = mount.read().peer_group().map(Arc::clone);
675 match peer_group {
676 Some(group) => group.collect_propagation_targets(buf),
677 None => buf.push(mount),
678 }
679 }
680 }
681}
682
683impl Drop for Mount {
684 fn drop(&mut self) {
685 let state = self.state.get_mut();
686 state.take_from_peer_group();
687 state.take_from_upstream();
688 }
689}
690
691impl fmt::Debug for Mount {
692 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
693 let state = self.state.read();
694 f.debug_struct("Mount")
695 .field("id", &(self as *const Mount))
696 .field("root", &self.root)
697 .field("mountpoint", &state.mountpoint)
698 .field("submounts", &state.submounts)
699 .finish()
700 }
701}
702
703impl Kernel {
704 pub fn get_next_mount_id(&self) -> u64 {
705 self.next_mount_id.next()
706 }
707
708 pub fn get_next_peer_group_id(&self) -> u64 {
709 self.next_peer_group_id.next()
710 }
711
712 pub fn get_next_namespace_id(&self) -> u64 {
713 self.next_namespace_id.next()
714 }
715}
716
717impl CurrentTask {
718 pub fn create_filesystem(
719 &self,
720 locked: &mut Locked<Unlocked>,
721 fs_type: &FsStr,
722 options: FileSystemOptions,
723 ) -> Result<FileSystemHandle, Errno> {
724 self.kernel()
731 .expando
732 .get::<FsRegistry>()
733 .create(locked, self, fs_type, options)
734 .ok_or_else(|| errno!(ENODEV, fs_type))?
735 }
736}
737
738struct ProcMountsFileSource(WeakRef<Task>);
739
740impl DynamicFileSource for ProcMountsFileSource {
741 fn generate(
742 &self,
743 _current_task: &CurrentTask,
744 sink: &mut DynamicFileBuf,
745 ) -> Result<(), Errno> {
746 let task = Task::from_weak(&self.0)?;
751 let task_fs = task.live()?.fs.read();
752 let root = task_fs.root();
753 let ns = task_fs.namespace();
754 for_each_mount(&ns.root_mount, &mut |mount| {
755 let mountpoint = mount.read().mountpoint().unwrap_or_else(|| mount.root());
756 if !mountpoint.is_descendant_of(&root) {
757 return Ok(());
758 }
759 write!(
760 sink,
761 "{} {} {} {}{}",
762 mount.fs.options.source_for_display(),
763 mountpoint.path(&task_fs),
764 mount.fs.name(),
765 mount.flags(),
768 security::sb_show_options(&task.kernel(), &mount.fs)?,
769 )?;
770 writeln!(sink, " 0 0")?;
771 Ok(())
772 })?;
773 Ok(())
774 }
775}
776
777pub struct ProcMountsFile {
778 dynamic_file: DynamicFile<ProcMountsFileSource>,
779}
780
781impl ProcMountsFile {
782 pub fn new_node(task: WeakRef<Task>) -> impl FsNodeOps {
783 SimpleFileNode::new(move |_, _| {
784 Ok(Self { dynamic_file: DynamicFile::new(ProcMountsFileSource(task.clone())) })
785 })
786 }
787}
788
789impl FileOps for ProcMountsFile {
790 fileops_impl_delegate_read_write_and_seek!(self, self.dynamic_file);
791 fileops_impl_noop_sync!();
792
793 fn wait_async(
794 &self,
795 _locked: &mut Locked<FileOpsCore>,
796 _file: &FileObject,
797 _current_task: &CurrentTask,
798 waiter: &Waiter,
799 _events: FdEvents,
800 _handler: EventHandler,
801 ) -> Option<WaitCanceler> {
802 Some(waiter.fake_wait())
805 }
806
807 fn query_events(
808 &self,
809 _locked: &mut Locked<FileOpsCore>,
810 _file: &FileObject,
811 _current_task: &CurrentTask,
812 ) -> Result<FdEvents, Errno> {
813 Ok(FdEvents::empty())
814 }
815}
816
817#[derive(Clone)]
818pub struct ProcMountinfoFile(WeakRef<Task>);
819impl ProcMountinfoFile {
820 pub fn new_node(task: WeakRef<Task>) -> impl FsNodeOps {
821 DynamicFile::new_node(Self(task))
822 }
823}
824impl DynamicFileSource for ProcMountinfoFile {
825 fn generate(
826 &self,
827 _current_task: &CurrentTask,
828 sink: &mut DynamicFileBuf,
829 ) -> Result<(), Errno> {
830 fn path_from_fs_root(dir: &DirEntryHandle) -> FsString {
832 let mut path = PathBuilder::new();
833 if dir.is_dead() {
834 path.prepend_element("/deleted".into());
836 }
837 let scope = RcuReadScope::new();
838 let mut current = dir.deref();
839 while let Some(parent) = current.parent_ref(&scope) {
840 path.prepend_element(current.local_name(&scope));
841 current = parent;
842 }
843 path.build_absolute()
844 }
845
846 let task = Task::from_weak(&self.0)?;
851 let task_fs = task.live()?.fs.read();
852 let root = task_fs.root();
853 let ns = task_fs.namespace();
854 for_each_mount(&ns.root_mount, &mut |mount| {
855 let mountpoint = mount.read().mountpoint().unwrap_or_else(|| mount.root());
856 if !mountpoint.is_descendant_of(&root) {
857 return Ok(());
858 }
859 let parent = mountpoint.mount.as_ref().unwrap();
861 write!(
862 sink,
863 "{} {} {} {} {} {}",
864 mount.id,
865 parent.id,
866 mount.root.node.fs().dev_id,
867 path_from_fs_root(&mount.root),
868 mountpoint.path(&task_fs),
869 mount.mount_flags(),
870 )?;
871 if let Some(peer_group) = mount.read().peer_group() {
872 write!(sink, " shared:{}", peer_group.id)?;
873 }
874 if let Some(upstream) = mount.read().upstream() {
875 write!(sink, " master:{}", upstream.id)?;
876 }
877 writeln!(
878 sink,
879 " - {} {} {}{}",
880 mount.fs.name(),
881 mount.fs.options.source_for_display(),
882 mount.fs_flags(),
883 security::sb_show_options(&task.kernel(), &mount.fs)?
885 )?;
886 Ok(())
887 })?;
888 Ok(())
889 }
890}
891
892fn for_each_mount<E>(
893 mount: &MountHandle,
894 callback: &mut impl FnMut(&MountHandle) -> Result<(), E>,
895) -> Result<(), E> {
896 callback(mount)?;
897 let submounts: Vec<_> = mount.read().submounts.iter().map(|s| s.mount.clone()).collect();
900 for submount in submounts {
901 for_each_mount(&submount, callback)?;
902 }
903 Ok(())
904}
905
906#[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
908pub enum SymlinkMode {
909 #[default]
911 Follow,
912
913 NoFollow,
915}
916
917pub const MAX_SYMLINK_FOLLOWS: u8 = 40;
919
920pub struct LookupContext {
925 pub symlink_mode: SymlinkMode,
930
931 pub remaining_follows: u8,
935
936 pub must_be_directory: bool,
942
943 pub resolve_flags: ResolveFlags,
945
946 pub resolve_base: ResolveBase,
949}
950
951#[derive(Clone, Eq, PartialEq)]
954pub enum ResolveBase {
955 None,
956
957 Beneath(NamespaceNode),
959
960 InRoot(NamespaceNode),
962}
963
964impl LookupContext {
965 pub fn new(symlink_mode: SymlinkMode) -> LookupContext {
966 LookupContext {
967 symlink_mode,
968 remaining_follows: MAX_SYMLINK_FOLLOWS,
969 must_be_directory: false,
970 resolve_flags: ResolveFlags::empty(),
971 resolve_base: ResolveBase::None,
972 }
973 }
974
975 pub fn with(&self, symlink_mode: SymlinkMode) -> LookupContext {
976 LookupContext { symlink_mode, resolve_base: self.resolve_base.clone(), ..*self }
977 }
978
979 pub fn update_for_path(&mut self, path: &FsStr) {
980 if path.last() == Some(&b'/') {
981 self.must_be_directory = true;
984 self.symlink_mode = SymlinkMode::Follow;
987 }
988 }
989}
990
991impl Default for LookupContext {
992 fn default() -> Self {
993 LookupContext::new(SymlinkMode::Follow)
994 }
995}
996
997pub enum PathWithReachability {
999 Reachable(FsString),
1001
1002 Unreachable(FsString),
1004}
1005
1006impl PathWithReachability {
1007 pub fn into_path(self) -> FsString {
1008 match self {
1009 PathWithReachability::Reachable(path) => path,
1010 PathWithReachability::Unreachable(path) => path,
1011 }
1012 }
1013}
1014
1015#[derive(Clone)]
1023pub struct NamespaceNode {
1024 pub mount: MountInfo,
1029
1030 pub entry: DirEntryHandle,
1032}
1033
1034impl NamespaceNode {
1035 pub fn new(mount: MountHandle, entry: DirEntryHandle) -> Self {
1036 Self { mount: Some(mount).into(), entry }
1037 }
1038
1039 pub fn new_anonymous(entry: DirEntryHandle) -> Self {
1041 Self { mount: None.into(), entry }
1042 }
1043
1044 pub fn new_anonymous_unrooted(current_task: &CurrentTask, node: FsNodeHandle) -> Self {
1047 let dir_entry = DirEntry::new_unrooted(node);
1048 let _ = security::fs_node_init_with_dentry_no_xattr(current_task, &dir_entry);
1049 Self::new_anonymous(dir_entry)
1050 }
1051
1052 pub fn open(
1058 &self,
1059 locked: &mut Locked<Unlocked>,
1060 current_task: &CurrentTask,
1061 flags: OpenFlags,
1062 access_check: AccessCheck,
1063 ) -> Result<FileHandle, Errno> {
1064 let ops = self.entry.node.open(locked, current_task, self, flags, access_check)?;
1065 FileObject::new(locked, current_task, ops, self.clone(), flags)
1066 }
1067
1068 pub fn open_create_node<L>(
1074 &self,
1075 locked: &mut Locked<L>,
1076 current_task: &CurrentTask,
1077 name: &FsStr,
1078 mode: FileMode,
1079 dev: DeviceId,
1080 flags: OpenFlags,
1081 ) -> Result<NamespaceNode, Errno>
1082 where
1083 L: LockEqualOrBefore<FileOpsCore>,
1084 {
1085 let owner = current_task.current_fscred();
1086 let mode = current_task.fs().apply_umask(mode);
1087 let create_fn =
1088 |locked: &mut Locked<L>, dir: &FsNodeHandle, mount: &MountInfo, name: &_| {
1089 dir.create_node(locked, current_task, mount, name, mode, dev, owner)
1090 };
1091 let entry = if flags.contains(OpenFlags::EXCL) {
1092 self.entry.create_entry(locked, current_task, &self.mount, name, create_fn)
1093 } else {
1094 self.entry.get_or_create_entry(locked, current_task, &self.mount, name, create_fn)
1095 }?;
1096 Ok(self.with_new_entry(entry))
1097 }
1098
1099 pub fn into_active(self) -> ActiveNamespaceNode {
1100 ActiveNamespaceNode::new(self)
1101 }
1102
1103 pub fn into_mapping(self, mode: Option<FileWriteGuardMode>) -> Result<Arc<FileMapping>, Errno> {
1104 self.into_active().into_mapping(mode)
1105 }
1106
1107 pub fn create_node<L>(
1113 &self,
1114 locked: &mut Locked<L>,
1115 current_task: &CurrentTask,
1116 name: &FsStr,
1117 mode: FileMode,
1118 dev: DeviceId,
1119 ) -> Result<NamespaceNode, Errno>
1120 where
1121 L: LockEqualOrBefore<FileOpsCore>,
1122 {
1123 let owner = current_task.current_fscred();
1124 let mode = current_task.fs().apply_umask(mode);
1125 let entry = self.entry.create_entry(
1126 locked,
1127 current_task,
1128 &self.mount,
1129 name,
1130 |locked, dir, mount, name| {
1131 dir.create_node(locked, current_task, mount, name, mode, dev, owner)
1132 },
1133 )?;
1134 Ok(self.with_new_entry(entry))
1135 }
1136
1137 pub fn create_symlink<L>(
1141 &self,
1142 locked: &mut Locked<L>,
1143 current_task: &CurrentTask,
1144 name: &FsStr,
1145 target: &FsStr,
1146 ) -> Result<NamespaceNode, Errno>
1147 where
1148 L: LockEqualOrBefore<FileOpsCore>,
1149 {
1150 let owner = current_task.current_fscred();
1151 let entry = self.entry.create_entry(
1152 locked,
1153 current_task,
1154 &self.mount,
1155 name,
1156 |locked, dir, mount, name| {
1157 dir.create_symlink(locked, current_task, mount, name, target, owner)
1158 },
1159 )?;
1160 Ok(self.with_new_entry(entry))
1161 }
1162
1163 pub fn create_tmpfile<L>(
1169 &self,
1170 locked: &mut Locked<L>,
1171 current_task: &CurrentTask,
1172 mode: FileMode,
1173 flags: OpenFlags,
1174 ) -> Result<NamespaceNode, Errno>
1175 where
1176 L: LockEqualOrBefore<FileOpsCore>,
1177 {
1178 let owner = current_task.current_fscred();
1179 let mode = current_task.fs().apply_umask(mode);
1180 Ok(self.with_new_entry(self.entry.create_tmpfile(
1181 locked,
1182 current_task,
1183 &self.mount,
1184 mode,
1185 owner,
1186 flags,
1187 )?))
1188 }
1189
1190 pub fn link<L>(
1191 &self,
1192 locked: &mut Locked<L>,
1193 current_task: &CurrentTask,
1194 name: &FsStr,
1195 child: &FsNodeHandle,
1196 ) -> Result<NamespaceNode, Errno>
1197 where
1198 L: LockEqualOrBefore<FileOpsCore>,
1199 {
1200 let dir_entry = self.entry.create_entry(
1201 locked,
1202 current_task,
1203 &self.mount,
1204 name,
1205 |locked, dir, mount, name| dir.link(locked, current_task, mount, name, child),
1206 )?;
1207 Ok(self.with_new_entry(dir_entry))
1208 }
1209
1210 pub fn bind_socket<L>(
1211 &self,
1212 locked: &mut Locked<L>,
1213 current_task: &CurrentTask,
1214 name: &FsStr,
1215 socket: SocketHandle,
1216 socket_address: SocketAddress,
1217 mode: FileMode,
1218 ) -> Result<NamespaceNode, Errno>
1219 where
1220 L: LockEqualOrBefore<FileOpsCore>,
1221 {
1222 let dir_entry = self.entry.create_entry(
1223 locked,
1224 current_task,
1225 &self.mount,
1226 name,
1227 |locked, dir, mount, name| {
1228 let node = dir.create_node(
1229 locked,
1230 current_task,
1231 mount,
1232 name,
1233 mode,
1234 DeviceId::NONE,
1235 current_task.current_fscred(),
1236 )?;
1237 if let Some(unix_socket) = socket.downcast_socket::<UnixSocket>() {
1238 unix_socket.bind_socket_to_node(&socket, socket_address, &node)?;
1239 } else {
1240 return error!(ENOTSUP);
1241 }
1242 Ok(node)
1243 },
1244 )?;
1245 Ok(self.with_new_entry(dir_entry))
1246 }
1247
1248 pub fn unlink<L>(
1249 &self,
1250 locked: &mut Locked<L>,
1251 current_task: &CurrentTask,
1252 name: &FsStr,
1253 kind: UnlinkKind,
1254 must_be_directory: bool,
1255 ) -> Result<(), Errno>
1256 where
1257 L: LockEqualOrBefore<FileOpsCore>,
1258 {
1259 if DirEntry::is_reserved_name(name) {
1260 match kind {
1261 UnlinkKind::Directory => {
1262 if name == ".." {
1263 error!(ENOTEMPTY)
1264 } else if self.parent().is_none() {
1265 error!(EBUSY)
1267 } else {
1268 error!(EINVAL)
1269 }
1270 }
1271 UnlinkKind::NonDirectory => error!(ENOTDIR),
1272 }
1273 } else {
1274 self.entry.unlink(locked, current_task, &self.mount, name, kind, must_be_directory)
1275 }
1276 }
1277
1278 fn resolve<L>(
1282 self,
1283 locked: &mut Locked<L>,
1284 current_task: &CurrentTask,
1285 context: &mut LookupContext,
1286 ) -> Result<NamespaceNode, Errno>
1287 where
1288 L: LockEqualOrBefore<FileOpsCore>,
1289 {
1290 let mut node = self;
1291
1292 loop {
1293 if !node.entry.node.is_lnk() || context.symlink_mode == SymlinkMode::NoFollow {
1294 break;
1295 }
1296 if context.remaining_follows == 0
1297 || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
1298 {
1299 return error!(ELOOP);
1300 }
1301 context.remaining_follows -= 1;
1302 node = match node.readlink(locked, current_task)? {
1303 SymlinkTarget::Path(link_target) => {
1304 let link_directory = if link_target[0] == b'/' {
1305 match &context.resolve_base {
1307 ResolveBase::None => current_task.fs().root(),
1308 ResolveBase::Beneath(_) => return error!(EXDEV),
1309 ResolveBase::InRoot(root) => root.clone(),
1310 }
1311 } else {
1312 node.parent().unwrap_or(node)
1316 };
1317 current_task.lookup_path(
1318 locked,
1319 context,
1320 link_directory,
1321 link_target.as_ref(),
1322 )?
1323 }
1324 SymlinkTarget::Node(node) => {
1325 if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS) {
1326 return error!(ELOOP);
1327 }
1328 node
1329 }
1330 };
1331 }
1332 Ok(node.enter_mount())
1333 }
1334
1335 pub fn lookup_child<L>(
1337 &self,
1338 locked: &mut Locked<L>,
1339 current_task: &CurrentTask,
1340 context: &mut LookupContext,
1341 basename: &FsStr,
1342 ) -> Result<NamespaceNode, Errno>
1343 where
1344 L: LockEqualOrBefore<FileOpsCore>,
1345 {
1346 self.lookup_children(locked, current_task, context, &[basename])
1347 }
1348
1349 pub fn lookup_children<L>(
1351 &self,
1352 locked: &mut Locked<L>,
1353 current_task: &CurrentTask,
1354 context: &mut LookupContext,
1355 mut basenames: &[&FsStr],
1356 ) -> Result<NamespaceNode, Errno>
1357 where
1358 L: LockEqualOrBefore<FileOpsCore>,
1359 {
1360 for name in basenames {
1361 if name.len() > NAME_MAX as usize {
1362 return error!(ENAMETOOLONG);
1363 }
1364 }
1365
1366 let mut current_namespace_node = self.clone();
1367
1368 while basenames.len() > 0 {
1369 if !current_namespace_node.entry.node.is_dir() {
1370 return error!(ENOTDIR);
1371 }
1372
1373 let basename = basenames[0];
1374 if basename.is_empty() || basename == "." {
1375 basenames = &basenames[1..];
1376 continue;
1377 }
1378 if basename == ".." {
1379 let root = match &context.resolve_base {
1380 ResolveBase::None => current_task.fs().root(),
1381 ResolveBase::Beneath(node) => {
1382 if current_namespace_node == *node {
1384 return error!(EXDEV);
1385 }
1386 current_task.fs().root()
1387 }
1388 ResolveBase::InRoot(root) => root.clone(),
1389 };
1390
1391 if current_namespace_node != root {
1393 current_namespace_node =
1394 current_namespace_node.parent().unwrap_or(current_namespace_node)
1395 }
1396 if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1397 && current_namespace_node.mount != self.mount
1398 {
1399 return error!(EXDEV);
1400 }
1401
1402 if context.must_be_directory && !current_namespace_node.entry.node.is_dir() {
1403 return error!(ENOTDIR);
1404 }
1405 basenames = &basenames[1..];
1406 continue;
1407 }
1408 if basenames.len() == 1
1409 || !current_namespace_node.entry.node.ops().has_lookup_pipelined()
1410 {
1411 current_namespace_node = current_namespace_node.with_new_entry(
1412 current_namespace_node.entry.component_lookup(
1413 locked,
1414 current_task,
1415 ¤t_namespace_node.mount,
1416 basename,
1417 )?,
1418 );
1419
1420 current_namespace_node =
1421 current_namespace_node.resolve(locked, current_task, context)?;
1422
1423 if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1424 && current_namespace_node.mount != self.mount
1425 {
1426 return error!(EXDEV);
1427 }
1428
1429 if context.must_be_directory && !current_namespace_node.entry.node.is_dir() {
1430 return error!(ENOTDIR);
1431 }
1432
1433 basenames = &basenames[1..];
1434 continue;
1435 }
1436
1437 let pipelined_basenames = if let Some(pos) =
1438 basenames.iter().position(|&name| name.is_empty() || name == "." || name == "..")
1439 {
1440 &basenames[..pos]
1441 } else {
1442 basenames
1443 };
1444 let precomputed_entries = current_namespace_node.entry.get_children_pipelined(
1445 locked,
1446 current_task,
1447 ¤t_namespace_node.mount,
1448 pipelined_basenames,
1449 );
1450 for entry in precomputed_entries {
1451 basenames = &basenames[1..];
1452 let child = current_namespace_node.with_new_entry(entry?);
1453
1454 current_namespace_node = child.clone().resolve(locked, current_task, context)?;
1455
1456 if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1457 && current_namespace_node.mount != self.mount
1458 {
1459 return error!(EXDEV);
1460 }
1461
1462 if context.must_be_directory && !current_namespace_node.entry.node.is_dir() {
1463 return error!(ENOTDIR);
1464 }
1465
1466 if current_namespace_node != child {
1467 break;
1468 }
1469 }
1470 }
1471
1472 Ok(current_namespace_node)
1473 }
1474
1475 pub fn parent(&self) -> Option<NamespaceNode> {
1481 let mountpoint_or_self = self.escape_mount();
1482 let parent = mountpoint_or_self.entry.parent()?;
1483 Some(mountpoint_or_self.with_new_entry(parent))
1484 }
1485
1486 pub fn parent_within_mount(&self) -> Option<DirEntryHandle> {
1489 if let Ok(_) = self.mount_if_root() {
1490 return None;
1491 }
1492 self.entry.parent()
1493 }
1494
1495 pub fn is_descendant_of(&self, ancestor: &NamespaceNode) -> bool {
1500 let ancestor = ancestor.escape_mount();
1501 let mut current = self.escape_mount();
1502 while current != ancestor {
1503 if let Some(parent) = current.parent() {
1504 current = parent.escape_mount();
1505 } else {
1506 return false;
1507 }
1508 }
1509 true
1510 }
1511
1512 fn enter_mount(&self) -> NamespaceNode {
1514 fn enter_one_mount(node: &NamespaceNode) -> Option<NamespaceNode> {
1516 if let Some(mount) = node.mount.deref() {
1517 if let Some(submount) =
1518 mount.state.read().submounts.get(ArcKey::ref_cast(&node.entry))
1519 {
1520 return Some(submount.mount.root());
1521 }
1522 }
1523 None
1524 }
1525 let mut inner = self.clone();
1526 while let Some(inner_root) = enter_one_mount(&inner) {
1527 inner = inner_root;
1528 }
1529 inner
1530 }
1531
1532 fn escape_mount(&self) -> NamespaceNode {
1537 let mut mountpoint_or_self = self.clone();
1538 while let Some(mountpoint) = mountpoint_or_self.mountpoint() {
1539 mountpoint_or_self = mountpoint;
1540 }
1541 mountpoint_or_self
1542 }
1543
1544 pub fn mount_if_root(&self) -> Result<&MountHandle, Errno> {
1546 if let Some(mount) = self.mount.deref() {
1547 if Arc::ptr_eq(&self.entry, &mount.root) {
1548 return Ok(mount);
1549 }
1550 }
1551 error!(EINVAL)
1552 }
1553
1554 fn mountpoint(&self) -> Option<NamespaceNode> {
1559 self.mount_if_root().ok()?.read().mountpoint()
1560 }
1561
1562 pub fn path(&self, fs: &FsContext) -> FsString {
1564 self.path_from_root(Some(&fs.root())).into_path()
1565 }
1566
1567 pub fn path_escaping_chroot(&self) -> FsString {
1569 self.path_from_root(None).into_path()
1570 }
1571
1572 pub fn path_from_root(&self, root: Option<&NamespaceNode>) -> PathWithReachability {
1575 if self.mount.is_none() {
1576 return PathWithReachability::Reachable(self.entry.node.internal_name());
1577 }
1578
1579 let mut path = PathBuilder::new();
1580 let mut current = self.escape_mount();
1581 if let Some(root) = root {
1582 let scope = RcuReadScope::new();
1583 let root = root.escape_mount();
1585 while current != root {
1586 if let Some(parent) = current.parent() {
1587 path.prepend_element(current.entry.local_name(&scope));
1588 current = parent.escape_mount();
1589 } else {
1590 let mut absolute_path = path.build_absolute();
1592 if self.entry.is_dead() {
1593 absolute_path.extend_from_slice(b" (deleted)");
1594 }
1595
1596 return PathWithReachability::Unreachable(absolute_path);
1597 }
1598 }
1599 } else {
1600 let scope = RcuReadScope::new();
1602 while let Some(parent) = current.parent() {
1603 path.prepend_element(current.entry.local_name(&scope));
1604 current = parent.escape_mount();
1605 }
1606 }
1607
1608 let mut absolute_path = path.build_absolute();
1609 if self.entry.is_dead() {
1610 absolute_path.extend_from_slice(b" (deleted)");
1611 }
1612
1613 PathWithReachability::Reachable(absolute_path)
1614 }
1615
1616 pub fn mount(&self, what: WhatToMount, flags: MountpointFlags) -> Result<(), Errno> {
1617 let mountpoint = self.enter_mount();
1618 let mount = mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount");
1619 mount.create_submount(&mountpoint.entry, what, flags);
1620 Ok(())
1621 }
1622
1623 pub fn unmount(&self, flags: UnmountFlags) -> Result<(), Errno> {
1625 let mount = self.enter_mount().mount_if_root()?.clone();
1626 mount.unmount(flags)
1627 }
1628
1629 pub fn rename<L>(
1630 locked: &mut Locked<L>,
1631 current_task: &CurrentTask,
1632 old_parent: &NamespaceNode,
1633 old_name: &FsStr,
1634 new_parent: &NamespaceNode,
1635 new_name: &FsStr,
1636 flags: RenameFlags,
1637 ) -> Result<(), Errno>
1638 where
1639 L: LockEqualOrBefore<FileOpsCore>,
1640 {
1641 DirEntry::rename(
1642 locked,
1643 current_task,
1644 &old_parent.entry,
1645 &old_parent.mount,
1646 old_name,
1647 &new_parent.entry,
1648 &new_parent.mount,
1649 new_name,
1650 flags,
1651 )
1652 }
1653
1654 fn with_new_entry(&self, entry: DirEntryHandle) -> NamespaceNode {
1655 Self { mount: self.mount.clone(), entry }
1656 }
1657
1658 fn mount_hash_key(&self) -> &ArcKey<DirEntry> {
1659 ArcKey::ref_cast(&self.entry)
1660 }
1661
1662 pub fn suid_and_sgid(&self, current_task: &CurrentTask) -> Result<UserAndOrGroupId, Errno> {
1663 if self.mount.flags().contains(MountFlags::NOSUID) {
1664 Ok(UserAndOrGroupId::default())
1665 } else {
1666 self.entry.node.info().suid_and_sgid(current_task, &self.entry.node)
1667 }
1668 }
1669
1670 pub fn update_atime(&self) {
1671 if !self.mount.flags().contains(MountFlags::NOATIME) {
1673 self.entry.node.update_info(|info| {
1674 let now = utc::utc_now();
1675 info.time_access = now;
1676 info.pending_time_access_update = true;
1677 });
1678 }
1679 }
1680
1681 pub fn readlink<L>(
1682 &self,
1683 locked: &mut Locked<L>,
1684 current_task: &CurrentTask,
1685 ) -> Result<SymlinkTarget, Errno>
1686 where
1687 L: LockEqualOrBefore<FileOpsCore>,
1688 {
1689 self.update_atime();
1690 self.entry.node.readlink(locked, current_task)
1691 }
1692
1693 pub fn notify(&self, event_mask: InotifyMask) {
1694 if self.mount.is_some() {
1695 self.entry.notify(event_mask);
1696 }
1697 }
1698
1699 pub fn check_access<L>(
1703 &self,
1704 locked: &mut Locked<L>,
1705 current_task: &CurrentTask,
1706 permission_flags: impl Into<security::PermissionFlags>,
1707 reason: CheckAccessReason,
1708 ) -> Result<(), Errno>
1709 where
1710 L: LockEqualOrBefore<FileOpsCore>,
1711 {
1712 self.entry.node.check_access(
1713 locked,
1714 current_task,
1715 &self.mount,
1716 permission_flags,
1717 reason,
1718 self,
1719 )
1720 }
1721
1722 pub fn check_o_noatime_allowed(&self, current_task: &CurrentTask) -> Result<(), Errno> {
1724 self.entry.node.check_o_noatime_allowed(current_task)
1725 }
1726
1727 pub fn truncate<L>(
1728 &self,
1729 locked: &mut Locked<L>,
1730 current_task: &CurrentTask,
1731 length: u64,
1732 ) -> Result<(), Errno>
1733 where
1734 L: LockEqualOrBefore<BeforeFsNodeAppend>,
1735 {
1736 self.entry.node.truncate(locked, current_task, &self.mount, length)?;
1737 self.entry.notify_ignoring_excl_unlink(InotifyMask::MODIFY);
1738 Ok(())
1739 }
1740}
1741
1742impl fmt::Debug for NamespaceNode {
1743 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1744 f.debug_struct("NamespaceNode")
1745 .field("path", &self.path_escaping_chroot())
1746 .field("mount", &self.mount)
1747 .field("entry", &self.entry)
1748 .finish()
1749 }
1750}
1751
1752impl PartialEq for NamespaceNode {
1754 fn eq(&self, other: &Self) -> bool {
1755 self.mount.as_ref().map(Arc::as_ptr).eq(&other.mount.as_ref().map(Arc::as_ptr))
1756 && Arc::ptr_eq(&self.entry, &other.entry)
1757 }
1758}
1759impl Eq for NamespaceNode {}
1760impl Hash for NamespaceNode {
1761 fn hash<H: Hasher>(&self, state: &mut H) {
1762 self.mount.as_ref().map(Arc::as_ptr).hash(state);
1763 Arc::as_ptr(&self.entry).hash(state);
1764 }
1765}
1766
1767#[derive(Debug, Clone)]
1769pub struct ActiveNamespaceNode {
1770 name: NamespaceNode,
1772
1773 _marker: Option<MountClientMarker>,
1777}
1778
1779impl ActiveNamespaceNode {
1780 pub fn new(name: NamespaceNode) -> Self {
1781 let marker = name.mount.as_ref().map(|mount| mount.active_client_counter.clone());
1782 Self { name, _marker: marker }
1783 }
1784
1785 pub fn to_passive(&self) -> NamespaceNode {
1786 self.deref().clone()
1787 }
1788
1789 pub fn into_mapping(self, mode: Option<FileWriteGuardMode>) -> Result<Arc<FileMapping>, Errno> {
1790 if let Some(mode) = mode {
1791 self.entry.node.write_guard_state.lock().acquire(mode)?;
1792 }
1793 Ok(Arc::new(FileMapping { name: self, mode }))
1794 }
1795}
1796
1797impl Deref for ActiveNamespaceNode {
1798 type Target = NamespaceNode;
1799
1800 fn deref(&self) -> &Self::Target {
1801 &self.name
1802 }
1803}
1804
1805impl PartialEq for ActiveNamespaceNode {
1806 fn eq(&self, other: &Self) -> bool {
1807 self.deref().eq(other.deref())
1808 }
1809}
1810impl Eq for ActiveNamespaceNode {}
1811impl Hash for ActiveNamespaceNode {
1812 fn hash<H: Hasher>(&self, state: &mut H) {
1813 self.deref().hash(state)
1814 }
1815}
1816
1817#[derive(Debug, Clone, PartialEq, Eq)]
1818#[must_use]
1819pub struct FileMapping {
1820 pub name: ActiveNamespaceNode,
1821 mode: Option<FileWriteGuardMode>,
1822}
1823
1824impl Drop for FileMapping {
1825 fn drop(&mut self) {
1826 if let Some(mode) = self.mode {
1827 self.name.entry.node.write_guard_state.lock().release(mode);
1828 }
1829 }
1830}
1831
1832pub struct Mounts {
1834 mounts: RcuHashMap<WeakKey<DirEntry>, Vec<ArcKey<Mount>>>,
1835}
1836
1837impl Mounts {
1838 pub fn new() -> Self {
1839 Mounts { mounts: RcuHashMap::default() }
1840 }
1841
1842 fn register_mount(&self, dir_entry: &Arc<DirEntry>, mount: MountHandle) -> Submount {
1844 let mut mounts = self.mounts.lock();
1845 let key = WeakKey::from(dir_entry);
1846 let mut vec = mounts.get(&key).unwrap_or_else(|| {
1847 dir_entry.set_has_mounts(true);
1848 Vec::new()
1849 });
1850 vec.push(ArcKey(mount.clone()));
1851 mounts.insert(key, vec);
1852 Submount { dir: ArcKey(dir_entry.clone()), mount }
1853 }
1854
1855 fn unregister_mount(&self, dir_entry: &Arc<DirEntry>, mount: &MountHandle) {
1857 let mut mounts = self.mounts.lock();
1858 let key = WeakKey::from(dir_entry);
1859 if let Some(mut vec) = mounts.get(&key) {
1860 let index = vec.iter().position(|e| e == ArcKey::ref_cast(mount)).unwrap();
1861 if vec.len() == 1 {
1862 mounts.remove(&key);
1863 dir_entry.set_has_mounts(false);
1864 } else {
1865 vec.swap_remove(index);
1866 mounts.insert(key, vec);
1867 }
1868 }
1869 }
1870
1871 pub fn unmount(&self, dir_entry: &DirEntry) {
1875 let mounts = self.mounts.lock().remove(&PtrKey::from(dir_entry as *const _));
1876 if let Some(mounts) = mounts {
1877 for mount in mounts {
1878 let _ = mount.unmount(UnmountFlags::DETACH);
1880 }
1881 }
1882 }
1883
1884 pub fn clear(&self) {
1888 for (_dir_entry, mounts) in self.mounts.lock().drain() {
1889 for mount in mounts {
1890 mount.fs.force_unmount_ops();
1891 }
1892 }
1893 }
1894
1895 pub fn sync_all(
1896 &self,
1897 locked: &mut Locked<Unlocked>,
1898 current_task: &CurrentTask,
1899 ) -> Result<(), Errno> {
1900 let mut filesystems = Vec::new();
1901 {
1902 let scope = RcuReadScope::new();
1903 let mut seen = HashSet::new();
1904 for (_dir_entry, m_list) in self.mounts.iter(&scope) {
1905 for m in m_list {
1906 if seen.insert(Arc::as_ptr(&m.fs)) {
1907 filesystems.push(m.fs.clone());
1908 }
1909 }
1910 }
1911 }
1912
1913 for fs in filesystems {
1914 if let Err(e) = fs.sync(locked, current_task) {
1915 log_warn!("sync failed for filesystem {:?}: {:?}", fs.name(), e);
1916 }
1917 }
1918 Ok(())
1919 }
1920}
1921
1922#[derive(Debug)]
1924struct Submount {
1925 dir: ArcKey<DirEntry>,
1926 mount: MountHandle,
1927}
1928
1929impl Drop for Submount {
1930 fn drop(&mut self) {
1931 self.mount.fs.kernel.upgrade().unwrap().mounts.unregister_mount(&self.dir, &self.mount)
1932 }
1933}
1934
1935impl Eq for Submount {}
1937impl PartialEq<Self> for Submount {
1938 fn eq(&self, other: &Self) -> bool {
1939 self.dir == other.dir
1940 }
1941}
1942impl Hash for Submount {
1943 fn hash<H: Hasher>(&self, state: &mut H) {
1944 self.dir.hash(state)
1945 }
1946}
1947
1948impl Borrow<ArcKey<DirEntry>> for Submount {
1949 fn borrow(&self) -> &ArcKey<DirEntry> {
1950 &self.dir
1951 }
1952}
1953
1954#[cfg(test)]
1955mod test {
1956 use crate::fs::tmpfs::TmpFs;
1957 use crate::testing::spawn_kernel_and_run;
1958 use crate::vfs::namespace::DeviceId;
1959 use crate::vfs::{
1960 CallbackSymlinkNode, FsNodeInfo, LookupContext, MountInfo, Namespace, NamespaceNode,
1961 RenameFlags, SymlinkMode, SymlinkTarget, UnlinkKind, WhatToMount,
1962 };
1963 use starnix_uapi::mount_flags::MountpointFlags;
1964 use starnix_uapi::{errno, mode};
1965 use std::sync::Arc;
1966
1967 #[::fuchsia::test]
1968 async fn test_namespace() {
1969 spawn_kernel_and_run(async |locked, current_task| {
1970 let kernel = current_task.kernel();
1971 let root_fs = TmpFs::new_fs(locked, &kernel);
1972 let root_node = Arc::clone(root_fs.root());
1973 let _dev_node = root_node
1974 .create_dir(locked, ¤t_task, "dev".into())
1975 .expect("failed to mkdir dev");
1976 let dev_fs = TmpFs::new_fs(locked, &kernel);
1977 let dev_root_node = Arc::clone(dev_fs.root());
1978 let _dev_pts_node = dev_root_node
1979 .create_dir(locked, ¤t_task, "pts".into())
1980 .expect("failed to mkdir pts");
1981
1982 let ns = Namespace::new(root_fs);
1983 let mut context = LookupContext::default();
1984 let dev = ns
1985 .root()
1986 .lookup_child(locked, ¤t_task, &mut context, "dev".into())
1987 .expect("failed to lookup dev");
1988 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
1989 .expect("failed to mount dev root node");
1990
1991 let mut context = LookupContext::default();
1992 let dev = ns
1993 .root()
1994 .lookup_child(locked, ¤t_task, &mut context, "dev".into())
1995 .expect("failed to lookup dev");
1996 let mut context = LookupContext::default();
1997 let pts = dev
1998 .lookup_child(locked, ¤t_task, &mut context, "pts".into())
1999 .expect("failed to lookup pts");
2000 let pts_parent =
2001 pts.parent().ok_or_else(|| errno!(ENOENT)).expect("failed to get parent of pts");
2002 assert!(Arc::ptr_eq(&pts_parent.entry, &dev.entry));
2003
2004 let dev_parent =
2005 dev.parent().ok_or_else(|| errno!(ENOENT)).expect("failed to get parent of dev");
2006 assert!(Arc::ptr_eq(&dev_parent.entry, &ns.root().entry));
2007 })
2008 .await;
2009 }
2010
2011 #[::fuchsia::test]
2012 async fn test_mount_does_not_upgrade() {
2013 spawn_kernel_and_run(async |locked, current_task| {
2014 let kernel = current_task.kernel();
2015 let root_fs = TmpFs::new_fs(locked, &kernel);
2016 let root_node = Arc::clone(root_fs.root());
2017 let _dev_node = root_node
2018 .create_dir(locked, ¤t_task, "dev".into())
2019 .expect("failed to mkdir dev");
2020 let dev_fs = TmpFs::new_fs(locked, &kernel);
2021 let dev_root_node = Arc::clone(dev_fs.root());
2022 let _dev_pts_node = dev_root_node
2023 .create_dir(locked, ¤t_task, "pts".into())
2024 .expect("failed to mkdir pts");
2025
2026 let ns = Namespace::new(root_fs);
2027 let mut context = LookupContext::default();
2028 let dev = ns
2029 .root()
2030 .lookup_child(locked, ¤t_task, &mut context, "dev".into())
2031 .expect("failed to lookup dev");
2032 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2033 .expect("failed to mount dev root node");
2034 let mut context = LookupContext::default();
2035 let new_dev = ns
2036 .root()
2037 .lookup_child(locked, ¤t_task, &mut context, "dev".into())
2038 .expect("failed to lookup dev again");
2039 assert!(!Arc::ptr_eq(&dev.entry, &new_dev.entry));
2040 assert_ne!(&dev, &new_dev);
2041
2042 let mut context = LookupContext::default();
2043 let _new_pts = new_dev
2044 .lookup_child(locked, ¤t_task, &mut context, "pts".into())
2045 .expect("failed to lookup pts");
2046 let mut context = LookupContext::default();
2047 assert!(dev.lookup_child(locked, ¤t_task, &mut context, "pts".into()).is_err());
2048 })
2049 .await;
2050 }
2051
2052 #[::fuchsia::test]
2053 async fn test_path() {
2054 spawn_kernel_and_run(async |locked, current_task| {
2055 let kernel = current_task.kernel();
2056 let root_fs = TmpFs::new_fs(locked, &kernel);
2057 let root_node = Arc::clone(root_fs.root());
2058 let _dev_node = root_node
2059 .create_dir(locked, ¤t_task, "dev".into())
2060 .expect("failed to mkdir dev");
2061 let dev_fs = TmpFs::new_fs(locked, &kernel);
2062 let dev_root_node = Arc::clone(dev_fs.root());
2063 let _dev_pts_node = dev_root_node
2064 .create_dir(locked, ¤t_task, "pts".into())
2065 .expect("failed to mkdir pts");
2066
2067 let ns = Namespace::new(root_fs);
2068 let mut context = LookupContext::default();
2069 let dev = ns
2070 .root()
2071 .lookup_child(locked, ¤t_task, &mut context, "dev".into())
2072 .expect("failed to lookup dev");
2073 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2074 .expect("failed to mount dev root node");
2075
2076 let mut context = LookupContext::default();
2077 let dev = ns
2078 .root()
2079 .lookup_child(locked, ¤t_task, &mut context, "dev".into())
2080 .expect("failed to lookup dev");
2081 let mut context = LookupContext::default();
2082 let pts = dev
2083 .lookup_child(locked, ¤t_task, &mut context, "pts".into())
2084 .expect("failed to lookup pts");
2085
2086 assert_eq!("/", ns.root().path_escaping_chroot());
2087 assert_eq!("/dev", dev.path_escaping_chroot());
2088 assert_eq!("/dev/pts", pts.path_escaping_chroot());
2089 })
2090 .await;
2091 }
2092
2093 #[::fuchsia::test]
2094 async fn test_shadowing() {
2095 spawn_kernel_and_run(async |locked, current_task| {
2096 let kernel = current_task.kernel();
2097 let root_fs = TmpFs::new_fs(locked, &kernel);
2098 let ns = Namespace::new(root_fs.clone());
2099 let _foo_node = root_fs.root().create_dir(locked, ¤t_task, "foo".into()).unwrap();
2100 let mut context = LookupContext::default();
2101 let foo_dir =
2102 ns.root().lookup_child(locked, ¤t_task, &mut context, "foo".into()).unwrap();
2103
2104 let foofs1 = TmpFs::new_fs(locked, &kernel);
2105 foo_dir.mount(WhatToMount::Fs(foofs1.clone()), MountpointFlags::empty()).unwrap();
2106 let mut context = LookupContext::default();
2107 assert!(Arc::ptr_eq(
2108 &ns.root()
2109 .lookup_child(locked, ¤t_task, &mut context, "foo".into())
2110 .unwrap()
2111 .entry,
2112 foofs1.root()
2113 ));
2114 let foo_dir =
2115 ns.root().lookup_child(locked, ¤t_task, &mut context, "foo".into()).unwrap();
2116
2117 let ns_clone = ns.clone_namespace();
2118
2119 let foofs2 = TmpFs::new_fs(locked, &kernel);
2120 foo_dir.mount(WhatToMount::Fs(foofs2.clone()), MountpointFlags::empty()).unwrap();
2121 let mut context = LookupContext::default();
2122 assert!(Arc::ptr_eq(
2123 &ns.root()
2124 .lookup_child(locked, ¤t_task, &mut context, "foo".into())
2125 .unwrap()
2126 .entry,
2127 foofs2.root()
2128 ));
2129
2130 assert!(Arc::ptr_eq(
2131 &ns_clone
2132 .root()
2133 .lookup_child(
2134 locked,
2135 ¤t_task,
2136 &mut LookupContext::default(),
2137 "foo".into()
2138 )
2139 .unwrap()
2140 .entry,
2141 foofs1.root()
2142 ));
2143 })
2144 .await;
2145 }
2146
2147 #[::fuchsia::test]
2148 async fn test_unlink_mounted_directory() {
2149 spawn_kernel_and_run(async |locked, current_task| {
2150 let kernel = current_task.kernel();
2151 let root_fs = TmpFs::new_fs(locked, &kernel);
2152 let ns1 = Namespace::new(root_fs.clone());
2153 let ns2 = Namespace::new(root_fs.clone());
2154 let _foo_node = root_fs.root().create_dir(locked, ¤t_task, "foo".into()).unwrap();
2155 let mut context = LookupContext::default();
2156 let foo_dir =
2157 ns1.root().lookup_child(locked, ¤t_task, &mut context, "foo".into()).unwrap();
2158
2159 let foofs = TmpFs::new_fs(locked, &kernel);
2160 foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2161
2162 assert_eq!(
2164 ns1.root()
2165 .unlink(locked, ¤t_task, "foo".into(), UnlinkKind::Directory, false)
2166 .unwrap_err(),
2167 errno!(EBUSY),
2168 );
2169
2170 ns2.root()
2172 .unlink(locked, ¤t_task, "foo".into(), UnlinkKind::Directory, false)
2173 .expect("unlink failed");
2174
2175 assert_eq!(
2177 ns1.root()
2178 .unlink(locked, ¤t_task, "foo".into(), UnlinkKind::Directory, false)
2179 .unwrap_err(),
2180 errno!(ENOENT),
2181 );
2182 })
2183 .await;
2184 }
2185
2186 #[::fuchsia::test]
2187 async fn test_rename_mounted_directory() {
2188 spawn_kernel_and_run(async |locked, current_task| {
2189 let kernel = current_task.kernel();
2190 let root_fs = TmpFs::new_fs(locked, &kernel);
2191 let ns1 = Namespace::new(root_fs.clone());
2192 let ns2 = Namespace::new(root_fs.clone());
2193 let _foo_node = root_fs.root().create_dir(locked, ¤t_task, "foo".into()).unwrap();
2194 let _bar_node = root_fs.root().create_dir(locked, ¤t_task, "bar".into()).unwrap();
2195 let _baz_node = root_fs.root().create_dir(locked, ¤t_task, "baz".into()).unwrap();
2196 let mut context = LookupContext::default();
2197 let foo_dir =
2198 ns1.root().lookup_child(locked, ¤t_task, &mut context, "foo".into()).unwrap();
2199
2200 let foofs = TmpFs::new_fs(locked, &kernel);
2201 foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2202
2203 let root = ns1.root();
2205 assert_eq!(
2206 NamespaceNode::rename(
2207 locked,
2208 ¤t_task,
2209 &root,
2210 "bar".into(),
2211 &root,
2212 "foo".into(),
2213 RenameFlags::empty()
2214 )
2215 .unwrap_err(),
2216 errno!(EBUSY),
2217 );
2218 assert_eq!(
2220 NamespaceNode::rename(
2221 locked,
2222 ¤t_task,
2223 &root,
2224 "foo".into(),
2225 &root,
2226 "bar".into(),
2227 RenameFlags::empty()
2228 )
2229 .unwrap_err(),
2230 errno!(EBUSY),
2231 );
2232
2233 let root = ns2.root();
2235
2236 NamespaceNode::rename(
2238 locked,
2239 ¤t_task,
2240 &root,
2241 "foo".into(),
2242 &root,
2243 "bar".into(),
2244 RenameFlags::empty(),
2245 )
2246 .expect("rename failed");
2247
2248 NamespaceNode::rename(
2250 locked,
2251 ¤t_task,
2252 &root,
2253 "baz".into(),
2254 &root,
2255 "bar".into(),
2256 RenameFlags::empty(),
2257 )
2258 .expect("rename failed");
2259
2260 assert_eq!(
2262 ns1.root()
2263 .lookup_child(locked, ¤t_task, &mut context, "foo".into())
2264 .unwrap_err(),
2265 errno!(ENOENT)
2266 );
2267 assert_eq!(
2268 ns1.root()
2269 .lookup_child(locked, ¤t_task, &mut context, "baz".into())
2270 .unwrap_err(),
2271 errno!(ENOENT)
2272 );
2273 })
2274 .await;
2275 }
2276
2277 #[::fuchsia::test]
2280 async fn test_lookup_with_symlink_chain() {
2281 spawn_kernel_and_run(async |locked, current_task| {
2282 let kernel = current_task.kernel();
2284 let root_fs = TmpFs::new_fs(locked, &kernel);
2285 let root_node = Arc::clone(root_fs.root());
2286 let _first_subdir_node = root_node
2287 .create_dir(locked, ¤t_task, "first_subdir".into())
2288 .expect("failed to mkdir dev");
2289 let _second_subdir_node = root_node
2290 .create_dir(locked, ¤t_task, "second_subdir".into())
2291 .expect("failed to mkdir dev");
2292
2293 let first_subdir_fs = TmpFs::new_fs(locked, &kernel);
2295 let second_subdir_fs = TmpFs::new_fs(locked, &kernel);
2296
2297 let ns = Namespace::new(root_fs);
2298 let mut context = LookupContext::default();
2299 let first_subdir = ns
2300 .root()
2301 .lookup_child(locked, ¤t_task, &mut context, "first_subdir".into())
2302 .expect("failed to lookup first_subdir");
2303 first_subdir
2304 .mount(WhatToMount::Fs(first_subdir_fs), MountpointFlags::empty())
2305 .expect("failed to mount first_subdir fs node");
2306 let second_subdir = ns
2307 .root()
2308 .lookup_child(locked, ¤t_task, &mut context, "second_subdir".into())
2309 .expect("failed to lookup second_subdir");
2310 second_subdir
2311 .mount(WhatToMount::Fs(second_subdir_fs), MountpointFlags::empty())
2312 .expect("failed to mount second_subdir fs node");
2313
2314 let real_file_node = first_subdir
2323 .create_node(
2324 locked,
2325 ¤t_task,
2326 "real_file".into(),
2327 mode!(IFREG, 0o777),
2328 DeviceId::NONE,
2329 )
2330 .expect("failed to create real_file");
2331 first_subdir
2332 .create_symlink(locked, ¤t_task, "path_symlink".into(), "real_file".into())
2333 .expect("failed to create path_symlink");
2334
2335 let mut no_follow_lookup_context = LookupContext::new(SymlinkMode::NoFollow);
2336 let path_symlink_node = first_subdir
2337 .lookup_child(
2338 locked,
2339 ¤t_task,
2340 &mut no_follow_lookup_context,
2341 "path_symlink".into(),
2342 )
2343 .expect("Failed to lookup path_symlink");
2344
2345 let node_symlink_node = second_subdir.entry.node.fs().create_node_and_allocate_node_id(
2349 CallbackSymlinkNode::new(move || {
2350 let node = path_symlink_node.clone();
2351 Ok(SymlinkTarget::Node(node))
2352 }),
2353 FsNodeInfo::new(mode!(IFLNK, 0o777), current_task.current_fscred()),
2354 );
2355 second_subdir
2356 .entry
2357 .create_entry(
2358 locked,
2359 ¤t_task,
2360 &MountInfo::detached(),
2361 "node_symlink".into(),
2362 move |_locked, _dir, _mount, _name| Ok(node_symlink_node),
2363 )
2364 .expect("failed to create node_symlink entry");
2365
2366 let mut follow_lookup_context = LookupContext::new(SymlinkMode::Follow);
2368 let node_symlink_resolution = second_subdir
2369 .lookup_child(
2370 locked,
2371 ¤t_task,
2372 &mut follow_lookup_context,
2373 "node_symlink".into(),
2374 )
2375 .expect("lookup with symlink chain failed");
2376
2377 assert!(node_symlink_resolution.entry.node.ino == real_file_node.entry.node.ino);
2379 })
2380 .await;
2381 }
2382}