1use crate::security;
6use crate::task::{
7 CurrentTask, EventHandler, Kernel, MountsWriteToken, Task, WaitCanceler, Waiter,
8};
9use crate::time::utc;
10use crate::vfs::fs_registry::FsRegistry;
11use crate::vfs::pseudo::dynamic_file::{DynamicFile, DynamicFileBuf, DynamicFileSource};
12use crate::vfs::pseudo::simple_file::SimpleFileNode;
13use crate::vfs::socket::{SocketAddress, SocketHandle, UnixSocket};
14use crate::vfs::{
15 CheckAccessReason, DirEntry, DirEntryHandle, FileHandle, FileObject, FileOps, FileSystemHandle,
16 FileSystemOptions, FileWriteGuardMode, FsContext, FsNode, FsNodeHandle, FsNodeOps, FsStr,
17 FsString, PathBuilder, RenameFlags, SymlinkTarget, UnlinkKind, fileops_impl_dataless,
18 fileops_impl_delegate_read_write_and_seek, fileops_impl_nonseekable, fileops_impl_noop_sync,
19 fs_node_impl_not_dir,
20};
21use fuchsia_rcu::{RcuBox, RcuReadScope};
22use fuchsia_rcu_collections::rcu_raw_hash_map::RcuRawHashMap;
23use ref_cast::RefCast;
24use starnix_logging::log_warn;
25use starnix_rcu::RcuHashMap;
26use starnix_sync::{LockDepMutex, NamespaceFlagsLock};
27use starnix_uapi::arc_key::{ArcKey, PtrKey, WeakKey};
28use starnix_uapi::auth::Credentials;
29use starnix_uapi::device_id::DeviceId;
30use starnix_uapi::errors::Errno;
31use starnix_uapi::file_mode::{AccessCheck, FileMode};
32use starnix_uapi::inotify_mask::InotifyMask;
33use starnix_uapi::mount_flags::{
34 AtomicMountpointFlags, FileSystemFlags, MountFlags, MountpointFlags,
35};
36use starnix_uapi::open_flags::OpenFlags;
37use starnix_uapi::unmount_flags::UnmountFlags;
38use starnix_uapi::vfs::{FdEvents, ResolveFlags};
39use starnix_uapi::{NAME_MAX, errno, error};
40use std::borrow::Borrow;
41use std::collections::HashSet;
42use std::fmt;
43use std::hash::{Hash, Hasher};
44use std::ops::{Deref, DerefMut};
45use std::sync::atomic::Ordering;
46use std::sync::{Arc, Weak};
47
48#[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 mut node: NamespaceNode,
92 new_ns: &Namespace,
93 _mounts_guard: &MountsWriteToken,
94 ) -> Option<NamespaceNode> {
95 let mut mountpoints = vec![];
97 let mut mount = node.mount;
98 while let Some(mountpoint) = mount.as_ref().and_then(|m| m.mountpoint()) {
99 mountpoints.push(mountpoint.entry);
100 mount = mountpoint.mount;
101 }
102
103 let scope = RcuReadScope::new();
105 let mut mount = &new_ns.root_mount;
106 for mountpoint in mountpoints.iter().rev() {
107 let next_mount =
108 &mount.relations.get_submount(&scope, ArcKey::ref_cast(mountpoint))?.mount;
109 mount = next_mount;
110 }
111 node.mount = Some(Arc::clone(mount)).into();
112 Some(node)
113 }
114}
115
116impl FsNodeOps for Arc<Namespace> {
117 fs_node_impl_not_dir!();
118
119 fn create_file_ops(
120 &self,
121 _node: &FsNode,
122 _current_task: &CurrentTask,
123 _flags: OpenFlags,
124 ) -> Result<Box<dyn FileOps>, Errno> {
125 Ok(Box::new(MountNamespaceFile(self.clone())))
126 }
127}
128
129pub struct MountNamespaceFile(pub Arc<Namespace>);
130
131impl FileOps for MountNamespaceFile {
132 fileops_impl_nonseekable!();
133 fileops_impl_dataless!();
134 fileops_impl_noop_sync!();
135}
136
137type MountClientMarker = Arc<()>;
142
143pub struct Mount {
152 root: DirEntryHandle,
153 fs: FileSystemHandle,
154
155 flags: AtomicMountpointFlags,
157
158 flags_lock: LockDepMutex<(), NamespaceFlagsLock>,
160
161 id: u64,
163
164 active_client_counter: MountClientMarker,
166
167 relations: MountRelations,
174 }
181type MountHandle = Arc<Mount>;
182
183#[derive(Clone, Debug)]
185pub struct MountInfo {
186 handle: Option<MountHandle>,
187}
188
189impl MountInfo {
190 pub fn detached() -> Self {
193 None.into()
194 }
195
196 pub fn flags(&self) -> MountFlags {
198 if let Some(handle) = &self.handle {
199 handle.flags()
200 } else {
201 MountFlags::NOATIME
203 }
204 }
205
206 pub fn check_readonly_filesystem(&self) -> Result<(), Errno> {
208 if self.flags().contains(MountFlags::RDONLY) {
209 return error!(EROFS);
210 }
211 Ok(())
212 }
213
214 pub fn check_noexec_filesystem(&self) -> Result<(), Errno> {
216 if self.flags().contains(MountFlags::NOEXEC) {
217 return error!(EACCES);
218 }
219 Ok(())
220 }
221}
222
223impl Deref for MountInfo {
224 type Target = Option<MountHandle>;
225
226 fn deref(&self) -> &Self::Target {
227 &self.handle
228 }
229}
230
231impl DerefMut for MountInfo {
232 fn deref_mut(&mut self) -> &mut Self::Target {
233 &mut self.handle
234 }
235}
236
237impl std::cmp::PartialEq for MountInfo {
238 fn eq(&self, other: &Self) -> bool {
239 self.handle.as_ref().map(Arc::as_ptr) == other.handle.as_ref().map(Arc::as_ptr)
240 }
241}
242
243impl std::cmp::Eq for MountInfo {}
244
245impl Into<MountInfo> for Option<MountHandle> {
246 fn into(self) -> MountInfo {
247 MountInfo { handle: self }
248 }
249}
250
251#[derive(Default)]
252struct MountRelations {
253 mountpoint: RcuBox<Option<(Weak<Mount>, DirEntryHandle)>>,
255 submounts: RcuRawHashMap<ArcKey<DirEntry>, Arc<Submount>>,
257 peer_group: RcuBox<Option<(Arc<PeerGroup>, PtrKey<Mount>)>>,
259 upstream: RcuBox<Option<(Weak<PeerGroup>, PtrKey<Mount>)>>,
261}
262
263impl MountRelations {
264 fn get_submount<'a>(
265 &'a self,
266 scope: &'a starnix_rcu::RcuReadScope,
267 key: &ArcKey<DirEntry>,
268 ) -> Option<&'a Arc<Submount>> {
269 self.submounts.get(scope, key)
270 }
271
272 fn insert_submount(
273 &self,
274 _guard: &MountsWriteToken,
275 key: ArcKey<DirEntry>,
276 value: Arc<Submount>,
277 ) -> Option<Arc<Submount>> {
278 let scope = starnix_rcu::RcuReadScope::new();
279 let result = unsafe { self.submounts.insert(&scope, key, value) };
281 match result {
282 fuchsia_rcu_collections::rcu_raw_hash_map::InsertionResult::Inserted(_) => None,
283 fuchsia_rcu_collections::rcu_raw_hash_map::InsertionResult::Updated(old) => Some(old),
284 }
285 }
286
287 fn remove_submount(
288 &self,
289 guard: &MountsWriteToken,
290 key: &ArcKey<DirEntry>,
291 ) -> Result<(), Errno> {
292 let submount = unsafe { self.submounts.remove(key) };
294 let submount = scopeguard::guard(submount, |submount| guard.defer_drop(submount));
295 if submount.is_some() { Ok(()) } else { error!(EINVAL) }
296 }
297
298 fn iter_submounts<'a>(
299 &'a self,
300 scope: &'a starnix_rcu::RcuReadScope,
301 ) -> impl Iterator<Item = (&'a ArcKey<DirEntry>, &'a Arc<Submount>)> {
302 let mut cursor = self.submounts.cursor(scope);
303 std::iter::from_fn(move || {
304 let current = cursor.current();
305 if current.is_some() {
306 cursor.advance();
307 }
308 current
309 })
310 }
311
312 fn submounts_len(&self) -> usize {
313 self.submounts.len()
314 }
315
316 fn set_mountpoint(
317 &self,
318 _guard: &MountsWriteToken,
319 mountpoint: Option<(Weak<Mount>, DirEntryHandle)>,
320 ) {
321 self.mountpoint.update(mountpoint);
322 }
323
324 fn mountpoint<'a>(
325 &'a self,
326 scope: &'a starnix_rcu::RcuReadScope,
327 ) -> Option<&'a (Weak<Mount>, DirEntryHandle)> {
328 self.mountpoint.as_ref(scope).as_ref()
329 }
330
331 fn take_peer_group(
332 &self,
333 _guard: &MountsWriteToken,
334 ) -> Option<(Arc<PeerGroup>, PtrKey<Mount>)> {
335 let peer_group = self.peer_group.cloned();
336 self.peer_group.update(None);
337 peer_group
338 }
339
340 fn take_upstream(&self, _guard: &MountsWriteToken) -> Option<(Weak<PeerGroup>, PtrKey<Mount>)> {
341 let upstream = self.upstream.cloned();
342 self.upstream.update(None);
343 upstream
344 }
345}
346
347#[derive(Default)]
351struct PeerGroup {
352 id: u64,
353 mounts: RcuRawHashMap<WeakKey<Mount>, ()>,
354 downstream: RcuRawHashMap<WeakKey<Mount>, ()>,
355}
356
357pub enum WhatToMount {
358 Fs(FileSystemHandle),
359 Bind(NamespaceNode),
360}
361
362enum WhatSubmount {
363 New(WhatToMount, MountpointFlags),
364 Existing(MountHandle),
365}
366
367impl Mount {
368 pub fn new(
369 mounts_guard: &MountsWriteToken,
370 what: WhatToMount,
371 mut flags: MountpointFlags,
372 ) -> Result<MountHandle, Errno> {
373 match what {
374 WhatToMount::Fs(fs) => {
375 flags.default_atime_from(MountpointFlags::RELATIME);
377 Ok(Self::new_with_root(fs.root().clone(), flags))
378 }
379 WhatToMount::Bind(node) => {
380 let mount = node.mount.as_ref().ok_or_else(|| errno!(ENOENT))?;
383 Ok(mount.clone_mount(mounts_guard, &node.entry, flags.into()))
384 }
385 }
386 }
387
388 fn new_with_root(root: DirEntryHandle, flags: MountpointFlags) -> MountHandle {
389 let fs = root.node.fs();
390 let kernel = fs.kernel.upgrade().expect("can't create mount without kernel");
391 Arc::new(Self {
392 id: kernel.get_next_mount_id(),
393 flags: (flags & MountpointFlags::STORED_ON_MOUNT).into(),
394 flags_lock: Default::default(),
395 root,
396 active_client_counter: Default::default(),
397 fs,
398 relations: Default::default(),
399 })
400 }
401
402 pub fn root(self: &MountHandle) -> NamespaceNode {
404 NamespaceNode::new(Arc::clone(self), Arc::clone(&self.root))
405 }
406
407 fn kernel(&self) -> Arc<Kernel> {
408 self.fs.kernel.upgrade().expect("No Kernel")
409 }
410
411 fn create_submount(
413 self: &MountHandle,
414 mounts_guard: &MountsWriteToken,
415 dir: &DirEntryHandle,
416 what: WhatSubmount,
417 ) -> Result<(), Errno> {
418 let peers = self.peer_group().map(|g| g.copy_propagation_targets()).unwrap_or_default();
421 let peers = scopeguard::guard(peers, |peers| mounts_guard.defer_drop(peers));
422
423 let mount = match what {
428 WhatSubmount::Existing(mount) => mount,
429 WhatSubmount::New(what, flags) => Mount::new(mounts_guard, what, flags)?,
430 };
431
432 if self.is_shared() {
433 mount.make_shared(mounts_guard);
434 }
435
436 for peer in &*peers {
437 if Arc::ptr_eq(self, peer) {
438 continue;
439 }
440 let clone = mount.clone_mount_recursive(mounts_guard);
441 peer.add_submount_internal(mounts_guard, dir, clone);
442 }
443
444 self.add_submount_internal(mounts_guard, dir, mount);
445 Ok(())
446 }
447
448 fn remove_submount(
449 self: &MountHandle,
450 mounts_guard: &MountsWriteToken,
451 mount_hash_key: &ArcKey<DirEntry>,
452 ) -> Result<(), Errno> {
453 let peers = self.peer_group().map(|g| g.copy_propagation_targets()).unwrap_or_default();
455 let peers = scopeguard::guard(peers, |peers| mounts_guard.defer_drop(peers));
456
457 for peer in &*peers {
458 if Arc::ptr_eq(self, peer) {
459 continue;
460 }
461 let scope = RcuReadScope::new();
465 if let Some(submount) = peer.relations.submounts.get(&scope, mount_hash_key) {
466 if submount.mount.relations.submounts_len() != 0 {
467 continue;
468 }
469 }
470 let _ = peer.remove_submount_internal(mounts_guard, mount_hash_key);
471 }
472
473 self.remove_submount_internal(mounts_guard, mount_hash_key)
474 }
475
476 pub fn move_mount(
477 source_mount: &MountHandle,
478 target_mount: &MountHandle,
479 target_dir: &DirEntryHandle,
480 ) -> Result<(), Errno> {
481 let kernel = target_mount.kernel();
482 let mounts_guard = kernel.mounts_lock();
483
484 let source_mountpoint = source_mount.mountpoint().ok_or_else(|| errno!(EIO))?;
485 let source_parent = mounts_guard.retain(
486 source_mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount"),
487 );
488 mounts_guard.retain(&source_mountpoint.entry);
489
490 {
492 if source_parent.peer_group().is_some() {
493 return error!(EINVAL);
497 }
498 source_parent
499 .remove_submount_internal(&mounts_guard, source_mountpoint.mount_hash_key())?;
500 source_mount.relations.set_mountpoint(&mounts_guard, None);
501 }
502
503 target_mount.create_submount(
504 &mounts_guard,
505 target_dir,
506 WhatSubmount::Existing(Arc::clone(source_mount)),
507 )?;
508 Ok(())
509 }
510
511 fn clone_mount(
514 self: &MountHandle,
515 mounts_guard: &MountsWriteToken,
516 new_root: &DirEntryHandle,
517 flags: MountFlags,
518 ) -> MountHandle {
519 assert!(new_root.is_descendant_of(&self.root));
520 let clone = Self::new_with_root(Arc::clone(new_root), self.mount_flags());
523
524 if flags.contains(MountFlags::REC) {
525 for (dir, submount) in self.relations.iter_submounts(&RcuReadScope::new()) {
526 let submount = submount.mount.clone_mount_recursive(mounts_guard);
527 clone.add_submount_internal(mounts_guard, dir, submount);
528 }
529 }
530
531 let peer_group = self.peer_group();
533 if let Some(peer_group) = peer_group {
534 clone.set_peer_group(mounts_guard, peer_group);
535 }
536
537 clone
538 }
539
540 fn clone_mount_recursive(self: &MountHandle, mounts_guard: &MountsWriteToken) -> MountHandle {
543 self.clone_mount(mounts_guard, &self.root, MountFlags::REC)
544 }
545
546 pub fn change_propagation(
547 self: &MountHandle,
548 mounts_guard: &MountsWriteToken,
549 flag: MountFlags,
550 recursive: bool,
551 ) {
552 match flag {
553 MountFlags::SHARED => self.make_shared(mounts_guard),
554 MountFlags::PRIVATE => self.make_private(mounts_guard),
555 MountFlags::DOWNSTREAM => self.make_downstream(mounts_guard),
556 _ => {
557 log_warn!("mount propagation {:?}", flag);
558 }
559 }
560
561 if recursive {
562 for (_, submount) in self.relations.iter_submounts(&starnix_rcu::RcuReadScope::new()) {
563 submount.mount.change_propagation(mounts_guard, flag, recursive);
564 }
565 }
566 }
567
568 fn flags(&self) -> MountFlags {
571 MountFlags::from(self.mount_flags()) | self.fs_flags().into()
572 }
573
574 fn mount_flags(&self) -> MountpointFlags {
576 self.flags.load(Ordering::Relaxed)
577 }
578
579 fn fs_flags(&self) -> FileSystemFlags {
581 self.fs.options.flags.load(Ordering::Relaxed)
582 }
583
584 pub fn update_flags(self: &MountHandle, mut flags: MountpointFlags) {
587 let _lock = self.flags_lock.lock();
588 flags.default_atime_from(self.flags.load(Ordering::Relaxed));
593 flags &= MountpointFlags::STORED_ON_MOUNT;
594 self.flags.store(flags, Ordering::Relaxed);
595 }
596
597 fn active_clients(&self) -> usize {
601 Arc::strong_count(&self.active_client_counter) - 1
603 }
604
605 pub fn unmount(
606 &self,
607 mounts_guard: &MountsWriteToken,
608 flags: UnmountFlags,
609 ) -> Result<(), Errno> {
610 if !flags.contains(UnmountFlags::DETACH) {
611 if self.active_clients() > 0 || self.relations.submounts_len() != 0 {
612 return error!(EBUSY);
613 }
614 }
615
616 let mountpoint = self.mountpoint().ok_or_else(|| errno!(EINVAL))?;
617 let parent_mount = mountpoint.mount.as_ref().expect("a mountpoint must be part of a mount");
618 parent_mount.remove_submount(mounts_guard, mountpoint.mount_hash_key())
619 }
620
621 pub fn security_state(&self) -> &security::FileSystemState {
623 &self.fs.security_state
624 }
625
626 pub fn fs_name(&self) -> &'static FsStr {
628 self.fs.name()
629 }
630
631 pub fn reconfigure_fs(
633 &self,
634 current_task: &CurrentTask,
635 flags: FileSystemFlags,
636 ) -> Result<(), Errno> {
637 self.fs.update_flags(current_task, flags)
638 }
639
640 pub fn has_submount(&self, dir_entry: &DirEntryHandle) -> bool {
642 let scope = RcuReadScope::new();
643 self.relations.get_submount(&scope, ArcKey::ref_cast(dir_entry)).is_some()
644 }
645
646 pub fn mountpoint(&self) -> Option<NamespaceNode> {
648 let scope = RcuReadScope::new();
649 let (mount, entry) = self.relations.mountpoint(&scope)?;
650 Some(NamespaceNode::new(mount.upgrade()?, entry.clone()))
651 }
652
653 pub fn add_submount_internal(
655 self: &MountHandle,
656 guard: &MountsWriteToken,
657 dir: &DirEntryHandle,
658 mount: MountHandle,
659 ) {
660 if !dir.is_descendant_of(&self.root) {
661 return;
662 }
663
664 let submount = mount.kernel().mounts.register_mount(dir, mount.clone());
665
666 let old_mountpoint = {
667 let scope = RcuReadScope::new();
668 mount.relations.mountpoint(&scope).map(|x| x.clone())
669 };
670 mount.relations.set_mountpoint(guard, Some((Arc::downgrade(self), Arc::clone(dir))));
671 assert!(old_mountpoint.is_none(), "add_submount can only take a newly created mount");
672
673 let old_mount = self.relations.insert_submount(
674 guard,
675 ArcKey::ref_cast(dir).clone(),
676 Arc::new(submount),
677 );
678
679 if let Some(old_mount) = old_mount {
680 old_mount
681 .mount
682 .relations
683 .set_mountpoint(guard, Some((Arc::downgrade(&mount), Arc::clone(dir))));
684 let new_old_submount =
685 mount.kernel().mounts.register_mount(&mount.root, old_mount.mount.clone());
686 mount.relations.insert_submount(
687 guard,
688 ArcKey(mount.root.clone()),
689 Arc::new(new_old_submount),
690 );
691 }
692 }
693
694 pub fn remove_submount_internal(
695 self: &MountHandle,
696 guard: &MountsWriteToken,
697 mount_hash_key: &ArcKey<DirEntry>,
698 ) -> Result<(), Errno> {
699 self.relations.remove_submount(guard, mount_hash_key)
700 }
701
702 fn peer_group(&self) -> Option<Arc<PeerGroup>> {
704 let scope = RcuReadScope::new();
705 self.relations.peer_group.as_ref(&scope).as_ref().map(|(g, _)| g.clone())
706 }
707
708 fn unregister_from_peer_group_and_upstream(
711 guard: &MountsWriteToken,
712 peer_group: Option<(Arc<PeerGroup>, PtrKey<Mount>)>,
713 upstream: Option<(Weak<PeerGroup>, PtrKey<Mount>)>,
714 ) {
715 let upstream_group = match upstream {
716 Some((weak_group, mount)) => {
717 if let Some(group) = weak_group.upgrade() {
718 group.remove_downstream(guard, mount);
719 Some(group)
720 } else {
721 None
722 }
723 }
724 None => None,
725 };
726
727 if let Some((group, mount)) = peer_group {
728 group.remove(guard, mount);
729
730 if let Some(upstream_group) = upstream_group {
731 let next_mount = {
732 let scope = RcuReadScope::new();
733 group.mounts.keys(&scope).next().map(|w| w.0.upgrade().unwrap())
734 };
735 if let Some(next_mount) = next_mount {
736 next_mount.set_upstream(guard, upstream_group);
737 }
738 }
739 }
740 }
741
742 fn take_from_peer_group(&self, guard: &MountsWriteToken) -> Option<Arc<PeerGroup>> {
744 let peer_group = self.relations.take_peer_group(guard);
745 if peer_group.is_none() {
746 return None;
747 }
748 let upstream = self.relations.take_upstream(guard);
749 let return_group = peer_group.as_ref().map(|(g, _)| g.clone());
750 Mount::unregister_from_peer_group_and_upstream(guard, peer_group, upstream);
751 return_group
752 }
753
754 fn upstream(&self) -> Option<Arc<PeerGroup>> {
755 let scope = RcuReadScope::new();
756 let (group, _) = self.relations.upstream.as_ref(&scope).as_ref()?;
757 group.upgrade()
758 }
759
760 fn remove_from_upstream(&self, guard: &MountsWriteToken) {
761 let upstream = self.relations.take_upstream(guard);
762 if let Some((weak_group, mount)) = upstream {
763 if let Some(group) = weak_group.upgrade() {
764 group.remove_downstream(guard, mount);
765 }
766 }
767 }
768
769 fn set_peer_group(self: &Arc<Mount>, guard: &MountsWriteToken, group: Arc<PeerGroup>) {
771 self.take_from_peer_group(guard);
772 group.add(guard, self);
773 self.relations.peer_group.update(Some((group, Arc::as_ptr(self).into())));
774 }
775
776 fn set_upstream(self: &Arc<Mount>, guard: &MountsWriteToken, group: Arc<PeerGroup>) {
777 self.remove_from_upstream(guard);
778 group.add_downstream(guard, self);
779 self.relations.upstream.update(Some((Arc::downgrade(&group), Arc::as_ptr(self).into())));
780 }
781
782 pub fn is_shared(&self) -> bool {
784 self.peer_group().is_some()
785 }
786
787 fn make_shared(self: &Arc<Mount>, guard: &MountsWriteToken) {
789 if self.is_shared() {
790 return;
791 }
792 let kernel = self.kernel();
793 self.set_peer_group(guard, PeerGroup::new(kernel.get_next_peer_group_id()))
794 }
795
796 fn make_private(&self, guard: &MountsWriteToken) {
798 let peer_group = self.relations.take_peer_group(guard);
799 let upstream = self.relations.take_upstream(guard);
800 Mount::unregister_from_peer_group_and_upstream(guard, peer_group, upstream);
801 }
802
803 fn make_downstream(self: &Arc<Mount>, guard: &MountsWriteToken) {
806 if let Some(peer_group) = self.take_from_peer_group(guard) {
807 self.set_upstream(guard, peer_group);
808 }
809 }
810}
811
812impl PeerGroup {
813 fn new(id: u64) -> Arc<Self> {
814 Arc::new(Self {
815 id,
816 mounts: RcuRawHashMap::default(),
817 downstream: RcuRawHashMap::default(),
818 })
819 }
820
821 fn add(&self, _guard: &MountsWriteToken, mount: &Arc<Mount>) {
822 unsafe { self.mounts.insert(&starnix_rcu::RcuReadScope::new(), WeakKey::from(mount), ()) };
824 }
825
826 fn remove(&self, _guard: &MountsWriteToken, mount: PtrKey<Mount>) {
827 unsafe { self.mounts.remove(&mount) };
829 }
830
831 fn add_downstream(&self, _guard: &MountsWriteToken, mount: &Arc<Mount>) {
832 unsafe {
834 self.downstream.insert(&starnix_rcu::RcuReadScope::new(), WeakKey::from(mount), ())
835 };
836 }
837
838 fn remove_downstream(&self, _guard: &MountsWriteToken, mount: PtrKey<Mount>) {
839 unsafe { self.downstream.remove(&mount) };
841 }
842
843 fn copy_propagation_targets(&self) -> Vec<MountHandle> {
844 let mut buf = vec![];
845 self.collect_propagation_targets(&mut buf);
846 buf
847 }
848
849 fn collect_propagation_targets(&self, buf: &mut Vec<MountHandle>) {
850 let downstream_mounts: Vec<_> = {
851 let scope = RcuReadScope::new();
852 buf.extend(self.mounts.keys(&scope).filter_map(|m| m.0.upgrade()));
853 self.downstream.keys(&scope).filter_map(|m| m.0.upgrade()).collect()
854 };
855 for mount in downstream_mounts {
856 let peer_group = mount.peer_group();
857 match peer_group {
858 Some(group) => group.collect_propagation_targets(buf),
859 None => buf.push(mount),
860 }
861 }
862 }
863}
864
865impl Kernel {
866 pub fn get_next_mount_id(&self) -> u64 {
867 self.next_mount_id.next()
868 }
869
870 pub fn get_next_peer_group_id(&self) -> u64 {
871 self.next_peer_group_id.next()
872 }
873
874 pub fn get_next_namespace_id(&self) -> u64 {
875 self.next_namespace_id.next()
876 }
877}
878
879impl CurrentTask {
880 pub fn create_filesystem(
881 &self,
882 fs_type: &FsStr,
883 options: FileSystemOptions,
884 ) -> Result<FileSystemHandle, Errno> {
885 self.kernel()
892 .expando
893 .get::<FsRegistry>()
894 .create(self, fs_type, options)
895 .ok_or_else(|| errno!(ENODEV, fs_type))?
896 }
897}
898
899struct ProcMountsFileSource(Weak<Task>);
900
901impl DynamicFileSource for ProcMountsFileSource {
902 fn generate(
903 &self,
904 _current_task: &CurrentTask,
905 sink: &mut DynamicFileBuf,
906 ) -> Result<(), Errno> {
907 let task = Task::from_weak(&self.0)?;
912 let task_fs = task.running_state()?.fs.read();
913 let root = task_fs.root();
914 let ns = task_fs.namespace();
915 for_each_mount(&ns.root_mount, &mut |mount| {
916 let mountpoint = mount.mountpoint().unwrap_or_else(|| mount.root());
917 if !mountpoint.is_descendant_of(&root) {
918 return Ok(());
919 }
920 write!(
921 sink,
922 "{} {} {} {}{}",
923 mount.fs.options.source_for_display(),
924 mountpoint.path(&task_fs),
925 mount.fs.name(),
926 mount.flags(),
929 security::sb_show_options(&task.kernel(), &mount.fs)?,
930 )?;
931 writeln!(sink, " 0 0")?;
932 Ok(())
933 })?;
934 Ok(())
935 }
936}
937
938pub struct ProcMountsFile {
939 dynamic_file: DynamicFile<ProcMountsFileSource>,
940}
941
942impl ProcMountsFile {
943 pub fn new_node(task: Weak<Task>) -> impl FsNodeOps {
944 SimpleFileNode::new(move |_| {
945 Ok(Self { dynamic_file: DynamicFile::new(ProcMountsFileSource(task.clone())) })
946 })
947 }
948}
949
950impl FileOps for ProcMountsFile {
951 fileops_impl_delegate_read_write_and_seek!(self, self.dynamic_file);
952 fileops_impl_noop_sync!();
953
954 fn wait_async(
955 &self,
956 _file: &FileObject,
957 _current_task: &CurrentTask,
958 waiter: &Waiter,
959 _events: FdEvents,
960 _handler: EventHandler,
961 ) -> Option<WaitCanceler> {
962 Some(waiter.fake_wait())
965 }
966
967 fn query_events(
968 &self,
969 _file: &FileObject,
970 _current_task: &CurrentTask,
971 ) -> Result<FdEvents, Errno> {
972 Ok(FdEvents::empty())
973 }
974}
975
976#[derive(Clone)]
977pub struct ProcMountinfoFile(Weak<Task>);
978impl ProcMountinfoFile {
979 pub fn new_node(task: Weak<Task>) -> impl FsNodeOps {
980 DynamicFile::new_node(Self(task))
981 }
982}
983impl DynamicFileSource for ProcMountinfoFile {
984 fn generate(
985 &self,
986 _current_task: &CurrentTask,
987 sink: &mut DynamicFileBuf,
988 ) -> Result<(), Errno> {
989 fn path_from_fs_root(dir: &DirEntryHandle) -> FsString {
991 let mut path = PathBuilder::new();
992 if dir.is_dead() {
993 path.prepend_element("/deleted".into());
995 }
996 let scope = RcuReadScope::new();
997 let mut current = dir.deref();
998 while let Some(parent) = current.parent_ref(&scope) {
999 path.prepend_element(current.local_name(&scope));
1000 current = parent;
1001 }
1002 path.build_absolute()
1003 }
1004
1005 let task = Task::from_weak(&self.0)?;
1010 let task_fs = task.running_state()?.fs.read();
1011 let root = task_fs.root();
1012 let ns = task_fs.namespace();
1013 for_each_mount(&ns.root_mount, &mut |mount| {
1014 let mountpoint = mount.mountpoint().unwrap_or_else(|| mount.root());
1015 if !mountpoint.is_descendant_of(&root) {
1016 return Ok(());
1017 }
1018 let parent = mountpoint.mount.as_ref().unwrap();
1020 write!(
1021 sink,
1022 "{} {} {} {} {} {}",
1023 mount.id,
1024 parent.id,
1025 mount.root.node.fs().dev_id,
1026 path_from_fs_root(&mount.root),
1027 mountpoint.path(&task_fs),
1028 mount.mount_flags(),
1029 )?;
1030 if let Some(peer_group) = mount.peer_group() {
1031 write!(sink, " shared:{}", peer_group.id)?;
1032 }
1033 if let Some(upstream) = mount.upstream() {
1034 write!(sink, " master:{}", upstream.id)?;
1035 }
1036 writeln!(
1037 sink,
1038 " - {} {} {}{}",
1039 mount.fs.name(),
1040 mount.fs.options.source_for_display(),
1041 mount.fs_flags(),
1042 security::sb_show_options(&task.kernel(), &mount.fs)?
1044 )?;
1045 Ok(())
1046 })?;
1047 Ok(())
1048 }
1049}
1050
1051fn for_each_mount<E>(
1052 mount: &MountHandle,
1053 callback: &mut impl FnMut(&MountHandle) -> Result<(), E>,
1054) -> Result<(), E> {
1055 callback(mount)?;
1056 for (_, s) in mount.relations.iter_submounts(&RcuReadScope::new()) {
1057 for_each_mount(&s.mount, callback)?;
1058 }
1059 Ok(())
1060}
1061
1062#[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
1064pub enum SymlinkMode {
1065 #[default]
1067 Follow,
1068
1069 NoFollow,
1071}
1072
1073pub const MAX_SYMLINK_FOLLOWS: u8 = 40;
1075
1076pub struct LookupContext {
1081 pub symlink_mode: SymlinkMode,
1086
1087 pub remaining_follows: u8,
1091
1092 pub must_be_directory: bool,
1098
1099 pub resolve_flags: ResolveFlags,
1101
1102 pub resolve_base: ResolveBase,
1105}
1106
1107#[derive(Clone, Eq, PartialEq)]
1110pub enum ResolveBase {
1111 None,
1112
1113 Beneath(NamespaceNode),
1115
1116 InRoot(NamespaceNode),
1118}
1119
1120impl LookupContext {
1121 pub fn new(symlink_mode: SymlinkMode) -> LookupContext {
1122 LookupContext {
1123 symlink_mode,
1124 remaining_follows: MAX_SYMLINK_FOLLOWS,
1125 must_be_directory: false,
1126 resolve_flags: ResolveFlags::empty(),
1127 resolve_base: ResolveBase::None,
1128 }
1129 }
1130
1131 pub fn with(&self, symlink_mode: SymlinkMode) -> LookupContext {
1132 LookupContext { symlink_mode, resolve_base: self.resolve_base.clone(), ..*self }
1133 }
1134
1135 pub fn update_for_path(&mut self, path: &FsStr) {
1136 if path.last() == Some(&b'/') {
1137 self.must_be_directory = true;
1140 self.symlink_mode = SymlinkMode::Follow;
1143 }
1144 }
1145}
1146
1147impl Default for LookupContext {
1148 fn default() -> Self {
1149 LookupContext::new(SymlinkMode::Follow)
1150 }
1151}
1152
1153pub enum PathWithReachability {
1155 Reachable(FsString),
1157
1158 Unreachable(FsString),
1160}
1161
1162impl PathWithReachability {
1163 pub fn into_path(self) -> FsString {
1164 match self {
1165 PathWithReachability::Reachable(path) => path,
1166 PathWithReachability::Unreachable(path) => path,
1167 }
1168 }
1169}
1170
1171#[derive(Clone)]
1179pub struct NamespaceNode {
1180 pub mount: MountInfo,
1185
1186 pub entry: DirEntryHandle,
1188}
1189
1190impl NamespaceNode {
1191 pub fn new(mount: MountHandle, entry: DirEntryHandle) -> Self {
1192 Self { mount: Some(mount).into(), entry }
1193 }
1194
1195 pub fn new_anonymous(entry: DirEntryHandle) -> Self {
1197 Self { mount: None.into(), entry }
1198 }
1199
1200 pub fn new_anonymous_unrooted(current_task: &CurrentTask, node: FsNodeHandle) -> Self {
1203 let dir_entry = DirEntry::new_unrooted(node);
1204 let _ = security::fs_node_init_with_dentry_no_xattr(current_task, &dir_entry);
1205 Self::new_anonymous(dir_entry)
1206 }
1207
1208 pub fn open(
1214 &self,
1215 current_task: &CurrentTask,
1216 flags: OpenFlags,
1217 access_check: AccessCheck,
1218 ) -> Result<FileHandle, Errno> {
1219 let ops = self.entry.node.open(current_task, self, flags, access_check)?;
1220 FileObject::new(current_task, ops, self.clone(), flags)
1221 }
1222
1223 pub fn open_create_node(
1229 &self,
1230 current_task: &CurrentTask,
1231 name: &FsStr,
1232 mode: FileMode,
1233 dev: DeviceId,
1234 flags: OpenFlags,
1235 ) -> Result<NamespaceNode, Errno> {
1236 let owner = current_task.current_fscred();
1237 let mode = current_task.fs().apply_umask(mode);
1238 let create_fn = |dir: &FsNodeHandle, mount: &MountInfo, name: &_| {
1239 dir.create_node(current_task, mount, name, mode, dev, owner)
1240 };
1241 let entry = if flags.contains(OpenFlags::EXCL) {
1242 self.entry.create_entry(current_task, &self.mount, name, create_fn)
1243 } else {
1244 self.entry.get_or_create_entry(current_task, &self.mount, name, create_fn)
1245 }?;
1246 Ok(self.with_new_entry(entry))
1247 }
1248
1249 pub fn into_active(self) -> ActiveNamespaceNode {
1250 ActiveNamespaceNode::new(self)
1251 }
1252
1253 pub fn into_mapping(self, mode: Option<FileWriteGuardMode>) -> Result<Arc<FileMapping>, Errno> {
1254 self.into_active().into_mapping(mode)
1255 }
1256
1257 pub fn create_node(
1263 &self,
1264 current_task: &CurrentTask,
1265 name: &FsStr,
1266 mode: FileMode,
1267 dev: DeviceId,
1268 ) -> Result<NamespaceNode, Errno> {
1269 let owner = current_task.current_fscred();
1270 let mode = current_task.fs().apply_umask(mode);
1271 let entry =
1272 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1273 dir.create_node(current_task, mount, name, mode, dev, owner)
1274 })?;
1275 Ok(self.with_new_entry(entry))
1276 }
1277
1278 pub fn create_symlink(
1282 &self,
1283 current_task: &CurrentTask,
1284 name: &FsStr,
1285 target: &FsStr,
1286 ) -> Result<NamespaceNode, Errno> {
1287 let owner = current_task.current_fscred();
1288 let entry =
1289 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1290 dir.create_symlink(current_task, mount, name, target, owner)
1291 })?;
1292 Ok(self.with_new_entry(entry))
1293 }
1294
1295 pub fn create_tmpfile(
1301 &self,
1302 current_task: &CurrentTask,
1303 mode: FileMode,
1304 flags: OpenFlags,
1305 ) -> Result<NamespaceNode, Errno> {
1306 let owner = current_task.current_fscred();
1307 let mode = current_task.fs().apply_umask(mode);
1308 Ok(self.with_new_entry(self.entry.create_tmpfile(
1309 current_task,
1310 &self.mount,
1311 mode,
1312 owner,
1313 flags,
1314 )?))
1315 }
1316
1317 pub fn link(
1318 &self,
1319 current_task: &CurrentTask,
1320 name: &FsStr,
1321 child: &FsNodeHandle,
1322 ) -> Result<NamespaceNode, Errno> {
1323 let dir_entry =
1324 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1325 dir.link(current_task, mount, name, child)
1326 })?;
1327 Ok(self.with_new_entry(dir_entry))
1328 }
1329
1330 pub fn bind_socket(
1331 &self,
1332 current_task: &CurrentTask,
1333 name: &FsStr,
1334 socket: SocketHandle,
1335 socket_address: SocketAddress,
1336 mode: FileMode,
1337 ) -> Result<NamespaceNode, Errno> {
1338 let dir_entry =
1339 self.entry.create_entry(current_task, &self.mount, name, |dir, mount, name| {
1340 let node = dir.create_node(
1341 current_task,
1342 mount,
1343 name,
1344 mode,
1345 DeviceId::NONE,
1346 current_task.current_fscred(),
1347 )?;
1348 if let Some(unix_socket) = socket.downcast_socket::<UnixSocket>() {
1349 unix_socket.bind_socket_to_node(&socket, socket_address, &node)?;
1350 } else {
1351 return error!(ENOTSUP);
1352 }
1353 Ok(node)
1354 })?;
1355 Ok(self.with_new_entry(dir_entry))
1356 }
1357
1358 pub fn unlink(
1359 &self,
1360 current_task: &CurrentTask,
1361 name: &FsStr,
1362 kind: UnlinkKind,
1363 must_be_directory: bool,
1364 ) -> Result<(), Errno> {
1365 if DirEntry::is_reserved_name(name) {
1366 match kind {
1367 UnlinkKind::Directory => {
1368 if name == ".." {
1369 error!(ENOTEMPTY)
1370 } else if self.parent().is_none() {
1371 error!(EBUSY)
1373 } else {
1374 error!(EINVAL)
1375 }
1376 }
1377 UnlinkKind::NonDirectory => error!(ENOTDIR),
1378 }
1379 } else {
1380 self.entry.unlink(current_task, &self.mount, name, kind, must_be_directory)
1381 }
1382 }
1383
1384 fn resolve(
1388 self,
1389 current_task: &CurrentTask,
1390 context: &mut LookupContext,
1391 ) -> Result<NamespaceNode, Errno> {
1392 let mut node = self;
1393
1394 loop {
1395 if !node.entry.node.is_lnk() || context.symlink_mode == SymlinkMode::NoFollow {
1396 break;
1397 }
1398 if context.remaining_follows == 0
1399 || context.resolve_flags.contains(ResolveFlags::NO_SYMLINKS)
1400 {
1401 return error!(ELOOP);
1402 }
1403 context.remaining_follows -= 1;
1404 node = match node.readlink(current_task)? {
1405 SymlinkTarget::Path(link_target) => {
1406 let link_directory = if link_target[0] == b'/' {
1407 match &context.resolve_base {
1409 ResolveBase::None => current_task.fs().root(),
1410 ResolveBase::Beneath(_) => return error!(EXDEV),
1411 ResolveBase::InRoot(root) => root.clone(),
1412 }
1413 } else {
1414 node.parent().unwrap_or(node)
1418 };
1419 current_task.lookup_path(context, link_directory, link_target.as_ref())?
1420 }
1421 SymlinkTarget::Node(node) => {
1422 if context.resolve_flags.contains(ResolveFlags::NO_MAGICLINKS) {
1423 return error!(ELOOP);
1424 }
1425 node
1426 }
1427 };
1428 }
1429 Ok(node.enter_mount())
1430 }
1431
1432 pub fn lookup_child(
1434 &self,
1435 current_task: &CurrentTask,
1436 context: &mut LookupContext,
1437 basename: &FsStr,
1438 ) -> Result<NamespaceNode, Errno> {
1439 self.lookup_children(current_task, context, &[basename])
1440 }
1441
1442 pub fn lookup_children(
1444 &self,
1445 current_task: &CurrentTask,
1446 context: &mut LookupContext,
1447 mut basenames: &[&FsStr],
1448 ) -> Result<NamespaceNode, Errno> {
1449 for name in basenames {
1450 if name.len() > NAME_MAX as usize {
1451 return error!(ENAMETOOLONG);
1452 }
1453 }
1454
1455 let mut current_namespace_node = self.clone();
1456
1457 while basenames.len() > 0 {
1458 if !current_namespace_node.entry.node.is_dir() {
1459 return error!(ENOTDIR);
1460 }
1461
1462 let basename = basenames[0];
1463 if basename.is_empty() || basename == "." {
1464 basenames = &basenames[1..];
1465 continue;
1466 }
1467 if basename == ".." {
1468 let root = match &context.resolve_base {
1469 ResolveBase::None => current_task.fs().root(),
1470 ResolveBase::Beneath(node) => {
1471 if current_namespace_node == *node {
1473 return error!(EXDEV);
1474 }
1475 current_task.fs().root()
1476 }
1477 ResolveBase::InRoot(root) => root.clone(),
1478 };
1479
1480 if current_namespace_node != root {
1482 current_namespace_node =
1483 current_namespace_node.parent().unwrap_or(current_namespace_node)
1484 }
1485 if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1486 && current_namespace_node.mount != self.mount
1487 {
1488 return error!(EXDEV);
1489 }
1490
1491 if context.must_be_directory && !current_namespace_node.entry.node.is_dir() {
1492 return error!(ENOTDIR);
1493 }
1494 basenames = &basenames[1..];
1495 continue;
1496 }
1497 if basenames.len() == 1
1498 || !current_namespace_node.entry.node.ops().has_lookup_pipelined()
1499 {
1500 current_namespace_node = current_namespace_node.with_new_entry(
1501 current_namespace_node.entry.component_lookup(
1502 current_task,
1503 ¤t_namespace_node.mount,
1504 basename,
1505 )?,
1506 );
1507
1508 current_namespace_node = current_namespace_node.resolve(current_task, context)?;
1509
1510 if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1511 && current_namespace_node.mount != self.mount
1512 {
1513 return error!(EXDEV);
1514 }
1515
1516 if context.must_be_directory && !current_namespace_node.entry.node.is_dir() {
1517 return error!(ENOTDIR);
1518 }
1519
1520 basenames = &basenames[1..];
1521 continue;
1522 }
1523
1524 let pipelined_basenames = if let Some(pos) =
1525 basenames.iter().position(|&name| name.is_empty() || name == "." || name == "..")
1526 {
1527 &basenames[..pos]
1528 } else {
1529 basenames
1530 };
1531 let precomputed_entries = current_namespace_node.entry.get_children_pipelined(
1532 current_task,
1533 ¤t_namespace_node.mount,
1534 pipelined_basenames,
1535 );
1536 for entry in precomputed_entries {
1537 basenames = &basenames[1..];
1538 let child = current_namespace_node.with_new_entry(entry?);
1539
1540 current_namespace_node = child.clone().resolve(current_task, context)?;
1541
1542 if context.resolve_flags.contains(ResolveFlags::NO_XDEV)
1543 && current_namespace_node.mount != self.mount
1544 {
1545 return error!(EXDEV);
1546 }
1547
1548 if context.must_be_directory && !current_namespace_node.entry.node.is_dir() {
1549 return error!(ENOTDIR);
1550 }
1551
1552 if current_namespace_node != child {
1553 break;
1554 }
1555 }
1556 }
1557
1558 Ok(current_namespace_node)
1559 }
1560
1561 pub fn parent(&self) -> Option<NamespaceNode> {
1567 let mountpoint_or_self = self.escape_mount();
1568 let parent = mountpoint_or_self.entry.parent()?;
1569 Some(mountpoint_or_self.with_new_entry(parent))
1570 }
1571
1572 pub fn parent_within_mount(&self) -> Option<DirEntryHandle> {
1575 if let Ok(_) = self.mount_if_root() {
1576 return None;
1577 }
1578 self.entry.parent()
1579 }
1580
1581 pub fn is_descendant_of(&self, ancestor: &NamespaceNode) -> bool {
1586 let ancestor = ancestor.escape_mount();
1587 let mut current = self.escape_mount();
1588 while current != ancestor {
1589 if let Some(parent) = current.parent() {
1590 current = parent.escape_mount();
1591 } else {
1592 return false;
1593 }
1594 }
1595 true
1596 }
1597
1598 fn enter_one_mount(&self) -> Option<NamespaceNode> {
1603 if let Some(mount) = self.mount.deref() {
1604 if let Some(submount) =
1605 mount.relations.get_submount(&RcuReadScope::new(), ArcKey::ref_cast(&self.entry))
1606 {
1607 return Some(submount.mount.root());
1608 }
1609 }
1610 None
1611 }
1612
1613 fn enter_mount(&self) -> NamespaceNode {
1618 let kernel = self.entry.node.fs().kernel.upgrade().expect("kernel");
1620 kernel.mounts_lock.read_seq(|| {
1621 let mut inner = self.clone();
1622 while let Some(inner_root) = inner.enter_one_mount() {
1623 inner = inner_root;
1624 }
1625 inner
1626 })
1627 }
1628
1629 fn enter_mount_locked(&self, _mounts_guard: &MountsWriteToken) -> NamespaceNode {
1635 let mut inner = self.clone();
1637 while let Some(inner_root) = inner.enter_one_mount() {
1638 inner = inner_root;
1639 }
1640 inner
1641 }
1642
1643 fn escape_mount(&self) -> NamespaceNode {
1648 let kernel = self.entry.node.fs().kernel.upgrade().expect("kernel");
1649 kernel.mounts_lock.read_seq(|| {
1650 let mut mountpoint_or_self = self.clone();
1651 while let Some(mountpoint) = mountpoint_or_self.mountpoint() {
1652 mountpoint_or_self = mountpoint;
1653 }
1654 mountpoint_or_self
1655 })
1656 }
1657
1658 pub fn mount_if_root(&self) -> Result<&MountHandle, Errno> {
1660 if let Some(mount) = self.mount.deref() {
1661 if Arc::ptr_eq(&self.entry, &mount.root) {
1662 return Ok(mount);
1663 }
1664 }
1665 error!(EINVAL)
1666 }
1667
1668 fn mountpoint(&self) -> Option<NamespaceNode> {
1673 self.mount_if_root().ok()?.mountpoint()
1674 }
1675
1676 pub fn path(&self, fs: &FsContext) -> FsString {
1678 self.path_from_root(Some(&fs.root())).into_path()
1679 }
1680
1681 pub fn path_escaping_chroot(&self) -> FsString {
1683 self.path_from_root(None).into_path()
1684 }
1685
1686 pub fn path_from_root(&self, root: Option<&NamespaceNode>) -> PathWithReachability {
1689 if self.mount.is_none() {
1690 return self.unrooted_path();
1691 }
1692
1693 let mut path = PathBuilder::new();
1694 let mut current = self.escape_mount();
1695 if let Some(root) = root {
1696 let scope = RcuReadScope::new();
1697 let root = root.escape_mount();
1699 while current != root {
1700 if let Some(parent) = current.parent() {
1701 path.prepend_element(current.entry.local_name(&scope));
1702 current = parent.escape_mount();
1703 } else {
1704 let mut absolute_path = path.build_absolute();
1706 if self.entry.is_dead() {
1707 absolute_path.extend_from_slice(b" (deleted)");
1708 }
1709
1710 return PathWithReachability::Unreachable(absolute_path);
1711 }
1712 }
1713 } else {
1714 let scope = RcuReadScope::new();
1716 while let Some(parent) = current.parent() {
1717 path.prepend_element(current.entry.local_name(&scope));
1718 current = parent.escape_mount();
1719 }
1720 }
1721
1722 let mut absolute_path = path.build_absolute();
1723 if self.entry.is_dead() {
1724 absolute_path.extend_from_slice(b" (deleted)");
1725 }
1726
1727 PathWithReachability::Reachable(absolute_path)
1728 }
1729
1730 fn unrooted_path(&self) -> PathWithReachability {
1731 let scope = RcuReadScope::new();
1732 let mode = self.entry.node.info().mode;
1733 let local_name = self.entry.local_name(&scope);
1734 let path = if !local_name.is_empty() {
1735 format!("anon_inode:{}", local_name)
1736 } else if mode.is_sock() {
1737 format!("socket:[{}]", self.entry.node.ino)
1738 } else if mode.is_fifo() {
1739 format!("pipe:[{}]", self.entry.node.ino)
1740 } else {
1741 format!("file:[{}]", self.entry.node.ino)
1742 };
1743 PathWithReachability::Reachable(path.into())
1744 }
1745
1746 pub fn mount(&self, what: WhatToMount, flags: MountpointFlags) -> Result<(), Errno> {
1747 let target = self.enter_mount();
1748
1749 if target.mount.is_none() {
1752 return error!(ENOENT);
1753 }
1754
1755 let source_is_dir = match &what {
1756 WhatToMount::Fs(fs) => fs.root().node.is_dir(),
1757 WhatToMount::Bind(node) => node.entry.node.is_dir(),
1758 };
1759
1760 if source_is_dir != target.entry.node.is_dir() {
1763 return error!(ENOTDIR);
1764 }
1765
1766 let kernel = self.entry.node.fs().kernel.upgrade().expect("can't mount without a kernel");
1767 let mounts_guard = kernel.mounts_lock();
1768 let mountpoint = self.enter_mount_locked(&mounts_guard);
1769
1770 let mount = mountpoint.mount.as_ref().ok_or_else(|| errno!(ENOENT))?;
1771 let writeable_mount = mounts_guard.retain(mount);
1772 let writeable_entry = mounts_guard.retain(&mountpoint.entry);
1773 writeable_mount.create_submount(
1774 &mounts_guard,
1775 &writeable_entry,
1776 WhatSubmount::New(what, flags),
1777 )
1778 }
1779
1780 pub fn unmount(&self, flags: UnmountFlags) -> Result<(), Errno> {
1782 let kernel = self.entry.node.fs().kernel.upgrade().expect("can't mount without a kernel");
1783 let mounts_guard = kernel.mounts_lock();
1784
1785 let mountpoint = self.enter_mount_locked(&mounts_guard);
1786 mounts_guard.retain(&mountpoint.entry);
1787 mountpoint.mount.as_ref().map(|mount| mounts_guard.retain(mount));
1788 let mount = mounts_guard.retain(mountpoint.mount_if_root()?);
1789 mount.unmount(&mounts_guard, flags)
1790 }
1791
1792 pub fn rename(
1793 current_task: &CurrentTask,
1794 old_parent: &NamespaceNode,
1795 old_name: &FsStr,
1796 new_parent: &NamespaceNode,
1797 new_name: &FsStr,
1798 flags: RenameFlags,
1799 ) -> Result<(), Errno> {
1800 DirEntry::rename(
1801 current_task,
1802 &old_parent.entry,
1803 &old_parent.mount,
1804 old_name,
1805 &new_parent.entry,
1806 &new_parent.mount,
1807 new_name,
1808 flags,
1809 )
1810 }
1811
1812 fn with_new_entry(&self, entry: DirEntryHandle) -> NamespaceNode {
1813 Self { mount: self.mount.clone(), entry }
1814 }
1815
1816 fn mount_hash_key(&self) -> &ArcKey<DirEntry> {
1817 ArcKey::ref_cast(&self.entry)
1818 }
1819
1820 pub fn apply_suid_and_sgid(&self, creds: &mut Credentials) {
1821 if self.mount.flags().contains(MountFlags::NOSUID) {
1827 return;
1828 }
1829 self.entry.node.info().apply_suid_and_sgid(creds)
1830 }
1831
1832 pub fn update_atime(&self) {
1833 if !self.mount.flags().contains(MountFlags::NOATIME) {
1835 self.entry.node.update_info(|info| {
1836 let now = utc::utc_now();
1837 info.time_access = now;
1838 info.pending_time_access_update = true;
1839 });
1840 }
1841 }
1842
1843 pub fn readlink(&self, current_task: &CurrentTask) -> Result<SymlinkTarget, Errno> {
1844 self.update_atime();
1845 self.entry.node.readlink(current_task)
1846 }
1847
1848 pub fn notify(&self, event_mask: InotifyMask) {
1849 if self.mount.is_some() {
1850 self.entry.notify(event_mask);
1851 }
1852 }
1853
1854 pub fn check_access(
1858 &self,
1859 current_task: &CurrentTask,
1860 permission_flags: impl Into<security::PermissionFlags>,
1861 reason: CheckAccessReason,
1862 ) -> Result<(), Errno> {
1863 self.entry.node.check_access(current_task, &self.mount, permission_flags, reason, self)
1864 }
1865
1866 pub fn check_o_noatime_allowed(&self, current_task: &CurrentTask) -> Result<(), Errno> {
1868 self.entry.node.check_o_noatime_allowed(current_task)
1869 }
1870
1871 pub fn truncate(&self, current_task: &CurrentTask, length: u64) -> Result<(), Errno> {
1872 self.entry.node.truncate(current_task, &self.mount, length)?;
1873 self.entry.notify_ignoring_excl_unlink(InotifyMask::MODIFY);
1874 Ok(())
1875 }
1876}
1877
1878impl fmt::Debug for NamespaceNode {
1879 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1880 f.debug_struct("NamespaceNode")
1881 .field("path", &self.path_escaping_chroot())
1882 .field("mount", &self.mount)
1883 .field("entry", &self.entry)
1884 .finish()
1885 }
1886}
1887
1888impl PartialEq for NamespaceNode {
1890 fn eq(&self, other: &Self) -> bool {
1891 self.mount.as_ref().map(Arc::as_ptr).eq(&other.mount.as_ref().map(Arc::as_ptr))
1892 && Arc::ptr_eq(&self.entry, &other.entry)
1893 }
1894}
1895impl Eq for NamespaceNode {}
1896impl Hash for NamespaceNode {
1897 fn hash<H: Hasher>(&self, state: &mut H) {
1898 self.mount.as_ref().map(Arc::as_ptr).hash(state);
1899 Arc::as_ptr(&self.entry).hash(state);
1900 }
1901}
1902
1903#[derive(Debug, Clone)]
1905pub struct ActiveNamespaceNode {
1906 name: NamespaceNode,
1908
1909 _marker: Option<MountClientMarker>,
1913}
1914
1915impl ActiveNamespaceNode {
1916 pub fn new(name: NamespaceNode) -> Self {
1917 let marker = name.mount.as_ref().map(|mount| mount.active_client_counter.clone());
1918 Self { name, _marker: marker }
1919 }
1920
1921 pub fn to_passive(&self) -> NamespaceNode {
1922 self.deref().clone()
1923 }
1924
1925 pub fn into_mapping(self, mode: Option<FileWriteGuardMode>) -> Result<Arc<FileMapping>, Errno> {
1926 if let Some(mode) = mode {
1927 self.entry.node.write_guard_state.lock().acquire(mode)?;
1928 }
1929 Ok(Arc::new(FileMapping { name: self, mode }))
1930 }
1931}
1932
1933impl Deref for ActiveNamespaceNode {
1934 type Target = NamespaceNode;
1935
1936 fn deref(&self) -> &Self::Target {
1937 &self.name
1938 }
1939}
1940
1941impl PartialEq for ActiveNamespaceNode {
1942 fn eq(&self, other: &Self) -> bool {
1943 self.deref().eq(other.deref())
1944 }
1945}
1946impl Eq for ActiveNamespaceNode {}
1947impl Hash for ActiveNamespaceNode {
1948 fn hash<H: Hasher>(&self, state: &mut H) {
1949 self.deref().hash(state)
1950 }
1951}
1952
1953#[derive(Debug, Clone, PartialEq, Eq)]
1954#[must_use]
1955pub struct FileMapping {
1956 pub name: ActiveNamespaceNode,
1957 mode: Option<FileWriteGuardMode>,
1958}
1959
1960impl Drop for FileMapping {
1961 fn drop(&mut self) {
1962 if let Some(mode) = self.mode {
1963 self.name.entry.node.write_guard_state.lock().release(mode);
1964 }
1965 }
1966}
1967
1968pub struct Mounts {
1970 mounts: RcuHashMap<WeakKey<DirEntry>, Vec<ArcKey<Mount>>>,
1971}
1972
1973impl Mounts {
1974 pub fn new() -> Self {
1975 Mounts { mounts: RcuHashMap::default() }
1976 }
1977
1978 fn register_mount(&self, dir_entry: &Arc<DirEntry>, mount: MountHandle) -> Submount {
1980 let mut mounts = self.mounts.lock();
1981 let key = WeakKey::from(dir_entry);
1982 let mut vec = mounts.get(&key).unwrap_or_else(|| {
1983 dir_entry.set_has_mounts(true);
1984 Vec::new()
1985 });
1986 vec.push(ArcKey(mount.clone()));
1987 mounts.insert(key, vec);
1988 Submount { dir: ArcKey(dir_entry.clone()), mount }
1989 }
1990
1991 fn unregister_mount(&self, dir_entry: &Arc<DirEntry>, mount: &MountHandle) {
1993 let mut mounts = self.mounts.lock();
1994 let key = WeakKey::from(dir_entry);
1995 if let Some(mut vec) = mounts.get(&key) {
1996 let index = vec.iter().position(|e| e == ArcKey::ref_cast(mount)).unwrap();
1997 if vec.len() == 1 {
1998 mounts.remove(&key);
1999 dir_entry.set_has_mounts(false);
2000 } else {
2001 vec.swap_remove(index);
2002 mounts.insert(key, vec);
2003 }
2004 }
2005 }
2006
2007 pub fn unmount(&self, dir_entry: &DirEntry) {
2011 let mounts = self.mounts.lock().remove(&PtrKey::from(dir_entry as *const _));
2012 if let Some(mounts) = mounts {
2013 if let Some(kernel) = mounts.get(0).map(|m| m.kernel()) {
2014 let mounts_guard = kernel.mounts_lock();
2015 let mounts = scopeguard::guard(mounts, |mounts| mounts_guard.defer_drop(mounts));
2016 for mount in &*mounts {
2017 let _ = mount.unmount(&mounts_guard, UnmountFlags::DETACH);
2019 }
2020 }
2021 }
2022 }
2023
2024 pub fn clear(&self) {
2028 for (_dir_entry, mounts) in self.mounts.lock().drain() {
2029 for mount in mounts {
2030 mount.fs.force_unmount_ops();
2031 }
2032 }
2033 }
2034
2035 pub fn sync_all(&self, current_task: &CurrentTask) -> Result<(), Errno> {
2036 let mut filesystems = Vec::new();
2037 {
2038 let scope = RcuReadScope::new();
2039 let mut seen = HashSet::new();
2040 for (_dir_entry, m_list) in self.mounts.iter(&scope) {
2041 for m in m_list {
2042 if seen.insert(Arc::as_ptr(&m.fs)) {
2043 filesystems.push(m.fs.clone());
2044 }
2045 }
2046 }
2047 }
2048
2049 for fs in filesystems {
2050 if let Err(e) = fs.sync(current_task) {
2051 log_warn!("sync failed for filesystem {:?}: {:?}", fs.name(), e);
2052 }
2053 }
2054 Ok(())
2055 }
2056}
2057
2058impl Drop for Mount {
2059 fn drop(&mut self) {
2060 let kernel = self.kernel();
2063 let peer_group = self.relations.peer_group.cloned();
2064 let upstream = self.relations.upstream.cloned();
2065 self.relations.peer_group.update(None);
2066 self.relations.upstream.update(None);
2067 if peer_group.is_some() || upstream.is_some() {
2068 fuchsia_rcu::rcu_drop(scopeguard::guard(
2069 (kernel, peer_group, upstream),
2070 |(kernel, peer_group, upstream)| {
2071 let guard = kernel.mounts_lock();
2072 Mount::unregister_from_peer_group_and_upstream(&guard, peer_group, upstream);
2073 },
2074 ));
2075 }
2076 }
2077}
2078
2079impl fmt::Debug for Mount {
2080 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2081 let scope = RcuReadScope::new();
2082 f.debug_struct("Mount")
2083 .field("id", &(self as *const Mount))
2084 .field("root", &self.root)
2085 .field("mountpoint", &self.relations.mountpoint(&scope))
2086 .field("submounts", &self.relations.iter_submounts(&scope).collect::<Vec<_>>())
2087 .finish()
2088 }
2089}
2090
2091#[derive(Debug)]
2093struct Submount {
2094 dir: ArcKey<DirEntry>,
2095 mount: MountHandle,
2096}
2097
2098impl Drop for Submount {
2099 fn drop(&mut self) {
2100 self.mount.kernel().mounts.unregister_mount(&self.dir, &self.mount)
2101 }
2102}
2103
2104impl Eq for Submount {}
2106impl PartialEq<Self> for Submount {
2107 fn eq(&self, other: &Self) -> bool {
2108 self.dir == other.dir
2109 }
2110}
2111impl Hash for Submount {
2112 fn hash<H: Hasher>(&self, state: &mut H) {
2113 self.dir.hash(state)
2114 }
2115}
2116
2117impl Borrow<ArcKey<DirEntry>> for Submount {
2118 fn borrow(&self) -> &ArcKey<DirEntry> {
2119 &self.dir
2120 }
2121}
2122
2123#[cfg(test)]
2124mod test {
2125 use crate::fs::tmpfs::TmpFs;
2126 use crate::testing::spawn_kernel_and_run;
2127 use crate::vfs::namespace::DeviceId;
2128 use crate::vfs::{
2129 CallbackSymlinkNode, FsNodeInfo, LookupContext, MountInfo, Namespace, NamespaceNode,
2130 RenameFlags, SymlinkMode, SymlinkTarget, UnlinkKind, WhatToMount,
2131 };
2132 use starnix_uapi::mount_flags::MountpointFlags;
2133 use starnix_uapi::{errno, mode};
2134 use std::sync::Arc;
2135
2136 #[::fuchsia::test]
2137 async fn test_namespace() {
2138 spawn_kernel_and_run(async |current_task| {
2139 let kernel = current_task.kernel();
2140 let root_fs = TmpFs::new_fs(&kernel);
2141 let root_node = Arc::clone(root_fs.root());
2142 let _dev_node =
2143 root_node.create_dir(¤t_task, "dev".into()).expect("failed to mkdir dev");
2144 let dev_fs = TmpFs::new_fs(&kernel);
2145 let dev_root_node = Arc::clone(dev_fs.root());
2146 let _dev_pts_node =
2147 dev_root_node.create_dir(¤t_task, "pts".into()).expect("failed to mkdir pts");
2148
2149 let ns = Namespace::new(root_fs);
2150 let mut context = LookupContext::default();
2151 let dev = ns
2152 .root()
2153 .lookup_child(¤t_task, &mut context, "dev".into())
2154 .expect("failed to lookup dev");
2155 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2156 .expect("failed to mount dev root node");
2157
2158 let mut context = LookupContext::default();
2159 let dev = ns
2160 .root()
2161 .lookup_child(¤t_task, &mut context, "dev".into())
2162 .expect("failed to lookup dev");
2163 let mut context = LookupContext::default();
2164 let pts = dev
2165 .lookup_child(¤t_task, &mut context, "pts".into())
2166 .expect("failed to lookup pts");
2167 let pts_parent =
2168 pts.parent().ok_or_else(|| errno!(ENOENT)).expect("failed to get parent of pts");
2169 assert!(Arc::ptr_eq(&pts_parent.entry, &dev.entry));
2170
2171 let dev_parent =
2172 dev.parent().ok_or_else(|| errno!(ENOENT)).expect("failed to get parent of dev");
2173 assert!(Arc::ptr_eq(&dev_parent.entry, &ns.root().entry));
2174 })
2175 .await;
2176 }
2177
2178 #[::fuchsia::test]
2179 async fn test_mount_does_not_upgrade() {
2180 spawn_kernel_and_run(async |current_task| {
2181 let kernel = current_task.kernel();
2182 let root_fs = TmpFs::new_fs(&kernel);
2183 let root_node = Arc::clone(root_fs.root());
2184 let _dev_node =
2185 root_node.create_dir(¤t_task, "dev".into()).expect("failed to mkdir dev");
2186 let dev_fs = TmpFs::new_fs(&kernel);
2187 let dev_root_node = Arc::clone(dev_fs.root());
2188 let _dev_pts_node =
2189 dev_root_node.create_dir(¤t_task, "pts".into()).expect("failed to mkdir pts");
2190
2191 let ns = Namespace::new(root_fs);
2192 let mut context = LookupContext::default();
2193 let dev = ns
2194 .root()
2195 .lookup_child(¤t_task, &mut context, "dev".into())
2196 .expect("failed to lookup dev");
2197 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2198 .expect("failed to mount dev root node");
2199 let mut context = LookupContext::default();
2200 let new_dev = ns
2201 .root()
2202 .lookup_child(¤t_task, &mut context, "dev".into())
2203 .expect("failed to lookup dev again");
2204 assert!(!Arc::ptr_eq(&dev.entry, &new_dev.entry));
2205 assert_ne!(&dev, &new_dev);
2206
2207 let mut context = LookupContext::default();
2208 let _new_pts = new_dev
2209 .lookup_child(¤t_task, &mut context, "pts".into())
2210 .expect("failed to lookup pts");
2211 let mut context = LookupContext::default();
2212 assert!(dev.lookup_child(¤t_task, &mut context, "pts".into()).is_err());
2213 })
2214 .await;
2215 }
2216
2217 #[::fuchsia::test]
2218 async fn test_path() {
2219 spawn_kernel_and_run(async |current_task| {
2220 let kernel = current_task.kernel();
2221 let root_fs = TmpFs::new_fs(&kernel);
2222 let root_node = Arc::clone(root_fs.root());
2223 let _dev_node =
2224 root_node.create_dir(¤t_task, "dev".into()).expect("failed to mkdir dev");
2225 let dev_fs = TmpFs::new_fs(&kernel);
2226 let dev_root_node = Arc::clone(dev_fs.root());
2227 let _dev_pts_node =
2228 dev_root_node.create_dir(¤t_task, "pts".into()).expect("failed to mkdir pts");
2229
2230 let ns = Namespace::new(root_fs);
2231 let mut context = LookupContext::default();
2232 let dev = ns
2233 .root()
2234 .lookup_child(¤t_task, &mut context, "dev".into())
2235 .expect("failed to lookup dev");
2236 dev.mount(WhatToMount::Fs(dev_fs), MountpointFlags::empty())
2237 .expect("failed to mount dev root node");
2238
2239 let mut context = LookupContext::default();
2240 let dev = ns
2241 .root()
2242 .lookup_child(¤t_task, &mut context, "dev".into())
2243 .expect("failed to lookup dev");
2244 let mut context = LookupContext::default();
2245 let pts = dev
2246 .lookup_child(¤t_task, &mut context, "pts".into())
2247 .expect("failed to lookup pts");
2248
2249 assert_eq!("/", ns.root().path_escaping_chroot());
2250 assert_eq!("/dev", dev.path_escaping_chroot());
2251 assert_eq!("/dev/pts", pts.path_escaping_chroot());
2252 })
2253 .await;
2254 }
2255
2256 #[::fuchsia::test]
2257 async fn test_shadowing() {
2258 spawn_kernel_and_run(async |current_task| {
2259 let kernel = current_task.kernel();
2260 let root_fs = TmpFs::new_fs(&kernel);
2261 let ns = Namespace::new(root_fs.clone());
2262 let _foo_node = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2263 let mut context = LookupContext::default();
2264 let foo_dir =
2265 ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2266
2267 let foofs1 = TmpFs::new_fs(&kernel);
2268 foo_dir.mount(WhatToMount::Fs(foofs1.clone()), MountpointFlags::empty()).unwrap();
2269 let mut context = LookupContext::default();
2270 assert!(Arc::ptr_eq(
2271 &ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap().entry,
2272 foofs1.root()
2273 ));
2274 let foo_dir =
2275 ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2276
2277 let ns_clone = ns.clone_namespace(&kernel.mounts_lock());
2278
2279 let foofs2 = TmpFs::new_fs(&kernel);
2280 foo_dir.mount(WhatToMount::Fs(foofs2.clone()), MountpointFlags::empty()).unwrap();
2281 let mut context = LookupContext::default();
2282 assert!(Arc::ptr_eq(
2283 &ns.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap().entry,
2284 foofs2.root()
2285 ));
2286
2287 assert!(Arc::ptr_eq(
2288 &ns_clone
2289 .root()
2290 .lookup_child(¤t_task, &mut LookupContext::default(), "foo".into())
2291 .unwrap()
2292 .entry,
2293 foofs1.root()
2294 ));
2295 })
2296 .await;
2297 }
2298
2299 #[::fuchsia::test]
2300 async fn test_unlink_mounted_directory() {
2301 spawn_kernel_and_run(async |current_task| {
2302 let kernel = current_task.kernel();
2303 let root_fs = TmpFs::new_fs(&kernel);
2304 let ns1 = Namespace::new(root_fs.clone());
2305 let ns2 = Namespace::new(root_fs.clone());
2306 let _foo_node = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2307 let mut context = LookupContext::default();
2308 let foo_dir =
2309 ns1.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2310
2311 let foofs = TmpFs::new_fs(&kernel);
2312 foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2313
2314 assert_eq!(
2316 ns1.root()
2317 .unlink(¤t_task, "foo".into(), UnlinkKind::Directory, false)
2318 .unwrap_err(),
2319 errno!(EBUSY),
2320 );
2321
2322 ns2.root()
2324 .unlink(¤t_task, "foo".into(), UnlinkKind::Directory, false)
2325 .expect("unlink failed");
2326
2327 assert_eq!(
2329 ns1.root()
2330 .unlink(¤t_task, "foo".into(), UnlinkKind::Directory, false)
2331 .unwrap_err(),
2332 errno!(ENOENT),
2333 );
2334 })
2335 .await;
2336 }
2337
2338 #[::fuchsia::test]
2339 async fn test_rename_mounted_directory() {
2340 spawn_kernel_and_run(async |current_task| {
2341 let kernel = current_task.kernel();
2342 let root_fs = TmpFs::new_fs(&kernel);
2343 let ns1 = Namespace::new(root_fs.clone());
2344 let ns2 = Namespace::new(root_fs.clone());
2345 let _foo_node = root_fs.root().create_dir(¤t_task, "foo".into()).unwrap();
2346 let _bar_node = root_fs.root().create_dir(¤t_task, "bar".into()).unwrap();
2347 let _baz_node = root_fs.root().create_dir(¤t_task, "baz".into()).unwrap();
2348 let mut context = LookupContext::default();
2349 let foo_dir =
2350 ns1.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap();
2351
2352 let foofs = TmpFs::new_fs(&kernel);
2353 foo_dir.mount(WhatToMount::Fs(foofs), MountpointFlags::empty()).unwrap();
2354
2355 let root = ns1.root();
2357 assert_eq!(
2358 NamespaceNode::rename(
2359 ¤t_task,
2360 &root,
2361 "bar".into(),
2362 &root,
2363 "foo".into(),
2364 RenameFlags::empty()
2365 )
2366 .unwrap_err(),
2367 errno!(EBUSY),
2368 );
2369 assert_eq!(
2371 NamespaceNode::rename(
2372 ¤t_task,
2373 &root,
2374 "foo".into(),
2375 &root,
2376 "bar".into(),
2377 RenameFlags::empty()
2378 )
2379 .unwrap_err(),
2380 errno!(EBUSY),
2381 );
2382
2383 let root = ns2.root();
2385
2386 NamespaceNode::rename(
2388 ¤t_task,
2389 &root,
2390 "foo".into(),
2391 &root,
2392 "bar".into(),
2393 RenameFlags::empty(),
2394 )
2395 .expect("rename failed");
2396
2397 NamespaceNode::rename(
2399 ¤t_task,
2400 &root,
2401 "baz".into(),
2402 &root,
2403 "bar".into(),
2404 RenameFlags::empty(),
2405 )
2406 .expect("rename failed");
2407
2408 assert_eq!(
2410 ns1.root().lookup_child(¤t_task, &mut context, "foo".into()).unwrap_err(),
2411 errno!(ENOENT)
2412 );
2413 assert_eq!(
2414 ns1.root().lookup_child(¤t_task, &mut context, "baz".into()).unwrap_err(),
2415 errno!(ENOENT)
2416 );
2417 })
2418 .await;
2419 }
2420
2421 #[::fuchsia::test]
2424 async fn test_lookup_with_symlink_chain() {
2425 spawn_kernel_and_run(async |current_task| {
2426 let kernel = current_task.kernel();
2428 let root_fs = TmpFs::new_fs(&kernel);
2429 let root_node = Arc::clone(root_fs.root());
2430 let _first_subdir_node = root_node
2431 .create_dir(¤t_task, "first_subdir".into())
2432 .expect("failed to mkdir dev");
2433 let _second_subdir_node = root_node
2434 .create_dir(¤t_task, "second_subdir".into())
2435 .expect("failed to mkdir dev");
2436
2437 let first_subdir_fs = TmpFs::new_fs(&kernel);
2439 let second_subdir_fs = TmpFs::new_fs(&kernel);
2440
2441 let ns = Namespace::new(root_fs);
2442 let mut context = LookupContext::default();
2443 let first_subdir = ns
2444 .root()
2445 .lookup_child(¤t_task, &mut context, "first_subdir".into())
2446 .expect("failed to lookup first_subdir");
2447 first_subdir
2448 .mount(WhatToMount::Fs(first_subdir_fs), MountpointFlags::empty())
2449 .expect("failed to mount first_subdir fs node");
2450 let second_subdir = ns
2451 .root()
2452 .lookup_child(¤t_task, &mut context, "second_subdir".into())
2453 .expect("failed to lookup second_subdir");
2454 second_subdir
2455 .mount(WhatToMount::Fs(second_subdir_fs), MountpointFlags::empty())
2456 .expect("failed to mount second_subdir fs node");
2457
2458 let real_file_node = first_subdir
2467 .create_node(¤t_task, "real_file".into(), mode!(IFREG, 0o777), DeviceId::NONE)
2468 .expect("failed to create real_file");
2469 first_subdir
2470 .create_symlink(¤t_task, "path_symlink".into(), "real_file".into())
2471 .expect("failed to create path_symlink");
2472
2473 let mut no_follow_lookup_context = LookupContext::new(SymlinkMode::NoFollow);
2474 let path_symlink_node = first_subdir
2475 .lookup_child(¤t_task, &mut no_follow_lookup_context, "path_symlink".into())
2476 .expect("Failed to lookup path_symlink");
2477
2478 let node_symlink_node = second_subdir.entry.node.fs().create_node_and_allocate_node_id(
2482 CallbackSymlinkNode::new(move || {
2483 let node = path_symlink_node.clone();
2484 Ok(SymlinkTarget::Node(node))
2485 }),
2486 FsNodeInfo::new(mode!(IFLNK, 0o777), current_task.current_fscred()),
2487 );
2488 second_subdir
2489 .entry
2490 .create_entry(
2491 ¤t_task,
2492 &MountInfo::detached(),
2493 "node_symlink".into(),
2494 move |_dir, _mount, _name| Ok(node_symlink_node),
2495 )
2496 .expect("failed to create node_symlink entry");
2497
2498 let mut follow_lookup_context = LookupContext::new(SymlinkMode::Follow);
2500 let node_symlink_resolution = second_subdir
2501 .lookup_child(¤t_task, &mut follow_lookup_context, "node_symlink".into())
2502 .expect("lookup with symlink chain failed");
2503
2504 assert!(node_symlink_resolution.entry.node.ino == real_file_node.entry.node.ino);
2506 })
2507 .await;
2508 }
2509}