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