1use crate::security;
6use crate::task::{
7 CurrentTask, EventHandler, Kernel, MountsWriteToken, Pid, WaitCanceler, Waiter,
8 register_delayed_call,
9};
10use crate::time::utc;
11use crate::vfs::fs_registry::FsRegistry;
12use crate::vfs::pseudo::dynamic_file::{DynamicFile, DynamicFileBuf, DynamicFileSource};
13use crate::vfs::pseudo::simple_file::SimpleFileNode;
14use crate::vfs::socket::{SocketAddress, SocketHandle, UnixSocket};
15use crate::vfs::{
16 AccessCheck, DirEntry, DirEntryHandle, FileHandle, FileObject, FileOps, FileSystem,
17 FileSystemHandle, FileSystemOptions, FileWriteGuardMode, FsContext, FsNode, FsNodeHandle,
18 FsNodeOps, FsStr, FsString, OpenAccessCheck, PathBuilder, RenameFlags, SymlinkTarget,
19 UnlinkKind, fileops_impl_dataless, fileops_impl_delegate_read_write_and_seek,
20 fileops_impl_nonseekable, fileops_impl_noop_sync, fs_node_impl_not_dir,
21};
22use fuchsia_rcu::{RcuArc, RcuBox, RcuReadScope};
23use fuchsia_rcu_collections::rcu_raw_hash_map::RcuRawHashMap;
24use fuchsia_sync::Mutex;
25use starnix_logging::log_warn;
26use starnix_rcu::RcuHashMap;
27use starnix_sync::{LockDepMutex, NamespaceFlagsLock};
28use starnix_uapi::arc_key::{ArcKey, PtrKey, WeakKey};
29use starnix_uapi::auth::Credentials;
30use starnix_uapi::device_id::DeviceId;
31use starnix_uapi::errors::Errno;
32use starnix_uapi::file_mode::FileMode;
33use starnix_uapi::inotify_mask::InotifyMask;
34use starnix_uapi::mount_flags::{
35 AtomicMountpointFlags, FileSystemFlags, MountFlags, MountpointFlags,
36};
37use starnix_uapi::open_flags::OpenFlags;
38use starnix_uapi::unmount_flags::UnmountFlags;
39use starnix_uapi::vfs::{FdEvents, ResolveFlags};
40use starnix_uapi::{NAME_MAX, errno, error};
41use std::collections::{HashMap, HashSet};
42use std::fmt;
43use std::hash::{Hash, Hasher};
44use std::ops::{Deref, DerefMut};
45use std::sync::atomic::Ordering;
46use std::sync::{Arc, Weak};
47
48#[derive(Debug)]
52pub struct Namespace {
53 root_mount: MountHandle,
54
55 pub id: u64,
57}
58
59impl Namespace {
60 pub fn new(fs: FileSystemHandle) -> Arc<Namespace> {
61 Self::new_with_flags(fs, MountpointFlags::empty())
62 }
63
64 pub fn new_with_flags(fs: FileSystemHandle, flags: MountpointFlags) -> Arc<Namespace> {
65 let kernel = fs.kernel.upgrade().expect("can't create namespace without a kernel");
66 let mounts_guard = kernel.mounts_lock();
67
68 let root_mount = Mount::new(&mounts_guard, WhatToMount::Fs(fs), flags)
69 .expect("creating root mount for new filesystem");
70 Arc::new(Self { root_mount, id: kernel.get_next_namespace_id() })
71 }
72
73 pub fn root(&self) -> NamespaceNode {
74 self.root_mount.root()
75 }
76
77 pub fn kernel(&self) -> Arc<Kernel> {
78 self.root_mount.kernel()
79 }
80
81 pub fn clone_namespace(&self, mounts_guard: &MountsWriteToken) -> Arc<Namespace> {
82 Arc::new(Self {
83 root_mount: self.root_mount.clone_mount_recursive(mounts_guard),
84 id: self.kernel().get_next_namespace_id(),
85 })
86 }
87
88 pub fn translate_node(
91 node: NamespaceNode,
92 new_ns: &Namespace,
93 mounts_guard: &MountsWriteToken,
94 ) -> Option<NamespaceNode> {
95 let mut node = mounts_guard.defer_drop(node);
96 let mut mountpoints = vec![];
98 let mut mount = node.mount.clone();
99 while let Some(mountpoint) = mount.as_ref().and_then(|m| m.mountpoint()) {
100 mountpoints.push(mountpoint.entry);
101 let prev = std::mem::replace(&mut mount, mountpoint.mount);
102 mounts_guard.defer_drop(prev);
103 }
104 mounts_guard.defer_drop(mount);
105 let mountpoints = mounts_guard.defer_drop(mountpoints);
106
107 let scope = RcuReadScope::new();
109 let mut mount = Arc::clone(&new_ns.root_mount);
110 for mountpoint in mountpoints.iter().rev() {
111 let next_mount = match mount.relations.get_submount(&scope, &PtrKey::from(mountpoint)) {
112 Some(m) => m,
113 None => {
114 mounts_guard.defer_drop(mount);
115 return None;
116 }
117 };
118 mounts_guard.defer_drop(std::mem::replace(&mut mount, next_mount));
119 }
120 mounts_guard.defer_drop(std::mem::replace(&mut node.mount, Some(mount).into()));
121 Some(scopeguard::ScopeGuard::into_inner(node))
122 }
123
124 pub fn pivot_root(
125 self: &Arc<Namespace>,
126 current_root: &NamespaceNode,
127 new_root: &NamespaceNode,
128 put_old: &NamespaceNode,
129 ) -> Result<(), Errno> {
130 debug_assert!(new_root.entry.node.is_dir());
131 debug_assert!(put_old.entry.node.is_dir());
132
133 let new_root_mount = new_root.mount.as_ref().ok_or_else(|| errno!(EINVAL))?;
134 let current_root_mount = current_root.mount.as_ref().ok_or_else(|| errno!(EINVAL))?;
135 let put_old_mount = put_old.mount.as_ref().ok_or_else(|| errno!(EINVAL))?;
136
137 let current_root_mountpoint =
138 current_root_mount.mountpoint().ok_or_else(|| errno!(EINVAL))?;
139 let new_root_mountpoint = new_root_mount.mountpoint().ok_or_else(|| errno!(EINVAL))?;
140
141 if Arc::ptr_eq(new_root_mount, current_root_mount)
142 || Arc::ptr_eq(put_old_mount, current_root_mount)
143 {
144 return error!(EBUSY);
145 }
146
147 let current_root_mount = current_root.mount_if_root()?;
148 let new_root_mount = new_root.mount_if_root()?;
149
150 if !new_root.is_descendant_of(current_root) {
151 return error!(EINVAL);
152 }
153 if !put_old.is_descendant_of(new_root) {
154 return error!(EINVAL);
155 }
156
157 let kernel = self.kernel();
158 let mounts_guard = kernel.mounts_lock();
159
160 let new_root_parent = mounts_guard.retain(
165 new_root_mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount"),
166 );
167 mounts_guard.retain(&new_root_mountpoint.entry);
168
169 if new_root_mount.peer_group().is_some() || new_root_parent.peer_group().is_some() {
170 return error!(EINVAL);
171 }
172
173 if put_old_mount.peer_group().is_some() {
174 return error!(EINVAL);
175 }
176
177 if current_root_mount.peer_group().is_some() {
178 return error!(EINVAL);
179 }
180
181 let current_root_parent = mounts_guard.retain(
182 current_root_mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount"),
183 );
184 mounts_guard.retain(¤t_root_mountpoint.entry);
185 if current_root_parent.peer_group().is_some() {
186 return error!(EINVAL);
187 }
188
189 mounts_guard.retain(current_root_mount);
192 mounts_guard.retain(new_root_mount);
193 mounts_guard.retain(put_old_mount);
194 mounts_guard.retain(&put_old.entry);
195
196 new_root_parent
198 .remove_submount_internal(&mounts_guard, &new_root_mountpoint.mount_hash_key())?;
199 new_root_mount.relations.set_mountpoint(&mounts_guard, None);
200
201 current_root_parent
203 .remove_submount_internal(&mounts_guard, ¤t_root_mountpoint.mount_hash_key())?;
204 current_root_mount.relations.set_mountpoint(&mounts_guard, None);
205 current_root_parent.create_submount(
206 &mounts_guard,
207 ¤t_root_mountpoint.entry,
208 WhatSubmount::Existing(Arc::clone(new_root_mount)),
209 )?;
210
211 put_old_mount.create_submount(
213 &mounts_guard,
214 &put_old.entry,
215 WhatSubmount::Existing(Arc::clone(current_root_mount)),
216 )?;
217
218 Ok(())
219 }
220}
221
222impl FsNodeOps for Arc<Namespace> {
223 fs_node_impl_not_dir!();
224
225 fn create_file_ops(
226 &self,
227 _node: &FsNode,
228 _current_task: &CurrentTask,
229 _flags: OpenFlags,
230 ) -> Result<Box<dyn FileOps>, Errno> {
231 Ok(Box::new(MountNamespaceFile(self.clone())))
232 }
233}
234
235pub struct MountNamespaceFile(pub Arc<Namespace>);
236
237impl FileOps for MountNamespaceFile {
238 fileops_impl_nonseekable!();
239 fileops_impl_dataless!();
240 fileops_impl_noop_sync!();
241}
242
243type MountClientMarker = Arc<()>;
248
249pub struct Mount {
258 root: DirEntryHandle,
259 fs: FileSystemHandle,
260
261 flags: AtomicMountpointFlags,
263
264 flags_lock: LockDepMutex<(), NamespaceFlagsLock>,
266
267 id: u64,
269
270 active_client_counter: MountClientMarker,
272
273 relations: MountRelations,
280 }
287
288type MountHandle = Arc<Mount>;
289
290#[derive(Clone, Debug)]
292pub struct MountInfo {
293 handle: Option<MountHandle>,
294}
295
296impl MountInfo {
297 pub fn detached() -> Self {
300 None.into()
301 }
302
303 pub fn flags(&self) -> MountFlags {
305 if let Some(handle) = &self.handle {
306 handle.flags()
307 } else {
308 MountFlags::NOATIME
310 }
311 }
312
313 pub fn check_readonly_filesystem(&self) -> Result<(), Errno> {
315 if self.flags().contains(MountFlags::RDONLY) {
316 return error!(EROFS);
317 }
318 Ok(())
319 }
320
321 pub fn check_noexec_filesystem(&self) -> Result<(), Errno> {
323 if self.flags().contains(MountFlags::NOEXEC) {
324 return error!(EACCES);
325 }
326 Ok(())
327 }
328}
329
330impl Deref for MountInfo {
331 type Target = Option<MountHandle>;
332
333 fn deref(&self) -> &Self::Target {
334 &self.handle
335 }
336}
337
338impl DerefMut for MountInfo {
339 fn deref_mut(&mut self) -> &mut Self::Target {
340 &mut self.handle
341 }
342}
343
344impl std::cmp::PartialEq for MountInfo {
345 fn eq(&self, other: &Self) -> bool {
346 self.handle.as_ref().map(Arc::as_ptr) == other.handle.as_ref().map(Arc::as_ptr)
347 }
348}
349
350impl std::cmp::Eq for MountInfo {}
351
352impl Into<MountInfo> for Option<MountHandle> {
353 fn into(self) -> MountInfo {
354 MountInfo { handle: self }
355 }
356}
357
358#[derive(Default)]
359struct MountRelations {
360 mountpoint: RcuBox<Option<(Weak<Mount>, Weak<DirEntry>)>>,
362 submounts: Mutex<HashMap<PtrKey<DirEntry>, Submount>>,
364 submount_lookup: RcuRawHashMap<WeakKey<DirEntry>, Weak<Mount>>,
366 peer_group: RcuArc<PeerGroup>,
368 upstream: RcuBox<Option<(Weak<PeerGroup>, PtrKey<Mount>)>>,
370}
371
372impl MountRelations {
373 fn get_submount(
374 &self,
375 scope: &starnix_rcu::RcuReadScope,
376 key: &PtrKey<DirEntry>,
377 ) -> Option<MountHandle> {
378 self.submount_lookup.get(scope, key).and_then(|weak| weak.upgrade())
379 }
380
381 fn insert_submount(
382 &self,
383 _guard: &MountsWriteToken,
384 key: WeakKey<DirEntry>,
385 value: Weak<Mount>,
386 submount: Submount,
387 ) -> Option<Submount> {
388 let ptr_key = PtrKey::from(key.0.as_ptr());
389 let old_submount = self.submounts.lock().insert(ptr_key, submount);
390 let scope = starnix_rcu::RcuReadScope::new();
391 unsafe { self.submount_lookup.insert(&scope, key, value) };
393 old_submount
394 }
395
396 fn remove_submount(
397 &self,
398 guard: &MountsWriteToken,
399 key: &PtrKey<DirEntry>,
400 ) -> Result<(), Errno> {
401 let _ = unsafe { self.submount_lookup.remove(key) };
403 let submount = self.submounts.lock().remove(key);
404 let submount = guard.defer_drop(submount);
405 if submount.is_some() { Ok(()) } else { error!(EINVAL) }
406 }
407
408 fn iter_submounts<'a>(
409 &'a self,
410 scope: &'a starnix_rcu::RcuReadScope,
411 ) -> impl Iterator<Item = (&'a WeakKey<DirEntry>, &'a Weak<Mount>)> {
412 let mut cursor = self.submount_lookup.cursor(scope);
413 std::iter::from_fn(move || {
414 let current = cursor.current();
415 if current.is_some() {
416 cursor.advance();
417 }
418 current
419 })
420 }
421
422 fn submounts_len(&self) -> usize {
423 self.submount_lookup.len()
424 }
425
426 fn set_mountpoint(
427 &self,
428 _guard: &MountsWriteToken,
429 mountpoint: Option<(Weak<Mount>, Weak<DirEntry>)>,
430 ) {
431 self.mountpoint.update(mountpoint);
432 }
433
434 fn mountpoint<'a>(
435 &'a self,
436 scope: &'a starnix_rcu::RcuReadScope,
437 ) -> Option<&'a (Weak<Mount>, Weak<DirEntry>)> {
438 self.mountpoint.as_ref(scope).as_ref()
439 }
440
441 fn take_peer_group(&self, _guard: &MountsWriteToken) -> Option<Arc<PeerGroup>> {
442 let peer_group = self.peer_group.upgrade();
443 self.peer_group.update(None);
444 peer_group
445 }
446
447 fn take_upstream(&self, _guard: &MountsWriteToken) -> Option<(Weak<PeerGroup>, PtrKey<Mount>)> {
448 let upstream = self.upstream.cloned();
449 self.upstream.update(None);
450 upstream
451 }
452}
453
454#[derive(Default)]
458struct PeerGroup {
459 id: u64,
460 mounts: RcuRawHashMap<WeakKey<Mount>, ()>,
461 downstream: RcuRawHashMap<WeakKey<Mount>, ()>,
462}
463
464pub enum WhatToMount {
465 Fs(FileSystemHandle),
466 Bind(NamespaceNode),
467}
468
469enum WhatSubmount {
470 New(WhatToMount, MountpointFlags),
471 Existing(MountHandle),
472}
473
474impl Mount {
475 pub fn new(
476 mounts_guard: &MountsWriteToken,
477 what: WhatToMount,
478 mut flags: MountpointFlags,
479 ) -> Result<MountHandle, Errno> {
480 let what = mounts_guard.defer_drop(what);
481 match &*what {
482 WhatToMount::Fs(fs) => {
483 flags.default_atime_from(MountpointFlags::RELATIME);
485 Ok(Self::new_with_root(fs.root().clone(), flags))
486 }
487 WhatToMount::Bind(node) => {
488 let mount = node.mount.as_ref().ok_or_else(|| errno!(ENOENT))?;
491 Ok(mount.clone_mount(mounts_guard, &node.entry, flags.into()))
492 }
493 }
494 }
495
496 fn new_with_root(root: DirEntryHandle, flags: MountpointFlags) -> MountHandle {
497 let fs = root.node.fs();
498 let kernel = fs.kernel.upgrade().expect("can't create mount without kernel");
499 Arc::new(Self {
500 id: kernel.get_next_mount_id(),
501 flags: (flags & MountpointFlags::STORED_ON_MOUNT).into(),
502 flags_lock: Default::default(),
503 root,
504 active_client_counter: Default::default(),
505 fs,
506 relations: Default::default(),
507 })
508 }
509
510 pub fn root(self: &MountHandle) -> NamespaceNode {
512 NamespaceNode::new(Arc::clone(self), Arc::clone(&self.root))
513 }
514
515 fn kernel(&self) -> Arc<Kernel> {
516 self.fs.kernel.upgrade().expect("No Kernel")
517 }
518
519 fn create_submount(
521 self: &MountHandle,
522 mounts_guard: &MountsWriteToken,
523 dir: &DirEntryHandle,
524 what: WhatSubmount,
525 ) -> Result<(), Errno> {
526 let peers = self.peer_group().map(|g| g.copy_propagation_targets()).unwrap_or_default();
529 let peers = mounts_guard.defer_drop(peers);
530
531 let mount = match what {
536 WhatSubmount::Existing(mount) => mount,
537 WhatSubmount::New(what, flags) => Mount::new(mounts_guard, what, flags)?,
538 };
539
540 if self.is_shared() {
541 mount.make_shared(mounts_guard);
542 }
543
544 for peer in &*peers {
545 if Arc::ptr_eq(self, peer) {
546 continue;
547 }
548 let clone = mount.clone_mount_recursive(mounts_guard);
549 peer.add_submount_internal(mounts_guard, dir, clone);
550 }
551
552 self.add_submount_internal(mounts_guard, dir, mount);
553 Ok(())
554 }
555
556 fn remove_submount(
557 self: &MountHandle,
558 mounts_guard: &MountsWriteToken,
559 mount_hash_key: &PtrKey<DirEntry>,
560 ) -> Result<(), Errno> {
561 let peers = self.peer_group().map(|g| g.copy_propagation_targets()).unwrap_or_default();
563 let peers = mounts_guard.defer_drop(peers);
564
565 for peer in &*peers {
566 if Arc::ptr_eq(self, peer) {
567 continue;
568 }
569 let submount = {
573 let scope = RcuReadScope::new();
574 peer.relations.get_submount(&scope, mount_hash_key)
575 };
576 if let Some(submount) = submount {
577 let submount = mounts_guard.defer_drop(submount);
578 if submount.relations.submounts_len() != 0 {
579 continue;
580 }
581 }
582 let _ = peer.remove_submount_internal(mounts_guard, mount_hash_key);
583 }
584
585 self.remove_submount_internal(mounts_guard, mount_hash_key)
586 }
587
588 pub fn move_mount(
589 source_mount: &MountHandle,
590 target_mount: &MountHandle,
591 target_dir: &DirEntryHandle,
592 ) -> Result<(), Errno> {
593 let kernel = target_mount.kernel();
594 let mounts_guard = kernel.mounts_lock();
595
596 let source_mountpoint = source_mount.mountpoint().ok_or_else(|| errno!(EIO))?;
597 let source_mountpoint = mounts_guard.defer_drop(source_mountpoint);
598 let source_parent = mounts_guard.retain(
599 source_mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount"),
600 );
601
602 {
604 if source_parent.peer_group().is_some() {
605 return error!(EINVAL);
609 }
610 source_parent
611 .remove_submount_internal(&mounts_guard, &source_mountpoint.mount_hash_key())?;
612 source_mount.relations.set_mountpoint(&mounts_guard, None);
613 }
614
615 target_mount.create_submount(
616 &mounts_guard,
617 target_dir,
618 WhatSubmount::Existing(Arc::clone(source_mount)),
619 )?;
620 Ok(())
621 }
622
623 fn clone_mount(
626 self: &MountHandle,
627 mounts_guard: &MountsWriteToken,
628 new_root: &DirEntryHandle,
629 flags: MountFlags,
630 ) -> MountHandle {
631 assert!(new_root.is_descendant_of(&self.root));
632 let clone = Self::new_with_root(Arc::clone(new_root), self.mount_flags());
635
636 if flags.contains(MountFlags::REC) {
637 let submounts: Vec<_> = {
638 let scope = RcuReadScope::new();
639 self.relations
640 .iter_submounts(&scope)
641 .filter_map(|(dir, submount)| Some((dir.0.upgrade()?, submount.upgrade()?)))
642 .collect()
643 };
644 let submounts = mounts_guard.defer_drop(submounts);
645 for (dir, submount) in &*submounts {
646 let submount = submount.clone_mount_recursive(mounts_guard);
647 clone.add_submount_internal(mounts_guard, dir, submount);
648 }
649 }
650
651 let peer_group = self.peer_group();
653 if let Some(peer_group) = peer_group {
654 let peer_group = mounts_guard.defer_drop(peer_group);
655 clone.set_peer_group(mounts_guard, Arc::clone(&peer_group));
656 }
657
658 clone
659 }
660
661 fn clone_mount_recursive(self: &MountHandle, mounts_guard: &MountsWriteToken) -> MountHandle {
664 self.clone_mount(mounts_guard, &self.root, MountFlags::REC)
665 }
666
667 pub fn change_propagation(
668 self: &MountHandle,
669 mounts_guard: &MountsWriteToken,
670 flag: MountFlags,
671 recursive: bool,
672 ) {
673 match flag {
674 MountFlags::SHARED => self.make_shared(mounts_guard),
675 MountFlags::PRIVATE => self.make_private(mounts_guard),
676 MountFlags::DOWNSTREAM => self.make_downstream(mounts_guard),
677 _ => {
678 log_warn!("mount propagation {:?}", flag);
679 }
680 }
681
682 if recursive {
683 let submounts: Vec<_> = {
684 let scope = starnix_rcu::RcuReadScope::new();
685 self.relations
686 .iter_submounts(&scope)
687 .filter_map(|(_, submount)| submount.upgrade())
688 .collect()
689 };
690 let submounts = mounts_guard.defer_drop(submounts);
691 for submount in &*submounts {
692 submount.change_propagation(mounts_guard, flag, recursive);
693 }
694 }
695 }
696
697 fn flags(&self) -> MountFlags {
700 MountFlags::from(self.mount_flags()) | self.fs_flags().into()
701 }
702
703 fn mount_flags(&self) -> MountpointFlags {
705 self.flags.load(Ordering::Relaxed)
706 }
707
708 fn fs_flags(&self) -> FileSystemFlags {
710 self.fs.options.flags.load(Ordering::Relaxed)
711 }
712
713 pub fn update_flags(self: &MountHandle, mut flags: MountpointFlags) {
716 let _lock = self.flags_lock.lock();
717 flags.default_atime_from(self.flags.load(Ordering::Relaxed));
722 flags &= MountpointFlags::STORED_ON_MOUNT;
723 self.flags.store(flags, Ordering::Relaxed);
724 }
725
726 fn active_clients(&self) -> usize {
730 Arc::strong_count(&self.active_client_counter) - 1
732 }
733
734 pub fn unmount(
735 &self,
736 mounts_guard: &MountsWriteToken,
737 flags: UnmountFlags,
738 ) -> Result<(), Errno> {
739 if !flags.contains(UnmountFlags::DETACH) {
740 if self.active_clients() > 0 || self.relations.submounts_len() != 0 {
741 return error!(EBUSY);
742 }
743 }
744
745 let mountpoint = self.mountpoint().ok_or_else(|| errno!(EINVAL))?;
746 let mountpoint = mounts_guard.defer_drop(mountpoint);
747 let parent_mount = mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount");
748 parent_mount.remove_submount(mounts_guard, &mountpoint.mount_hash_key())
749 }
750
751 pub fn security_state(&self) -> &security::FileSystemState {
753 &self.fs.security_state
754 }
755
756 pub fn fs_name(&self) -> &'static FsStr {
758 self.fs.name()
759 }
760
761 pub fn reconfigure_fs(
763 &self,
764 current_task: &CurrentTask,
765 flags: FileSystemFlags,
766 ) -> Result<(), Errno> {
767 self.fs.update_flags(current_task, flags)
768 }
769
770 pub fn has_submount(&self, dir_entry: &DirEntryHandle) -> bool {
772 let scope = RcuReadScope::new();
773 self.relations.get_submount(&scope, &PtrKey::from(dir_entry)).is_some()
774 }
775
776 pub fn mountpoint(&self) -> Option<NamespaceNode> {
778 let scope = RcuReadScope::new();
779 let (mount, entry) = self.relations.mountpoint(&scope)?;
780 Some(NamespaceNode::new(mount.upgrade()?, entry.upgrade()?))
781 }
782
783 pub fn add_submount_internal(
785 self: &MountHandle,
786 guard: &MountsWriteToken,
787 dir: &DirEntryHandle,
788 mount: MountHandle,
789 ) {
790 let mount = guard.defer_drop(mount);
791 if !dir.is_descendant_of(&self.root) {
792 return;
793 }
794
795 let submount = mount.kernel().mounts.register_mount(dir, Arc::clone(&mount));
796
797 let old_mountpoint = {
798 let scope = RcuReadScope::new();
799 mount.relations.mountpoint(&scope).map(|x| x.clone())
800 };
801 mount.relations.set_mountpoint(guard, Some((Arc::downgrade(self), Arc::downgrade(dir))));
802 assert!(old_mountpoint.is_none(), "add_submount can only take a newly created mount");
803
804 let old_mount = self.relations.insert_submount(
805 guard,
806 WeakKey::from(dir),
807 Arc::downgrade(&mount),
808 submount,
809 );
810 let old_mount = guard.defer_drop(old_mount);
811
812 if let Some(old_mount) = &*old_mount {
813 old_mount
814 .mount
815 .relations
816 .set_mountpoint(guard, Some((Arc::downgrade(&mount), Arc::downgrade(&mount.root))));
817 let new_old_submount =
818 mount.kernel().mounts.register_mount(&mount.root, old_mount.mount.clone());
819 let replaced = mount.relations.insert_submount(
820 guard,
821 WeakKey::from(&mount.root),
822 Arc::downgrade(&old_mount.mount),
823 new_old_submount,
824 );
825 if let Some(replaced) = replaced {
826 guard.defer_drop(replaced);
827 }
828 }
829 }
830
831 pub fn remove_submount_internal(
832 self: &MountHandle,
833 guard: &MountsWriteToken,
834 mount_hash_key: &PtrKey<DirEntry>,
835 ) -> Result<(), Errno> {
836 self.relations.remove_submount(guard, mount_hash_key)
837 }
838
839 fn peer_group(&self) -> Option<Arc<PeerGroup>> {
841 self.relations.peer_group.upgrade()
842 }
843
844 fn unregister_from_peer_group_and_upstream(
847 guard: &MountsWriteToken,
848 peer_group: Option<Arc<PeerGroup>>,
849 upstream: Option<(Weak<PeerGroup>, PtrKey<Mount>)>,
850 mount_ptr: PtrKey<Mount>,
851 ) {
852 let peer_group = guard.defer_drop(peer_group);
853 let upstream_group = match upstream {
854 Some((weak_group, mount)) => {
855 if let Some(group) = weak_group.upgrade() {
856 group.remove_downstream(guard, mount);
857 Some(group)
858 } else {
859 None
860 }
861 }
862 None => None,
863 };
864 let upstream_group = guard.defer_drop(upstream_group);
865
866 if let Some(group) = &*peer_group {
867 group.remove(guard, mount_ptr);
868
869 if let Some(upstream_group) = &*upstream_group {
870 let next_mount = {
871 let scope = RcuReadScope::new();
872 group.mounts.keys(&scope).next().and_then(|w| w.0.upgrade())
873 };
874 if let Some(next_mount) = next_mount {
875 let next_mount = guard.defer_drop(next_mount);
876 next_mount.set_upstream(guard, upstream_group);
877 }
878 }
879 }
880 }
881
882 fn take_from_peer_group(&self, guard: &MountsWriteToken) -> Option<Arc<PeerGroup>> {
884 let peer_group = self.relations.take_peer_group(guard);
885 if peer_group.is_none() {
886 return None;
887 }
888 let upstream = self.relations.take_upstream(guard);
889 let return_group = peer_group.clone();
890 Mount::unregister_from_peer_group_and_upstream(
891 guard,
892 peer_group,
893 upstream,
894 PtrKey::from(self),
895 );
896 return_group
897 }
898
899 fn upstream(&self) -> Option<Arc<PeerGroup>> {
900 let scope = RcuReadScope::new();
901 let (group, _) = self.relations.upstream.as_ref(&scope).as_ref()?;
902 group.upgrade()
903 }
904
905 fn remove_from_upstream(&self, guard: &MountsWriteToken) {
906 let upstream = self.relations.take_upstream(guard);
907 if let Some((weak_group, mount)) = upstream {
908 if let Some(group) = weak_group.upgrade() {
909 group.remove_downstream(guard, mount);
910 guard.defer_drop(group);
911 }
912 }
913 }
914
915 fn set_peer_group(self: &Arc<Mount>, guard: &MountsWriteToken, group: Arc<PeerGroup>) {
917 if let Some(prev) = self.take_from_peer_group(guard) {
918 guard.defer_drop(prev);
919 }
920 group.add(guard, self);
921 self.relations.peer_group.update(Some(group));
922 }
923
924 fn set_upstream(self: &Arc<Mount>, guard: &MountsWriteToken, group: &Arc<PeerGroup>) {
925 self.remove_from_upstream(guard);
926 group.add_downstream(guard, self);
927 self.relations.upstream.update(Some((Arc::downgrade(group), Arc::as_ptr(self).into())));
928 }
929
930 pub fn is_shared(&self) -> bool {
932 self.relations.peer_group.is_some()
933 }
934
935 fn make_shared(self: &Arc<Mount>, guard: &MountsWriteToken) {
937 if self.is_shared() {
938 return;
939 }
940 let kernel = self.kernel();
941 self.set_peer_group(guard, PeerGroup::new(kernel.get_next_peer_group_id()))
942 }
943
944 fn make_private(&self, guard: &MountsWriteToken) {
946 let peer_group = self.relations.take_peer_group(guard);
947 let upstream = self.relations.take_upstream(guard);
948 Mount::unregister_from_peer_group_and_upstream(
949 guard,
950 peer_group,
951 upstream,
952 PtrKey::from(self),
953 );
954 }
955
956 fn make_downstream(self: &Arc<Mount>, guard: &MountsWriteToken) {
959 if let Some(peer_group) = self.take_from_peer_group(guard) {
960 let peer_group = guard.defer_drop(peer_group);
961 self.set_upstream(guard, &peer_group);
962 }
963 }
964}
965
966impl PeerGroup {
967 fn new(id: u64) -> Arc<Self> {
968 Arc::new(Self {
969 id,
970 mounts: RcuRawHashMap::default(),
971 downstream: RcuRawHashMap::default(),
972 })
973 }
974
975 fn add(&self, _guard: &MountsWriteToken, mount: &Arc<Mount>) {
976 unsafe { self.mounts.insert(&starnix_rcu::RcuReadScope::new(), WeakKey::from(mount), ()) };
978 }
979
980 fn remove(&self, _guard: &MountsWriteToken, mount: PtrKey<Mount>) {
981 unsafe { self.mounts.remove(&mount) };
983 }
984
985 fn add_downstream(&self, _guard: &MountsWriteToken, mount: &Arc<Mount>) {
986 unsafe {
988 self.downstream.insert(&starnix_rcu::RcuReadScope::new(), WeakKey::from(mount), ())
989 };
990 }
991
992 fn remove_downstream(&self, _guard: &MountsWriteToken, mount: PtrKey<Mount>) {
993 unsafe { self.downstream.remove(&mount) };
995 }
996
997 fn copy_propagation_targets(&self) -> Vec<MountHandle> {
998 let mut buf = vec![];
999 self.collect_propagation_targets(&mut buf);
1000 buf
1001 }
1002
1003 fn collect_propagation_targets(&self, buf: &mut Vec<MountHandle>) {
1004 let downstream_mounts: Vec<_> = {
1005 let scope = RcuReadScope::new();
1006 buf.extend(self.mounts.keys(&scope).filter_map(|m| m.0.upgrade()));
1007 self.downstream.keys(&scope).filter_map(|m| m.0.upgrade()).collect()
1008 };
1009 for mount in downstream_mounts {
1010 let peer_group = mount.peer_group();
1011 match peer_group {
1012 Some(group) => group.collect_propagation_targets(buf),
1013 None => buf.push(mount),
1014 }
1015 }
1016 }
1017}
1018
1019impl Kernel {
1020 pub fn get_next_mount_id(&self) -> u64 {
1021 self.next_mount_id.next()
1022 }
1023
1024 pub fn get_next_peer_group_id(&self) -> u64 {
1025 self.next_peer_group_id.next()
1026 }
1027
1028 pub fn get_next_namespace_id(&self) -> u64 {
1029 self.next_namespace_id.next()
1030 }
1031}
1032
1033impl CurrentTask {
1034 pub fn create_filesystem(
1035 &self,
1036 fs_type: &FsStr,
1037 options: FileSystemOptions,
1038 ) -> Result<FileSystemHandle, Errno> {
1039 self.kernel()
1046 .expando
1047 .get::<FsRegistry>()
1048 .create(self, fs_type, options)
1049 .ok_or_else(|| errno!(ENODEV, fs_type))?
1050 }
1051}
1052
1053struct ProcMountsFileSource {
1054 tid: Pid,
1055}
1056
1057impl DynamicFileSource for ProcMountsFileSource {
1058 fn generate(
1059 &self,
1060 _current_task: &CurrentTask,
1061 sink: &mut DynamicFileBuf,
1062 ) -> Result<(), Errno> {
1063 let task = self.tid.get_task()?;
1068 let task_fs = task.running_state()?.fs();
1069 let root = task_fs.root();
1070 let ns = task_fs.namespace();
1071 for_each_mount(&ns.root_mount, &mut |mount| {
1072 let mountpoint = mount.mountpoint().unwrap_or_else(|| mount.root());
1073 if !mountpoint.is_descendant_of(&root) {
1074 return Ok(());
1075 }
1076 write!(
1077 sink,
1078 "{} {} {} {}{}",
1079 mount.fs.options.source_for_display(),
1080 mountpoint.path(&task_fs),
1081 mount.fs.name(),
1082 mount.flags(),
1085 security::sb_show_options(&task.kernel(), &mount.fs)?,
1086 )?;
1087 writeln!(sink, " 0 0")?;
1088 Ok(())
1089 })?;
1090 Ok(())
1091 }
1092}
1093
1094pub struct ProcMountsFile {
1095 dynamic_file: DynamicFile<ProcMountsFileSource>,
1096}
1097
1098impl ProcMountsFile {
1099 pub fn new_node(tid: Pid) -> impl FsNodeOps {
1100 SimpleFileNode::new(move |_| {
1101 Ok(Self { dynamic_file: DynamicFile::new(ProcMountsFileSource { tid: tid.clone() }) })
1102 })
1103 }
1104}
1105
1106impl FileOps for ProcMountsFile {
1107 fileops_impl_delegate_read_write_and_seek!(self, self.dynamic_file);
1108 fileops_impl_noop_sync!();
1109
1110 fn wait_async(
1111 &self,
1112 _file: &FileObject,
1113 _current_task: &CurrentTask,
1114 waiter: &Waiter,
1115 _events: FdEvents,
1116 _handler: EventHandler,
1117 ) -> Option<WaitCanceler> {
1118 Some(waiter.fake_wait())
1121 }
1122
1123 fn query_events(
1124 &self,
1125 _file: &FileObject,
1126 _current_task: &CurrentTask,
1127 ) -> Result<FdEvents, Errno> {
1128 Ok(FdEvents::empty())
1129 }
1130}
1131
1132#[derive(Clone)]
1133pub struct ProcMountinfoFile {
1134 tid: Pid,
1135}
1136impl ProcMountinfoFile {
1137 pub fn new_node(tid: Pid) -> impl FsNodeOps {
1138 DynamicFile::new_node(Self { tid })
1139 }
1140}
1141impl DynamicFileSource for ProcMountinfoFile {
1142 fn generate(
1143 &self,
1144 _current_task: &CurrentTask,
1145 sink: &mut DynamicFileBuf,
1146 ) -> Result<(), Errno> {
1147 fn path_from_fs_root(dir: &DirEntryHandle) -> FsString {
1149 let mut path = PathBuilder::new();
1150 if dir.is_dead() {
1151 path.prepend_element("/deleted".into());
1153 }
1154 let scope = RcuReadScope::new();
1155 let mut current = dir.clone();
1156 while let Some(parent) = current.parent() {
1157 path.prepend_element(current.local_name(&scope));
1158 current = parent;
1159 }
1160 path.build_absolute()
1161 }
1162
1163 let task = self.tid.get_task()?;
1168 let task_fs = task.running_state()?.fs();
1169 let root = task_fs.root();
1170 let ns = task_fs.namespace();
1171 for_each_mount(&ns.root_mount, &mut |mount| {
1172 let mountpoint = mount.mountpoint().unwrap_or_else(|| mount.root());
1173 if !mountpoint.is_descendant_of(&root) {
1174 return Ok(());
1175 }
1176 let parent = mountpoint.mount.as_ref().unwrap();
1178 write!(
1179 sink,
1180 "{} {} {} {} {} {}",
1181 mount.id,
1182 parent.id,
1183 mount.root.node.fs().dev_id,
1184 path_from_fs_root(&mount.root),
1185 mountpoint.path(&task_fs),
1186 mount.mount_flags(),
1187 )?;
1188 if let Some(peer_group) = mount.peer_group() {
1189 write!(sink, " shared:{}", peer_group.id)?;
1190 }
1191 if let Some(upstream) = mount.upstream() {
1192 write!(sink, " master:{}", upstream.id)?;
1193 }
1194 writeln!(
1195 sink,
1196 " - {} {} {}{}",
1197 mount.fs.name(),
1198 mount.fs.options.source_for_display(),
1199 mount.fs_flags(),
1200 security::sb_show_options(&task.kernel(), &mount.fs)?
1202 )?;
1203 Ok(())
1204 })?;
1205 Ok(())
1206 }
1207}
1208
1209fn for_each_mount<E>(
1210 mount: &MountHandle,
1211 callback: &mut impl FnMut(&MountHandle) -> Result<(), E>,
1212) -> Result<(), E> {
1213 callback(mount)?;
1214 for (_, s) in mount.relations.iter_submounts(&RcuReadScope::new()) {
1215 if let Some(submount) = s.upgrade() {
1216 for_each_mount(&submount, callback)?;
1217 }
1218 }
1219 Ok(())
1220}
1221
1222#[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
1224pub enum SymlinkMode {
1225 #[default]
1227 Follow,
1228
1229 NoFollow,
1231}
1232
1233#[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
1235pub enum DirectoryMode {
1236 #[default]
1238 AllowAny,
1239
1240 MustBeDirectory,
1242}
1243
1244pub const MAX_SYMLINK_FOLLOWS: u8 = 40;
1246
1247pub struct LookupContext {
1252 pub symlink_mode: SymlinkMode,
1257
1258 pub remaining_follows: u8,
1262
1263 pub directory_mode: DirectoryMode,
1269
1270 pub resolve_flags: ResolveFlags,
1272
1273 pub resolve_base: ResolveBase,
1276}
1277
1278#[derive(Clone, Eq, PartialEq)]
1281pub enum ResolveBase {
1282 None,
1283
1284 Beneath(NamespaceNode),
1286
1287 InRoot(NamespaceNode),
1289}
1290
1291impl LookupContext {
1292 pub fn new(symlink_mode: SymlinkMode) -> LookupContext {
1293 LookupContext {
1294 symlink_mode,
1295 remaining_follows: MAX_SYMLINK_FOLLOWS,
1296 directory_mode: DirectoryMode::default(),
1297 resolve_flags: ResolveFlags::empty(),
1298 resolve_base: ResolveBase::None,
1299 }
1300 }
1301
1302 pub fn with(&self, symlink_mode: SymlinkMode, directory_mode: DirectoryMode) -> LookupContext {
1303 LookupContext {
1304 symlink_mode,
1305 directory_mode,
1306 resolve_base: self.resolve_base.clone(),
1307 ..*self
1308 }
1309 }
1310
1311 pub fn update_for_path(&mut self, path: &FsStr) {
1312 if path.last() == Some(&b'/') {
1313 self.directory_mode = DirectoryMode::MustBeDirectory;
1316 self.symlink_mode = SymlinkMode::Follow;
1319 }
1320 }
1321}
1322
1323impl Default for LookupContext {
1324 fn default() -> Self {
1325 LookupContext::new(SymlinkMode::Follow)
1326 }
1327}
1328
1329pub enum PathWithReachability {
1331 Reachable(FsString),
1333
1334 Unreachable(FsString),
1336}
1337
1338impl PathWithReachability {
1339 pub fn into_path(self) -> FsString {
1340 match self {
1341 PathWithReachability::Reachable(path) => path,
1342 PathWithReachability::Unreachable(path) => path,
1343 }
1344 }
1345}
1346
1347#[derive(Clone)]
1355pub struct NamespaceNode {
1356 pub mount: MountInfo,
1361
1362 pub entry: DirEntryHandle,
1364}
1365
1366impl NamespaceNode {
1367 pub fn new(mount: MountHandle, entry: DirEntryHandle) -> Self {
1368 Self { mount: Some(mount).into(), entry }
1369 }
1370
1371 pub fn new_anonymous(entry: DirEntryHandle) -> Self {
1373 Self { mount: None.into(), entry }
1374 }
1375
1376 pub fn new_anonymous_unrooted(current_task: &CurrentTask, node: FsNodeHandle) -> Self {
1379 let dir_entry = DirEntry::new_unrooted(node);
1380 let _ = security::fs_node_init_with_dentry_no_xattr(current_task, &dir_entry);
1381 Self::new_anonymous(dir_entry)
1382 }
1383
1384 pub fn open(
1390 &self,
1391 current_task: &CurrentTask,
1392 open_check: impl Into<OpenAccessCheck>,
1393 ) -> Result<FileHandle, Errno> {
1394 let open_check = open_check.into();
1395 let ops = self.entry.node.open(current_task, self, open_check)?;
1396 FileObject::new(current_task, ops, self.clone(), open_check.open_flags())
1397 }
1398
1399 pub fn open_create_node(
1405 &self,
1406 current_task: &CurrentTask,
1407 name: &FsStr,
1408 mode: FileMode,
1409 dev: DeviceId,
1410 flags: OpenFlags,
1411 ) -> Result<NamespaceNode, Errno> {
1412 let owner = current_task.current_fscred();
1413 let mode = current_task.fs().apply_umask(mode);
1414 let create_fn = |dir: &FsNodeHandle, mount: &MountInfo, name: &_| {
1415 dir.create_node(current_task, mount, name, mode, dev, owner)
1416 };
1417 let entry = if flags.contains(OpenFlags::EXCL) {
1418 self.entry.create_entry(current_task, &self.mount, name, create_fn)
1419 } else {
1420 self.entry.get_or_create_entry(current_task, &self.mount, name, create_fn)
1421 }?;
1422 Ok(self.with_new_entry(entry))
1423 }
1424
1425 pub fn into_active(self) -> ActiveNamespaceNode {
1426 ActiveNamespaceNode::new(self)
1427 }
1428
1429 pub fn create_node(
1435 &self,
1436 current_task: &CurrentTask,
1437 name: &FsStr,
1438 mode: FileMode,
1439 dev: DeviceId,
1440 ) -> Result<NamespaceNode, Errno> {
1441 let owner = current_task.current_fscred();
1442 let mode = current_task.fs().apply_umask(mode);
1443 let entry =
1444 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1445 dir.create_node(current_task, mount, name, mode, dev, owner)
1446 })?;
1447 Ok(self.with_new_entry(entry))
1448 }
1449
1450 pub fn create_symlink(
1454 &self,
1455 current_task: &CurrentTask,
1456 name: &FsStr,
1457 target: &FsStr,
1458 ) -> Result<NamespaceNode, Errno> {
1459 let owner = current_task.current_fscred();
1460 let entry =
1461 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1462 dir.create_symlink(current_task, mount, name, target, owner)
1463 })?;
1464 Ok(self.with_new_entry(entry))
1465 }
1466
1467 pub fn create_tmpfile(
1473 &self,
1474 current_task: &CurrentTask,
1475 mode: FileMode,
1476 flags: OpenFlags,
1477 ) -> Result<NamespaceNode, Errno> {
1478 let owner = current_task.current_fscred();
1479 let mode = current_task.fs().apply_umask(mode);
1480 Ok(self.with_new_entry(self.entry.create_tmpfile(
1481 current_task,
1482 &self.mount,
1483 mode,
1484 owner,
1485 flags,
1486 )?))
1487 }
1488
1489 pub fn link(
1490 &self,
1491 current_task: &CurrentTask,
1492 name: &FsStr,
1493 child: &FsNodeHandle,
1494 ) -> Result<NamespaceNode, Errno> {
1495 let dir_entry =
1496 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1497 dir.link(current_task, mount, name, child)
1498 })?;
1499 Ok(self.with_new_entry(dir_entry))
1500 }
1501
1502 pub fn bind_socket(
1503 &self,
1504 current_task: &CurrentTask,
1505 name: &FsStr,
1506 socket: SocketHandle,
1507 socket_address: SocketAddress,
1508 mode: FileMode,
1509 ) -> Result<NamespaceNode, Errno> {
1510 let dir_entry =
1511 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1512 let node = dir.create_node(
1513 current_task,
1514 mount,
1515 name,
1516 mode,
1517 DeviceId::NONE,
1518 current_task.current_fscred(),
1519 )?;
1520 if let Some(unix_socket) = socket.downcast_socket::<UnixSocket>() {
1521 unix_socket.bind_socket_to_node(&socket, socket_address, &node)?;
1522 } else {
1523 return error!(ENOTSUP);
1524 }
1525 Ok(node)
1526 })?;
1527 Ok(self.with_new_entry(dir_entry))
1528 }
1529
1530 pub fn unlink(
1531 &self,
1532 current_task: &CurrentTask,
1533 name: &FsStr,
1534 kind: UnlinkKind,
1535 directory_mode: DirectoryMode,
1536 ) -> Result<(), Errno> {
1537 if DirEntry::is_reserved_name(name) {
1538 match kind {
1539 UnlinkKind::Directory => {
1540 if name == ".." {
1541 error!(ENOTEMPTY)
1542 } else if self.parent().is_none() {
1543 error!(EBUSY)
1545 } else {
1546 error!(EINVAL)
1547 }
1548 }
1549 UnlinkKind::NonDirectory => error!(ENOTDIR),
1550 }
1551 } else {
1552 self.entry.unlink(current_task, &self.mount, name, kind, directory_mode)
1553 }
1554 }
1555
1556 fn resolve(
1560 self,
1561 current_task: &CurrentTask,
1562 context: &mut LookupContext,
1563 ) -> Result<NamespaceNode, Errno> {
1564 let mut node = self;
1565
1566 loop {
1567 if !node.entry.node.is_lnk() || context.symlink_mode == SymlinkMode::NoFollow {
1568 break;
1569 }
1570 if context.remaining_follows == 0
1571 || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
1572 {
1573 return error!(ELOOP);
1574 }
1575 context.remaining_follows -= 1;
1576 node = match node.readlink(current_task)? {
1577 SymlinkTarget::Path(link_target) => {
1578 let link_directory = if link_target[0] == b'/' {
1579 match &context.resolve_base {
1581 ResolveBase::None => current_task.fs().root(),
1582 ResolveBase::Beneath(_) => return error!(EXDEV),
1583 ResolveBase::InRoot(root) => root.clone(),
1584 }
1585 } else {
1586 node.parent().unwrap_or(node)
1590 };
1591 current_task.lookup_path(context, link_directory, link_target.as_ref())?
1592 }
1593 SymlinkTarget::Node(node) => {
1594 if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS) {
1595 return error!(ELOOP);
1596 }
1597 node
1598 }
1599 };
1600 }
1601 Ok(node.enter_mount())
1602 }
1603
1604 pub fn lookup_child(
1606 &self,
1607 current_task: &CurrentTask,
1608 context: &mut LookupContext,
1609 basename: &FsStr,
1610 ) -> Result<NamespaceNode, Errno> {
1611 self.lookup_children(current_task, context, &[basename])
1612 }
1613
1614 pub fn lookup_children(
1616 &self,
1617 current_task: &CurrentTask,
1618 context: &mut LookupContext,
1619 mut basenames: &[&FsStr],
1620 ) -> Result<NamespaceNode, Errno> {
1621 for name in basenames {
1622 if name.len() > NAME_MAX as usize {
1623 return error!(ENAMETOOLONG);
1624 }
1625 }
1626
1627 let mut current_namespace_node = self.clone();
1628
1629 while basenames.len() > 0 {
1630 if !current_namespace_node.entry.node.is_dir() {
1631 return error!(ENOTDIR);
1632 }
1633
1634 let basename = basenames[0];
1635 if basename.is_empty() || basename == "." {
1636 basenames = &basenames[1..];
1637 continue;
1638 }
1639 if basename == ".." {
1640 let root = match &context.resolve_base {
1641 ResolveBase::None => current_task.fs().root(),
1642 ResolveBase::Beneath(node) => {
1643 if current_namespace_node == *node {
1645 return error!(EXDEV);
1646 }
1647 current_task.fs().root()
1648 }
1649 ResolveBase::InRoot(root) => root.clone(),
1650 };
1651
1652 if current_namespace_node != root {
1654 current_namespace_node =
1655 current_namespace_node.parent().unwrap_or(current_namespace_node)
1656 }
1657 if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1658 && current_namespace_node.mount != self.mount
1659 {
1660 return error!(EXDEV);
1661 }
1662
1663 if context.directory_mode == DirectoryMode::MustBeDirectory
1664 && !current_namespace_node.entry.node.is_dir()
1665 {
1666 return error!(ENOTDIR);
1667 }
1668 basenames = &basenames[1..];
1669 continue;
1670 }
1671 if basenames.len() == 1
1672 || !current_namespace_node.entry.node.ops().has_lookup_pipelined()
1673 {
1674 current_namespace_node = current_namespace_node.with_new_entry(
1675 current_namespace_node.entry.component_lookup(
1676 current_task,
1677 ¤t_namespace_node.mount,
1678 basename,
1679 )?,
1680 );
1681
1682 current_namespace_node = current_namespace_node.resolve(current_task, context)?;
1683
1684 if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1685 && current_namespace_node.mount != self.mount
1686 {
1687 return error!(EXDEV);
1688 }
1689
1690 if context.directory_mode == DirectoryMode::MustBeDirectory
1691 && !current_namespace_node.entry.node.is_dir()
1692 {
1693 return error!(ENOTDIR);
1694 }
1695
1696 basenames = &basenames[1..];
1697 continue;
1698 }
1699
1700 let pipelined_basenames = if let Some(pos) =
1701 basenames.iter().position(|&name| name.is_empty() || name == "." || name == "..")
1702 {
1703 &basenames[..pos]
1704 } else {
1705 basenames
1706 };
1707 let precomputed_entries = current_namespace_node.entry.get_children_pipelined(
1708 current_task,
1709 ¤t_namespace_node.mount,
1710 pipelined_basenames,
1711 );
1712 for entry in precomputed_entries {
1713 basenames = &basenames[1..];
1714 let child = current_namespace_node.with_new_entry(entry?);
1715
1716 current_namespace_node = child.clone().resolve(current_task, context)?;
1717
1718 if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1719 && current_namespace_node.mount != self.mount
1720 {
1721 return error!(EXDEV);
1722 }
1723
1724 if context.directory_mode == DirectoryMode::MustBeDirectory
1725 && !current_namespace_node.entry.node.is_dir()
1726 {
1727 return error!(ENOTDIR);
1728 }
1729
1730 if current_namespace_node != child {
1731 break;
1732 }
1733 }
1734 }
1735
1736 Ok(current_namespace_node)
1737 }
1738
1739 pub fn parent(&self) -> Option<NamespaceNode> {
1745 let mountpoint_or_self = self.escape_mount();
1746 let parent = mountpoint_or_self.entry.parent()?;
1747 Some(mountpoint_or_self.with_new_entry(parent))
1748 }
1749
1750 pub fn parent_within_mount(&self) -> Option<DirEntryHandle> {
1753 if let Ok(_) = self.mount_if_root() {
1754 return None;
1755 }
1756 self.entry.parent()
1757 }
1758
1759 pub fn is_descendant_of(&self, ancestor: &NamespaceNode) -> bool {
1764 let ancestor = ancestor.escape_mount();
1765 let mut current = self.escape_mount();
1766 while current != ancestor {
1767 if let Some(parent) = current.parent() {
1768 current = parent.escape_mount();
1769 } else {
1770 return false;
1771 }
1772 }
1773 true
1774 }
1775
1776 fn enter_one_mount(&self) -> Option<NamespaceNode> {
1781 if let Some(mount) = self.mount.deref() {
1782 if let Some(submount) =
1783 mount.relations.get_submount(&RcuReadScope::new(), &PtrKey::from(&self.entry))
1784 {
1785 return Some(submount.root());
1786 }
1787 }
1788 None
1789 }
1790
1791 fn enter_mount(&self) -> NamespaceNode {
1796 let kernel = self.entry.node.fs().kernel.upgrade().expect("kernel");
1798 kernel.mounts_lock.read_seq(|| {
1799 let mut inner = self.clone();
1800 while let Some(inner_root) = inner.enter_one_mount() {
1801 inner = inner_root;
1802 }
1803 inner
1804 })
1805 }
1806
1807 fn enter_mount_locked(&self, _mounts_guard: &MountsWriteToken) -> NamespaceNode {
1813 let mut inner = self.clone();
1815 while let Some(inner_root) = inner.enter_one_mount() {
1816 inner = inner_root;
1817 }
1818 inner
1819 }
1820
1821 fn escape_mount(&self) -> NamespaceNode {
1826 let kernel = self.entry.node.fs().kernel.upgrade().expect("kernel");
1827 kernel.mounts_lock.read_seq(|| {
1828 let mut mountpoint_or_self = self.clone();
1829 while let Some(mountpoint) = mountpoint_or_self.mountpoint() {
1830 mountpoint_or_self = mountpoint;
1831 }
1832 mountpoint_or_self
1833 })
1834 }
1835
1836 pub fn mount_if_root(&self) -> Result<&MountHandle, Errno> {
1838 if let Some(mount) = self.mount.deref() {
1839 if Arc::ptr_eq(&self.entry, &mount.root) {
1840 return Ok(mount);
1841 }
1842 }
1843 error!(EINVAL)
1844 }
1845
1846 fn mountpoint(&self) -> Option<NamespaceNode> {
1851 self.mount_if_root().ok()?.mountpoint()
1852 }
1853
1854 pub fn path(&self, fs: &FsContext) -> FsString {
1856 self.path_from_root(Some(&fs.root())).into_path()
1857 }
1858
1859 pub fn path_escaping_chroot(&self) -> FsString {
1861 self.path_from_root(None).into_path()
1862 }
1863
1864 pub fn path_from_root(&self, root: Option<&NamespaceNode>) -> PathWithReachability {
1867 if self.mount.is_none() {
1868 return self.unrooted_path();
1869 }
1870
1871 let mut path = PathBuilder::new();
1872 let mut current = self.escape_mount();
1873 if let Some(root) = root {
1874 let scope = RcuReadScope::new();
1875 let root = root.escape_mount();
1877 while current != root {
1878 if let Some(parent) = current.parent() {
1879 path.prepend_element(current.entry.local_name(&scope));
1880 current = parent.escape_mount();
1881 } else {
1882 let mut absolute_path = path.build_absolute();
1884 if self.entry.is_dead() {
1885 absolute_path.extend_from_slice(b" (deleted)");
1886 }
1887
1888 return PathWithReachability::Unreachable(absolute_path);
1889 }
1890 }
1891 } else {
1892 let scope = RcuReadScope::new();
1894 while let Some(parent) = current.parent() {
1895 path.prepend_element(current.entry.local_name(&scope));
1896 current = parent.escape_mount();
1897 }
1898 }
1899
1900 let mut absolute_path = path.build_absolute();
1901 if self.entry.is_dead() {
1902 absolute_path.extend_from_slice(b" (deleted)");
1903 }
1904
1905 PathWithReachability::Reachable(absolute_path)
1906 }
1907
1908 fn unrooted_path(&self) -> PathWithReachability {
1909 let scope = RcuReadScope::new();
1910 let mode = self.entry.node.info().mode;
1911 let local_name = self.entry.local_name(&scope);
1912 let path = if !local_name.is_empty() {
1913 format!("anon_inode:{}", local_name)
1914 } else if mode.is_sock() {
1915 format!("socket:[{}]", self.entry.node.ino)
1916 } else if mode.is_fifo() {
1917 format!("pipe:[{}]", self.entry.node.ino)
1918 } else {
1919 format!("file:[{}]", self.entry.node.ino)
1920 };
1921 PathWithReachability::Reachable(path.into())
1922 }
1923
1924 pub fn mount(&self, what: WhatToMount, flags: MountpointFlags) -> Result<(), Errno> {
1925 let target = self.enter_mount();
1926
1927 if target.mount.is_none() {
1930 return error!(ENOENT);
1931 }
1932
1933 let source_is_dir = match &what {
1934 WhatToMount::Fs(fs) => fs.root().node.is_dir(),
1935 WhatToMount::Bind(node) => node.entry.node.is_dir(),
1936 };
1937
1938 if source_is_dir != target.entry.node.is_dir() {
1941 return error!(ENOTDIR);
1942 }
1943
1944 let kernel = self.entry.node.fs().kernel.upgrade().expect("can't mount without a kernel");
1945 let mounts_guard = kernel.mounts_lock();
1946 let what = mounts_guard.defer_drop(what);
1947 let mountpoint = self.enter_mount_locked(&mounts_guard);
1948 let mountpoint = mounts_guard.defer_drop(mountpoint);
1949
1950 let mount = mountpoint.mount.as_ref().ok_or_else(|| errno!(ENOENT))?;
1951 let writeable_mount = mounts_guard.retain(mount);
1952 let writeable_entry = mounts_guard.retain(&mountpoint.entry);
1953 writeable_mount.create_submount(
1954 &mounts_guard,
1955 &writeable_entry,
1956 WhatSubmount::New(scopeguard::ScopeGuard::into_inner(what), flags),
1957 )
1958 }
1959
1960 pub fn unmount(&self, flags: UnmountFlags) -> Result<(), Errno> {
1962 let kernel = self.entry.node.fs().kernel.upgrade().expect("can't mount without a kernel");
1963 let mounts_guard = kernel.mounts_lock();
1964
1965 let mountpoint = self.enter_mount_locked(&mounts_guard);
1966 let mountpoint = mounts_guard.defer_drop(mountpoint);
1967 let mount = mounts_guard.retain(mountpoint.mount_if_root()?);
1968 mount.unmount(&mounts_guard, flags)
1969 }
1970
1971 pub fn rename(
1972 current_task: &CurrentTask,
1973 old_parent: &NamespaceNode,
1974 old_name: &FsStr,
1975 new_parent: &NamespaceNode,
1976 new_name: &FsStr,
1977 flags: RenameFlags,
1978 ) -> Result<(), Errno> {
1979 DirEntry::rename(
1980 current_task,
1981 &old_parent.entry,
1982 &old_parent.mount,
1983 old_name,
1984 &new_parent.entry,
1985 &new_parent.mount,
1986 new_name,
1987 flags,
1988 )
1989 }
1990
1991 fn with_new_entry(&self, entry: DirEntryHandle) -> NamespaceNode {
1992 Self { mount: self.mount.clone(), entry }
1993 }
1994
1995 fn mount_hash_key(&self) -> PtrKey<DirEntry> {
1996 PtrKey::from(&self.entry)
1997 }
1998
1999 pub fn apply_suid_and_sgid(&self, creds: &mut Credentials) {
2000 if self.mount.flags().contains(MountFlags::NOSUID) {
2006 return;
2007 }
2008 self.entry.node.info().apply_suid_and_sgid(creds)
2009 }
2010
2011 pub fn update_atime(&self) {
2012 if !self.mount.flags().contains(MountFlags::NOATIME) {
2014 self.entry.node.update_info(|info| {
2015 let now = utc::utc_now();
2016 info.time_access = now;
2017 info.pending_time_access_update = true;
2018 });
2019 }
2020 }
2021
2022 pub fn readlink(&self, current_task: &CurrentTask) -> Result<SymlinkTarget, Errno> {
2023 self.update_atime();
2024 self.entry.node.readlink(current_task)
2025 }
2026
2027 pub fn notify(&self, event_mask: InotifyMask) {
2028 if self.mount.is_some() {
2029 self.entry.notify(event_mask);
2030 }
2031 }
2032
2033 pub fn check_access(
2037 &self,
2038 current_task: &CurrentTask,
2039 access_check: AccessCheck,
2040 ) -> Result<(), Errno> {
2041 self.entry.node.check_access(
2042 current_task,
2043 &self.mount,
2044 access_check.permission_flags(),
2045 access_check.reason(),
2046 self,
2047 )
2048 }
2049
2050 pub fn check_o_noatime_allowed(&self, current_task: &CurrentTask) -> Result<(), Errno> {
2052 self.entry.node.check_o_noatime_allowed(current_task)
2053 }
2054
2055 pub fn truncate(&self, current_task: &CurrentTask, length: u64) -> Result<(), Errno> {
2056 self.entry.node.truncate(current_task, &self.mount, length)?;
2057 self.entry.notify_ignoring_excl_unlink(InotifyMask::MODIFY);
2058 Ok(())
2059 }
2060}
2061
2062impl fmt::Debug for NamespaceNode {
2063 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2064 f.debug_struct("NamespaceNode")
2065 .field("path", &self.path_escaping_chroot())
2066 .field("mount", &self.mount)
2067 .field("entry", &self.entry)
2068 .finish()
2069 }
2070}
2071
2072impl PartialEq for NamespaceNode {
2074 fn eq(&self, other: &Self) -> bool {
2075 self.mount.as_ref().map(Arc::as_ptr).eq(&other.mount.as_ref().map(Arc::as_ptr))
2076 && Arc::ptr_eq(&self.entry, &other.entry)
2077 }
2078}
2079impl Eq for NamespaceNode {}
2080impl Hash for NamespaceNode {
2081 fn hash<H: Hasher>(&self, state: &mut H) {
2082 self.mount.as_ref().map(Arc::as_ptr).hash(state);
2083 Arc::as_ptr(&self.entry).hash(state);
2084 }
2085}
2086
2087#[derive(Debug, Clone)]
2089pub struct ActiveNamespaceNode {
2090 name: NamespaceNode,
2092
2093 _marker: Option<MountClientMarker>,
2097}
2098
2099impl ActiveNamespaceNode {
2100 pub fn new(name: NamespaceNode) -> Self {
2101 let marker = name.mount.as_ref().map(|mount| mount.active_client_counter.clone());
2102 Self { name, _marker: marker }
2103 }
2104
2105 pub fn to_passive(&self) -> NamespaceNode {
2106 self.deref().clone()
2107 }
2108}
2109
2110impl Deref for ActiveNamespaceNode {
2111 type Target = NamespaceNode;
2112
2113 fn deref(&self) -> &Self::Target {
2114 &self.name
2115 }
2116}
2117
2118impl PartialEq for ActiveNamespaceNode {
2119 fn eq(&self, other: &Self) -> bool {
2120 self.deref().eq(other.deref())
2121 }
2122}
2123impl Eq for ActiveNamespaceNode {}
2124impl Hash for ActiveNamespaceNode {
2125 fn hash<H: Hasher>(&self, state: &mut H) {
2126 self.deref().hash(state)
2127 }
2128}
2129
2130#[derive(Debug, Clone)]
2133#[must_use]
2134pub struct FileMapping {
2135 file: FileHandle,
2136 mode: Option<FileWriteGuardMode>,
2137}
2138
2139impl FileMapping {
2140 pub fn new(file: FileHandle, mode: Option<FileWriteGuardMode>) -> Result<Arc<Self>, Errno> {
2142 if let Some(mode) = mode {
2143 file.name.entry.node.write_guard_state.lock().acquire(mode)?;
2144 }
2145 Ok(Arc::new(Self { file, mode }))
2146 }
2147
2148 pub fn file(&self) -> &FileHandle {
2150 &self.file
2151 }
2152
2153 pub fn name(&self) -> &ActiveNamespaceNode {
2155 &self.file.name
2156 }
2157
2158 pub fn node(&self) -> &FsNodeHandle {
2160 self.file.node()
2161 }
2162}
2163
2164impl PartialEq for FileMapping {
2165 fn eq(&self, other: &Self) -> bool {
2166 Arc::ptr_eq(&self.file, &other.file) && self.mode == other.mode
2167 }
2168}
2169
2170impl Eq for FileMapping {}
2171
2172impl Drop for FileMapping {
2173 fn drop(&mut self) {
2174 if let Some(mode) = self.mode {
2175 self.file.name.entry.node.write_guard_state.lock().release(mode);
2176 }
2177 }
2178}
2179
2180pub struct Mounts {
2182 mounts: RcuHashMap<WeakKey<DirEntry>, Vec<WeakKey<Mount>>>,
2183}
2184
2185impl Mounts {
2186 pub fn new() -> Self {
2187 Mounts { mounts: RcuHashMap::default() }
2188 }
2189
2190 fn register_mount(&self, dir_entry: &DirEntryHandle, mount: MountHandle) -> Submount {
2192 let mut mounts = self.mounts.lock();
2193 let key = WeakKey::from(dir_entry);
2194 let mut vec = mounts.get(&key).unwrap_or_else(|| {
2195 dir_entry.set_has_mounts(true);
2196 Vec::new()
2197 });
2198 vec.push(WeakKey::from(&mount));
2199 mounts.insert(key, vec);
2200 Submount { dir: dir_entry.clone(), mount }
2201 }
2202
2203 fn unregister_mount(&self, dir_entry: &DirEntryHandle, mount: &MountHandle) {
2205 let mut mounts = self.mounts.lock();
2206 let key = WeakKey::from(dir_entry);
2207 if let Some(mut vec) = mounts.get(&key) {
2208 let index = vec.iter().position(|e| e == &WeakKey::from(mount)).unwrap();
2209 if vec.len() == 1 {
2210 mounts.remove(&key);
2211 dir_entry.set_has_mounts(false);
2212 } else {
2213 vec.swap_remove(index);
2214 mounts.insert(key, vec);
2215 }
2216 }
2217 }
2218
2219 pub fn unmount(&self, dir_entry: &DirEntry) {
2223 let mounts = self.mounts.lock().remove(&PtrKey::from(dir_entry));
2224 if let Some(mounts) = mounts {
2225 let upgraded: Vec<_> = mounts.iter().filter_map(|m| m.0.upgrade()).collect();
2226 if let Some(kernel) = upgraded.first().map(|m| m.kernel()) {
2227 let mounts_guard = kernel.mounts_lock();
2228 let mounts = mounts_guard.defer_drop(upgraded);
2229 for mount in &*mounts {
2230 let _ = mount.unmount(&mounts_guard, UnmountFlags::DETACH);
2232 }
2233 }
2234 }
2235 }
2236
2237 pub fn clear(&self) {
2241 for (_dir_entry, mounts) in self.mounts.lock().drain() {
2242 for mount in mounts {
2243 if let Some(mount) = mount.0.upgrade() {
2244 mount.fs.force_unmount_ops();
2245 }
2246 }
2247 }
2248 }
2249
2250 fn unique_filesystems(&self) -> HashSet<ArcKey<FileSystem>> {
2253 let mut filesystems = HashSet::new();
2254 let mut queue = Vec::new();
2255 let scope = RcuReadScope::new();
2256 for (_dir_entry, m_list) in self.mounts.iter(&scope) {
2257 for m in m_list {
2258 if let Some(mount) = m.0.upgrade() {
2259 if filesystems.insert(ArcKey(mount.fs.clone())) {
2260 queue.push(mount.fs.clone());
2261 }
2262 }
2263 }
2264 }
2265 while let Some(fs) = queue.pop() {
2266 for sub_fs in fs.sub_filesystems() {
2267 if filesystems.insert(ArcKey(sub_fs.clone())) {
2268 queue.push(sub_fs);
2269 }
2270 }
2271 }
2272 filesystems
2273 }
2274
2275 pub fn sync_all(&self, current_task: &CurrentTask) -> Result<(), Errno> {
2276 for fs in self.unique_filesystems() {
2277 if let Err(e) = fs.sync(current_task) {
2278 log_warn!("sync failed for filesystem {:?}: {:?}", fs.name(), e);
2279 }
2280 }
2281 Ok(())
2282 }
2283
2284 pub fn drop_caches(&self) {
2285 let filesystems = self.unique_filesystems();
2286 for fs in &filesystems {
2289 fs.purge_dcache();
2290 }
2291 for fs in &filesystems {
2292 fs.drop_backend_caches();
2293 }
2294 }
2295}
2296
2297impl Drop for Mount {
2298 fn drop(&mut self) {
2299 let kernel = self.kernel();
2302 let peer_group = self.relations.peer_group.upgrade();
2303 let upstream = self.relations.upstream.cloned();
2304 self.relations.peer_group.update(None);
2305 self.relations.upstream.update(None);
2306 if peer_group.is_some() || upstream.is_some() {
2307 let mount_ptr = PtrKey::from(self as &Mount);
2308 register_delayed_call(move |_current_task| {
2309 let guard = kernel.mounts_lock();
2310 Mount::unregister_from_peer_group_and_upstream(
2311 &guard, peer_group, upstream, mount_ptr,
2312 );
2313 });
2314 }
2315 }
2316}
2317
2318impl fmt::Debug for Mount {
2319 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2320 let scope = RcuReadScope::new();
2321 f.debug_struct("Mount")
2322 .field("id", &(self as *const Mount))
2323 .field("root", &self.root)
2324 .field("mountpoint", &self.relations.mountpoint(&scope))
2325 .field(
2326 "submounts",
2327 &self
2328 .relations
2329 .iter_submounts(&scope)
2330 .filter_map(|(_, m)| m.upgrade())
2331 .collect::<Vec<_>>(),
2332 )
2333 .finish()
2334 }
2335}
2336
2337#[derive(Debug)]
2339struct Submount {
2340 dir: DirEntryHandle,
2341 mount: MountHandle,
2342}
2343
2344impl Drop for Submount {
2345 fn drop(&mut self) {
2346 self.mount.kernel().mounts.unregister_mount(&self.dir, &self.mount)
2347 }
2348}
2349
2350#[cfg(test)]
2351mod test {
2352 use crate::fs::tmpfs::TmpFs;
2353 use crate::testing::spawn_kernel_and_run;
2354 use crate::vfs::namespace::DeviceId;
2355 use crate::vfs::{
2356 CallbackSymlinkNode, DirectoryMode, FsNodeInfo, LookupContext, MountInfo, Namespace,
2357 NamespaceNode, RenameFlags, SymlinkMode, SymlinkTarget, UnlinkKind, WhatToMount,
2358 };
2359 use starnix_uapi::mount_flags::MountpointFlags;
2360 use starnix_uapi::{errno, mode};
2361 use std::sync::Arc;
2362
2363 #[::fuchsia::test]
2364 async fn test_namespace() {
2365 spawn_kernel_and_run(async |current_task| {
2366 let kernel = current_task.kernel();
2367 let root_fs = TmpFs::new_fs(&kernel);
2368 let root_node = Arc::clone(root_fs.root());
2369 let _dev_node =
2370 root_node.create_dir(¤t_task, "dev".into()).expect("failed to mkdir dev");
2371 let dev_fs = TmpFs::new_fs(&kernel);
2372 let dev_root_node = Arc::clone(dev_fs.root());
2373 let _dev_pts_node =
2374 dev_root_node.create_dir(¤t_task, "pts".into()).expect("failed to mkdir pts");
2375
2376 let ns = Namespace::new(root_fs);
2377 let mut context = LookupContext::default();
2378 let dev = ns
2379 .root()
2380 .lookup_child(¤t_task, &mut context, "dev".into())
2381 .expect("failed to lookup dev");
2382 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2383 .expect("failed to mount dev root node");
2384
2385 let mut context = LookupContext::default();
2386 let dev = ns
2387 .root()
2388 .lookup_child(¤t_task, &mut context, "dev".into())
2389 .expect("failed to lookup dev");
2390 let mut context = LookupContext::default();
2391 let pts = dev
2392 .lookup_child(¤t_task, &mut context, "pts".into())
2393 .expect("failed to lookup pts");
2394 let pts_parent =
2395 pts.parent().ok_or_else(|| errno!(ENOENT)).expect("failed to get parent of pts");
2396 assert!(Arc::ptr_eq(&pts_parent.entry, &dev.entry));
2397
2398 let dev_parent =
2399 dev.parent().ok_or_else(|| errno!(ENOENT)).expect("failed to get parent of dev");
2400 assert!(Arc::ptr_eq(&dev_parent.entry, &ns.root().entry));
2401 })
2402 .await;
2403 }
2404
2405 #[::fuchsia::test]
2406 async fn test_mount_does_not_upgrade() {
2407 spawn_kernel_and_run(async |current_task| {
2408 let kernel = current_task.kernel();
2409 let root_fs = TmpFs::new_fs(&kernel);
2410 let root_node = Arc::clone(root_fs.root());
2411 let _dev_node =
2412 root_node.create_dir(¤t_task, "dev".into()).expect("failed to mkdir dev");
2413 let dev_fs = TmpFs::new_fs(&kernel);
2414 let dev_root_node = Arc::clone(dev_fs.root());
2415 let _dev_pts_node =
2416 dev_root_node.create_dir(¤t_task, "pts".into()).expect("failed to mkdir pts");
2417
2418 let ns = Namespace::new(root_fs);
2419 let mut context = LookupContext::default();
2420 let dev = ns
2421 .root()
2422 .lookup_child(¤t_task, &mut context, "dev".into())
2423 .expect("failed to lookup dev");
2424 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2425 .expect("failed to mount dev root node");
2426 let mut context = LookupContext::default();
2427 let new_dev = ns
2428 .root()
2429 .lookup_child(¤t_task, &mut context, "dev".into())
2430 .expect("failed to lookup dev again");
2431 assert!(!Arc::ptr_eq(&dev.entry, &new_dev.entry));
2432 assert_ne!(&dev, &new_dev);
2433
2434 let mut context = LookupContext::default();
2435 let _new_pts = new_dev
2436 .lookup_child(¤t_task, &mut context, "pts".into())
2437 .expect("failed to lookup pts");
2438 let mut context = LookupContext::default();
2439 assert!(dev.lookup_child(¤t_task, &mut context, "pts".into()).is_err());
2440 })
2441 .await;
2442 }
2443
2444 #[::fuchsia::test]
2445 async fn test_path() {
2446 spawn_kernel_and_run(async |current_task| {
2447 let kernel = current_task.kernel();
2448 let root_fs = TmpFs::new_fs(&kernel);
2449 let root_node = Arc::clone(root_fs.root());
2450 let _dev_node =
2451 root_node.create_dir(¤t_task, "dev".into()).expect("failed to mkdir dev");
2452 let dev_fs = TmpFs::new_fs(&kernel);
2453 let dev_root_node = Arc::clone(dev_fs.root());
2454 let _dev_pts_node =
2455 dev_root_node.create_dir(¤t_task, "pts".into()).expect("failed to mkdir pts");
2456
2457 let ns = Namespace::new(root_fs);
2458 let mut context = LookupContext::default();
2459 let dev = ns
2460 .root()
2461 .lookup_child(¤t_task, &mut context, "dev".into())
2462 .expect("failed to lookup dev");
2463 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2464 .expect("failed to mount dev root node");
2465
2466 let mut context = LookupContext::default();
2467 let dev = ns
2468 .root()
2469 .lookup_child(¤t_task, &mut context, "dev".into())
2470 .expect("failed to lookup dev");
2471 let mut context = LookupContext::default();
2472 let pts = dev
2473 .lookup_child(¤t_task, &mut context, "pts".into())
2474 .expect("failed to lookup pts");
2475
2476 assert_eq!("/", ns.root().path_escaping_chroot());
2477 assert_eq!("/dev", dev.path_escaping_chroot());
2478 assert_eq!("/dev/pts", pts.path_escaping_chroot());
2479 })
2480 .await;
2481 }
2482
2483 #[::fuchsia::test]
2484 async fn test_shadowing() {
2485 spawn_kernel_and_run(async |current_task| {
2486 let kernel = current_task.kernel();
2487 let root_fs = TmpFs::new_fs(&kernel);
2488 let ns = Namespace::new(root_fs.clone());
2489 let _foo_node = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2490 let mut context = LookupContext::default();
2491 let foo_dir =
2492 ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2493
2494 let foofs1 = TmpFs::new_fs(&kernel);
2495 foo_dir.mount(WhatToMount::Fs(foofs1.clone()), MountpointFlags::empty()).unwrap();
2496 let mut context = LookupContext::default();
2497 assert!(Arc::ptr_eq(
2498 &ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap().entry,
2499 foofs1.root()
2500 ));
2501 let foo_dir =
2502 ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2503
2504 let ns_clone = ns.clone_namespace(&kernel.mounts_lock());
2505
2506 let foofs2 = TmpFs::new_fs(&kernel);
2507 foo_dir.mount(WhatToMount::Fs(foofs2.clone()), MountpointFlags::empty()).unwrap();
2508 let mut context = LookupContext::default();
2509 assert!(Arc::ptr_eq(
2510 &ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap().entry,
2511 foofs2.root()
2512 ));
2513
2514 assert!(Arc::ptr_eq(
2515 &ns_clone
2516 .root()
2517 .lookup_child(¤t_task, &mut LookupContext::default(), "foo".into())
2518 .unwrap()
2519 .entry,
2520 foofs1.root()
2521 ));
2522 })
2523 .await;
2524 }
2525
2526 #[::fuchsia::test]
2527 async fn test_unlink_mounted_directory() {
2528 spawn_kernel_and_run(async |current_task| {
2529 let kernel = current_task.kernel();
2530 let root_fs = TmpFs::new_fs(&kernel);
2531 let ns1 = Namespace::new(root_fs.clone());
2532 let ns2 = Namespace::new(root_fs.clone());
2533 let _foo_node = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2534 let mut context = LookupContext::default();
2535 let foo_dir =
2536 ns1.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2537
2538 let foofs = TmpFs::new_fs(&kernel);
2539 foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2540
2541 assert_eq!(
2543 ns1.root()
2544 .unlink(
2545 ¤t_task,
2546 "foo".into(),
2547 UnlinkKind::Directory,
2548 DirectoryMode::AllowAny
2549 )
2550 .unwrap_err(),
2551 errno!(EBUSY),
2552 );
2553
2554 ns2.root()
2556 .unlink(¤t_task, "foo".into(), UnlinkKind::Directory, DirectoryMode::AllowAny)
2557 .expect("unlink failed");
2558
2559 assert_eq!(
2561 ns1.root()
2562 .unlink(
2563 ¤t_task,
2564 "foo".into(),
2565 UnlinkKind::Directory,
2566 DirectoryMode::AllowAny
2567 )
2568 .unwrap_err(),
2569 errno!(ENOENT),
2570 );
2571 })
2572 .await;
2573 }
2574
2575 #[::fuchsia::test]
2576 async fn test_rename_mounted_directory() {
2577 spawn_kernel_and_run(async |current_task| {
2578 let kernel = current_task.kernel();
2579 let root_fs = TmpFs::new_fs(&kernel);
2580 let ns1 = Namespace::new(root_fs.clone());
2581 let ns2 = Namespace::new(root_fs.clone());
2582 let _foo_node = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2583 let _bar_node = root_fs.root().create_dir(¤t_task, "bar".into()).unwrap();
2584 let _baz_node = root_fs.root().create_dir(¤t_task, "baz".into()).unwrap();
2585 let mut context = LookupContext::default();
2586 let foo_dir =
2587 ns1.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2588
2589 let foofs = TmpFs::new_fs(&kernel);
2590 foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2591
2592 let root = ns1.root();
2594 assert_eq!(
2595 NamespaceNode::rename(
2596 ¤t_task,
2597 &root,
2598 "bar".into(),
2599 &root,
2600 "foo".into(),
2601 RenameFlags::empty()
2602 )
2603 .unwrap_err(),
2604 errno!(EBUSY),
2605 );
2606 assert_eq!(
2608 NamespaceNode::rename(
2609 ¤t_task,
2610 &root,
2611 "foo".into(),
2612 &root,
2613 "bar".into(),
2614 RenameFlags::empty()
2615 )
2616 .unwrap_err(),
2617 errno!(EBUSY),
2618 );
2619
2620 let root = ns2.root();
2622
2623 NamespaceNode::rename(
2625 ¤t_task,
2626 &root,
2627 "foo".into(),
2628 &root,
2629 "bar".into(),
2630 RenameFlags::empty(),
2631 )
2632 .expect("rename failed");
2633
2634 NamespaceNode::rename(
2636 ¤t_task,
2637 &root,
2638 "baz".into(),
2639 &root,
2640 "bar".into(),
2641 RenameFlags::empty(),
2642 )
2643 .expect("rename failed");
2644
2645 assert_eq!(
2647 ns1.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap_err(),
2648 errno!(ENOENT)
2649 );
2650 assert_eq!(
2651 ns1.root().lookup_child(¤t_task, &mut context, "baz".into()).unwrap_err(),
2652 errno!(ENOENT)
2653 );
2654 })
2655 .await;
2656 }
2657
2658 #[::fuchsia::test]
2661 async fn test_lookup_with_symlink_chain() {
2662 spawn_kernel_and_run(async |current_task| {
2663 let kernel = current_task.kernel();
2665 let root_fs = TmpFs::new_fs(&kernel);
2666 let root_node = Arc::clone(root_fs.root());
2667 let _first_subdir_node = root_node
2668 .create_dir(¤t_task, "first_subdir".into())
2669 .expect("failed to mkdir dev");
2670 let _second_subdir_node = root_node
2671 .create_dir(¤t_task, "second_subdir".into())
2672 .expect("failed to mkdir dev");
2673
2674 let first_subdir_fs = TmpFs::new_fs(&kernel);
2676 let second_subdir_fs = TmpFs::new_fs(&kernel);
2677
2678 let ns = Namespace::new(root_fs);
2679 let mut context = LookupContext::default();
2680 let first_subdir = ns
2681 .root()
2682 .lookup_child(¤t_task, &mut context, "first_subdir".into())
2683 .expect("failed to lookup first_subdir");
2684 first_subdir
2685 .mount(WhatToMount::Fs(first_subdir_fs), MountpointFlags::empty())
2686 .expect("failed to mount first_subdir fs node");
2687 let second_subdir = ns
2688 .root()
2689 .lookup_child(¤t_task, &mut context, "second_subdir".into())
2690 .expect("failed to lookup second_subdir");
2691 second_subdir
2692 .mount(WhatToMount::Fs(second_subdir_fs), MountpointFlags::empty())
2693 .expect("failed to mount second_subdir fs node");
2694
2695 let real_file_node = first_subdir
2704 .create_node(¤t_task, "real_file".into(), mode!(IFREG, 0o777), DeviceId::NONE)
2705 .expect("failed to create real_file");
2706 first_subdir
2707 .create_symlink(¤t_task, "path_symlink".into(), "real_file".into())
2708 .expect("failed to create path_symlink");
2709
2710 let mut no_follow_lookup_context = LookupContext::new(SymlinkMode::NoFollow);
2711 let path_symlink_node = first_subdir
2712 .lookup_child(¤t_task, &mut no_follow_lookup_context, "path_symlink".into())
2713 .expect("Failed to lookup path_symlink");
2714
2715 let node_symlink_node = second_subdir.entry.node.fs().create_node_and_allocate_node_id(
2719 CallbackSymlinkNode::new(move || {
2720 let node = path_symlink_node.clone();
2721 Ok(SymlinkTarget::Node(node))
2722 }),
2723 FsNodeInfo::new(mode!(IFLNK, 0o777), current_task.current_fscred()),
2724 );
2725 second_subdir
2726 .entry
2727 .create_entry(
2728 ¤t_task,
2729 &MountInfo::detached(),
2730 "node_symlink".into(),
2731 move |_dir, _mount, _name| Ok(node_symlink_node),
2732 )
2733 .expect("failed to create node_symlink entry");
2734
2735 let mut follow_lookup_context = LookupContext::new(SymlinkMode::Follow);
2737 let node_symlink_resolution = second_subdir
2738 .lookup_child(¤t_task, &mut follow_lookup_context, "node_symlink".into())
2739 .expect("lookup with symlink chain failed");
2740
2741 assert!(node_symlink_resolution.entry.node.ino == real_file_node.entry.node.ino);
2743 })
2744 .await;
2745 }
2746}