1use crate::mm::barrier::{BarrierType, system_barrier};
6use crate::mm::mapping::MappingBackingMemory;
7use crate::mm::memory::MemoryObject;
8use crate::mm::private_anonymous_memory_manager::PrivateAnonymousMemoryManager;
9use crate::mm::{
10 FaultRegisterMode, FutexTable, InflightVmsplicedPayloads, MapInfoCache, Mapping,
11 MappingBacking, MappingFlags, MappingMode, MappingName, MappingNameRef, MlockPinFlavor,
12 PrivateFutexKey, ProtectionFlags, UserFault, VMEX_RESOURCE, VmsplicePayload,
13 VmsplicePayloadSegment, read_to_array,
14};
15use crate::security;
16use crate::signals::{SignalDetail, SignalInfo};
17use crate::task::{CurrentTask, ExceptionResult, PageFaultExceptionReport, Task};
18use crate::vfs::aio::AioContext;
19use crate::vfs::pseudo::dynamic_file::{
20 DynamicFile, DynamicFileBuf, DynamicFileSource, SequenceFileSource,
21};
22use crate::vfs::{FsString, NamespaceNode};
23use anyhow::{Error, anyhow};
24use bitflags::bitflags;
25use flyweights::FlyByteStr;
26use linux_uapi::BUS_ADRERR;
27use memory_pinning::PinnedMapping;
28use range_map::RangeMap;
29use smallvec::SmallVec;
30use starnix_ext::map_ext::EntryExt;
31use starnix_lifecycle::DropNotifier;
32use starnix_logging::{CATEGORY_STARNIX_MM, impossible_error, log_error, log_warn, track_stub};
33use starnix_sync::{LockDepMutex, MmDumpable, RwLock, RwLockWriteGuard, ordered_write_lock};
34use starnix_types::arch::ArchWidth;
35use starnix_types::futex_address::FutexAddress;
36use starnix_types::math::{round_down_to_system_page_size, round_up_to_system_page_size};
37use starnix_types::user_buffer::{UserBuffer, UserBuffers};
38use starnix_uapi::auth::CAP_IPC_LOCK;
39use starnix_uapi::errors::Errno;
40use starnix_uapi::file_mode::Access;
41use starnix_uapi::range_ext::RangeExt;
42use starnix_uapi::resource_limits::Resource;
43use starnix_uapi::restricted_aspace::{
44 RESTRICTED_ASPACE_BASE, RESTRICTED_ASPACE_HIGHEST_ADDRESS, RESTRICTED_ASPACE_RANGE,
45 RESTRICTED_ASPACE_SIZE,
46};
47use starnix_uapi::signals::{SIGBUS, SIGSEGV};
48use starnix_uapi::user_address::{ArchSpecific, UserAddress};
49use starnix_uapi::{
50 MADV_COLD, MADV_COLLAPSE, MADV_DODUMP, MADV_DOFORK, MADV_DONTDUMP, MADV_DONTFORK,
51 MADV_DONTNEED, MADV_DONTNEED_LOCKED, MADV_FREE, MADV_HUGEPAGE, MADV_HWPOISON, MADV_KEEPONFORK,
52 MADV_MERGEABLE, MADV_NOHUGEPAGE, MADV_NORMAL, MADV_PAGEOUT, MADV_POPULATE_READ, MADV_RANDOM,
53 MADV_REMOVE, MADV_SEQUENTIAL, MADV_SOFT_OFFLINE, MADV_UNMERGEABLE, MADV_WILLNEED,
54 MADV_WIPEONFORK, MREMAP_DONTUNMAP, MREMAP_FIXED, MREMAP_MAYMOVE, errno, error,
55 from_status_like_fdio,
56};
57use std::collections::HashMap;
58use std::mem::MaybeUninit;
59use std::ops::{ControlFlow, Deref, DerefMut, Range, RangeBounds};
60use std::sync::{Arc, LazyLock, Weak};
61use syncio::zxio::zxio_default_maybe_faultable_copy;
62use zerocopy::IntoBytes;
63use zx::{Rights, VmoChildOptions};
64
65pub const ZX_VM_SPECIFIC_OVERWRITE: zx::VmarFlags =
66 zx::VmarFlags::from_bits_retain(zx::VmarFlagsExtended::SPECIFIC_OVERWRITE.bits());
67
68pub(crate) const UNIFIED_ASPACES_ENABLED: bool = cfg!(not(test));
70
71pub fn init_usercopy() {
78 let _ = usercopy();
80}
81
82thread_local! {
83 static LAST_SEEN_MAPPING_GENERATION: std::cell::Cell<u64> = const { std::cell::Cell::new(0) };
86}
87
88pub const GUARD_PAGE_COUNT_FOR_GROWSDOWN_MAPPINGS: usize = 256;
89
90#[cfg(target_arch = "x86_64")]
91const ASLR_RANDOM_BITS: usize = 27;
92
93#[cfg(target_arch = "aarch64")]
94const ASLR_RANDOM_BITS: usize = 28;
95
96#[cfg(target_arch = "riscv64")]
97const ASLR_RANDOM_BITS: usize = 18;
98
99const ASLR_32_RANDOM_BITS: usize = 8;
101
102const MAX_STACK_SIZE: usize = 512 * 1024 * 1024;
105
106const STUB_VM_RSS_HWM: usize = 2 * 1024 * 1024;
110
111fn usercopy() -> Option<&'static usercopy::Usercopy> {
112 static USERCOPY: LazyLock<Option<usercopy::Usercopy>> = LazyLock::new(|| {
113 if UNIFIED_ASPACES_ENABLED {
115 Some(usercopy::Usercopy::new(RESTRICTED_ASPACE_RANGE).unwrap())
118 } else {
119 None
120 }
121 });
122
123 LazyLock::force(&USERCOPY).as_ref()
124}
125
126#[unsafe(no_mangle)]
138pub unsafe fn zxio_maybe_faultable_copy_impl(
139 dest: *mut u8,
140 src: *const u8,
141 count: usize,
142 ret_dest: bool,
143) -> bool {
144 if let Some(usercopy) = usercopy() {
145 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
146 let ret = unsafe { usercopy.raw_hermetic_copy(dest, src, count, ret_dest) };
147 ret == count
148 } else {
149 #[allow(clippy::undocumented_unsafe_blocks, reason = "2024 edition migration")]
150 unsafe {
151 zxio_default_maybe_faultable_copy(dest, src, count, ret_dest)
152 }
153 }
154}
155
156pub static PAGE_SIZE: LazyLock<u64> = LazyLock::new(|| zx::system_get_page_size() as u64);
157
158bitflags! {
159 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
160 pub struct MappingOptions: u16 {
161 const SHARED = 1 << 0;
162 const ANONYMOUS = 1 << 1;
163 const LOWER_32BIT = 1 << 2;
164 const GROWSDOWN = 1 << 3;
165 const ELF_BINARY = 1 << 4;
166 const DONTFORK = 1 << 5;
167 const WIPEONFORK = 1 << 6;
168 const DONT_SPLIT = 1 << 7;
169 const DONT_EXPAND = 1 << 8;
170 const POPULATE = 1 << 9;
171 }
172}
173
174bitflags! {
175 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
176 pub struct MremapFlags: u32 {
177 const MAYMOVE = MREMAP_MAYMOVE;
178 const FIXED = MREMAP_FIXED;
179 const DONTUNMAP = MREMAP_DONTUNMAP;
180 }
181}
182
183bitflags! {
184 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
185 pub struct MsyncFlags: u32 {
186 const ASYNC = starnix_uapi::MS_ASYNC;
187 const INVALIDATE = starnix_uapi::MS_INVALIDATE;
188 const SYNC = starnix_uapi::MS_SYNC;
189 }
190}
191
192const PROGRAM_BREAK_LIMIT: u64 = 64 * 1024 * 1024;
193
194#[derive(Debug, Clone, Eq, PartialEq)]
195struct ProgramBreak {
196 base: UserAddress,
198
199 current: UserAddress,
204}
205
206#[derive(Debug, Clone, Copy, Eq, PartialEq)]
208pub enum DumpPolicy {
209 Disable,
213
214 User,
218}
219
220pub enum MembarrierType {
222 Memory, SyncCore, }
225
226#[derive(Default, Clone)]
228struct MembarrierRegistrations {
229 memory: bool,
230 sync_core: bool,
231}
232
233#[derive(Default)]
234struct Mappings {
235 map: RangeMap<UserAddress, Mapping>,
237
238 generation: u64,
242
243 total_usage: usize,
245}
246
247impl Deref for Mappings {
248 type Target = RangeMap<UserAddress, Mapping>;
249
250 fn deref(&self) -> &Self::Target {
251 &self.map
252 }
253}
254
255impl Mappings {
256 pub fn insert(&mut self, range: std::ops::Range<UserAddress>, value: Mapping) -> Vec<Mapping> {
257 self.generation = self.generation.wrapping_add(1);
258 let range_len = range.end - range.start;
259 let removed_len: usize = self
260 .map
261 .range(range.clone())
262 .map(|(r, _)| {
263 let intersection = r.intersect(&range);
264 intersection.end - intersection.start
265 })
266 .sum();
267 let removed = self.map.insert(range, value);
268 self.total_usage = self.total_usage.saturating_add(range_len).saturating_sub(removed_len);
269 removed
270 }
271
272 pub fn remove(&mut self, range: std::ops::Range<UserAddress>) -> Vec<Mapping> {
273 self.generation = self.generation.wrapping_add(1);
274 let removed_len: usize = self
275 .map
276 .range(range.clone())
277 .map(|(r, _)| {
278 let intersection = r.intersect(&range);
279 intersection.end - intersection.start
280 })
281 .sum();
282 let removed = self.map.remove(range);
283 self.total_usage = self.total_usage.saturating_sub(removed_len);
284 removed
285 }
286
287 pub fn append_non_overlapping(
288 &mut self,
289 range: std::ops::Range<UserAddress>,
290 value: Mapping,
291 ) -> bool {
292 self.generation = self.generation.wrapping_add(1);
293 let range_len = range.end - range.start;
294 if self.map.append_non_overlapping(range, value) {
295 self.total_usage = self.total_usage.saturating_add(range_len);
296 true
297 } else {
298 false
299 }
300 }
301
302 pub fn update_exact<F, E>(
303 &mut self,
304 range: &std::ops::Range<UserAddress>,
305 f: F,
306 ) -> Result<bool, E>
307 where
308 F: FnOnce(&mut Mapping) -> Result<(), E>,
309 {
310 self.generation = self.generation.wrapping_add(1);
311 self.map.update_exact(range, f)
312 }
313}
314
315pub struct MemoryManagerState {
316 mappings: Mappings,
318
319 userfaultfds: Vec<Weak<UserFault>>,
321
322 shadow_mappings_for_mlock: RangeMap<UserAddress, Arc<PinnedMapping>>,
327
328 forkable_state: MemoryManagerForkableState,
329}
330
331const LOWER_4GB_LIMIT: UserAddress = UserAddress::const_from(0xffff_0000);
333
334#[derive(Default, Clone)]
335pub struct MemoryManagerForkableState {
336 brk: Option<ProgramBreak>,
338
339 executable_node: Option<NamespaceNode>,
341
342 pub stack_size: usize,
343 pub stack_start: UserAddress,
344 pub auxv_start: UserAddress,
345 pub auxv_end: UserAddress,
346 pub argv_start: UserAddress,
347 pub argv_end: UserAddress,
348 pub environ_start: UserAddress,
349 pub environ_end: UserAddress,
350
351 pub vdso_base: UserAddress,
353
354 pub mmap_top: UserAddress,
356 pub stack_origin: UserAddress,
357 pub brk_origin: UserAddress,
358
359 membarrier_registrations: MembarrierRegistrations,
361}
362
363impl Deref for MemoryManagerState {
364 type Target = MemoryManagerForkableState;
365 fn deref(&self) -> &Self::Target {
366 &self.forkable_state
367 }
368}
369
370impl DerefMut for MemoryManagerState {
371 fn deref_mut(&mut self) -> &mut Self::Target {
372 &mut self.forkable_state
373 }
374}
375
376#[derive(Debug, Default)]
377struct ReleasedMappings {
378 doomed: Vec<Mapping>,
379 doomed_pins: Vec<Arc<PinnedMapping>>,
380}
381
382impl ReleasedMappings {
383 fn extend(&mut self, mappings: impl IntoIterator<Item = Mapping>) {
384 self.doomed.extend(mappings);
385 }
386
387 fn extend_pins(&mut self, mappings: impl IntoIterator<Item = Arc<PinnedMapping>>) {
388 self.doomed_pins.extend(mappings);
389 }
390
391 fn is_empty(&self) -> bool {
392 self.doomed.is_empty() && self.doomed_pins.is_empty()
393 }
394
395 #[cfg(test)]
396 fn len(&self) -> usize {
397 self.doomed.len() + self.doomed_pins.len()
398 }
399
400 fn finalize(&mut self, mm_state: RwLockWriteGuard<'_, MemoryManagerState>) {
401 std::mem::drop(mm_state);
404 std::mem::take(&mut self.doomed);
405 std::mem::take(&mut self.doomed_pins);
406 }
407}
408
409impl Drop for ReleasedMappings {
410 fn drop(&mut self) {
411 assert!(self.is_empty(), "ReleasedMappings::finalize() must be called before drop");
412 }
413}
414
415fn map_in_vmar(
416 vmar: &zx::Vmar,
417 vmar_info: &zx::VmarInfo,
418 addr: SelectedAddress,
419 memory: &MemoryObject,
420 memory_offset: u64,
421 length: usize,
422 flags: MappingFlags,
423 populate: bool,
424) -> Result<(), Errno> {
425 let vmar_offset = addr.addr().checked_sub(vmar_info.base).ok_or_else(|| errno!(ENOMEM))?;
426 let vmar_extra_flags = match addr {
427 SelectedAddress::Fixed(_) => zx::VmarFlags::SPECIFIC,
428 SelectedAddress::FixedOverwrite(_) => ZX_VM_SPECIFIC_OVERWRITE,
429 };
430
431 if populate {
432 let op = if flags.contains(MappingFlags::WRITE) {
433 zx::VmoOp::COMMIT
435 } else {
436 zx::VmoOp::PREFETCH
439 };
440 fuchsia_trace::duration!(CATEGORY_STARNIX_MM, "MmapCommitPages");
441 let _ = memory.op_range(op, memory_offset, length as u64);
442 }
444
445 let vmar_maybe_map_range = if populate && !vmar_extra_flags.contains(ZX_VM_SPECIFIC_OVERWRITE) {
446 zx::VmarFlags::MAP_RANGE
447 } else {
448 zx::VmarFlags::empty()
449 };
450 let vmar_flags = flags.access_flags().to_vmar_flags()
451 | zx::VmarFlags::ALLOW_FAULTS
452 | vmar_extra_flags
453 | vmar_maybe_map_range;
454
455 let map_result = memory.map_in_vmar(vmar, vmar_offset.ptr(), memory_offset, length, vmar_flags);
456 let mapped_addr = map_result.map_err(MemoryManager::get_errno_for_map_err)?;
457
458 let expected_addr = addr.addr().ptr();
459 debug_assert_eq!(
460 mapped_addr, expected_addr,
461 "Zircon mapped to a different address than requested!"
462 );
463
464 Ok(())
465}
466
467impl MemoryManagerState {
468 fn get_occupied_address_ranges<'a>(
475 &'a self,
476 subrange: &'a Range<UserAddress>,
477 ) -> impl Iterator<Item = Range<UserAddress>> + 'a {
478 let query_range = subrange.start
479 ..(subrange
480 .end
481 .saturating_add(*PAGE_SIZE as usize * GUARD_PAGE_COUNT_FOR_GROWSDOWN_MAPPINGS));
482 self.mappings.range(query_range).filter_map(|(range, mapping)| {
483 let occupied_range = mapping.inflate_to_include_guard_pages(range);
484 if occupied_range.start < subrange.end && subrange.start < occupied_range.end {
485 Some(occupied_range)
486 } else {
487 None
488 }
489 })
490 }
491
492 fn count_possible_placements(
493 &self,
494 length: usize,
495 subrange: &Range<UserAddress>,
496 ) -> Option<usize> {
497 let mut occupied_ranges = self.get_occupied_address_ranges(subrange);
498 let mut possible_placements = 0;
499 let mut first_fill_end = subrange.start.checked_add(length)?;
502 while first_fill_end <= subrange.end {
503 let Some(mapping) = occupied_ranges.next() else {
504 possible_placements += (subrange.end - first_fill_end) / (*PAGE_SIZE as usize) + 1;
505 break;
506 };
507 if mapping.start >= first_fill_end {
508 possible_placements += (mapping.start - first_fill_end) / (*PAGE_SIZE as usize) + 1;
509 }
510 first_fill_end = mapping.end.checked_add(length)?;
511 }
512 Some(possible_placements)
513 }
514
515 fn pick_placement(
516 &self,
517 length: usize,
518 mut chosen_placement_idx: usize,
519 subrange: &Range<UserAddress>,
520 ) -> Option<UserAddress> {
521 let mut candidate =
522 Range { start: subrange.start, end: subrange.start.checked_add(length)? };
523 let mut occupied_ranges = self.get_occupied_address_ranges(subrange);
524 loop {
525 let Some(mapping) = occupied_ranges.next() else {
526 let res =
528 candidate.start.checked_add(chosen_placement_idx * *PAGE_SIZE as usize)?;
529 debug_assert!(res.checked_add(length)? <= subrange.end);
530 return Some(res);
531 };
532 if mapping.start < candidate.end {
533 candidate = Range { start: mapping.end, end: mapping.end.checked_add(length)? };
535 continue;
536 }
537 let unused_space =
538 (mapping.start.ptr() - candidate.end.ptr()) / (*PAGE_SIZE as usize) + 1;
539 if unused_space > chosen_placement_idx {
540 let res =
542 candidate.start.checked_add(chosen_placement_idx * *PAGE_SIZE as usize)?;
543 return Some(res);
544 }
545
546 chosen_placement_idx -= unused_space;
548 candidate = Range { start: mapping.end, end: mapping.end.checked_add(length)? };
549 }
550 }
551
552 fn find_random_unused_range(
553 &self,
554 length: usize,
555 subrange: &Range<UserAddress>,
556 ) -> Option<UserAddress> {
557 let possible_placements = self.count_possible_placements(length, subrange)?;
558 if possible_placements == 0 {
559 return None;
560 }
561 let chosen_placement_idx = rand::random_range(0..possible_placements);
562 self.pick_placement(length, chosen_placement_idx, subrange)
563 }
564
565 pub fn find_next_unused_range(&self, length: usize) -> Option<UserAddress> {
568 let gap_size = length as u64;
569 let mut upper_bound = self.mmap_top;
570
571 loop {
572 let gap_end = self.mappings.find_gap_end(gap_size, &upper_bound);
573 let candidate = gap_end.checked_sub(length)?;
574
575 let Some((occupied_range, mapping)) = self.mappings.get(gap_end) else {
577 return Some(candidate);
578 };
579 let occupied_range = mapping.inflate_to_include_guard_pages(occupied_range);
580 if occupied_range.start >= gap_end {
582 return Some(candidate);
583 }
584 upper_bound = occupied_range.start;
586 }
587 }
588
589 fn is_hint_acceptable(&self, hint_addr: UserAddress, length: usize) -> bool {
591 let Some(hint_end) = hint_addr.checked_add(length) else {
592 return false;
593 };
594 if !RESTRICTED_ASPACE_RANGE.contains(&hint_addr.ptr())
595 || !RESTRICTED_ASPACE_RANGE.contains(&hint_end.ptr())
596 {
597 return false;
598 };
599 self.get_occupied_address_ranges(&(hint_addr..hint_end)).next().is_none()
600 }
601
602 fn select_address(
603 &self,
604 addr: DesiredAddress,
605 length: usize,
606 flags: MappingFlags,
607 ) -> Result<SelectedAddress, Errno> {
608 let adjusted_length = round_up_to_system_page_size(length).or_else(|_| error!(ENOMEM))?;
609
610 let find_address = || -> Result<SelectedAddress, Errno> {
611 let new_addr = if flags.contains(MappingFlags::LOWER_32BIT) {
612 self.find_random_unused_range(
615 adjusted_length,
616 &(UserAddress::from_ptr(RESTRICTED_ASPACE_BASE)
617 ..UserAddress::from_ptr(0x80000000)),
618 )
619 .ok_or_else(|| errno!(ENOMEM))?
620 } else {
621 self.find_next_unused_range(adjusted_length).ok_or_else(|| errno!(ENOMEM))?
622 };
623
624 Ok(SelectedAddress::Fixed(new_addr))
625 };
626
627 Ok(match addr {
628 DesiredAddress::Any => find_address()?,
629 DesiredAddress::Hint(hint_addr) => {
630 let hint_addr =
632 UserAddress::from_ptr(hint_addr.ptr() - hint_addr.ptr() % *PAGE_SIZE as usize);
633 if self.is_hint_acceptable(hint_addr, adjusted_length) {
634 SelectedAddress::Fixed(hint_addr)
635 } else {
636 find_address()?
637 }
638 }
639 DesiredAddress::Fixed(addr) => SelectedAddress::Fixed(addr),
640 DesiredAddress::FixedOverwrite(addr) => SelectedAddress::FixedOverwrite(addr),
641 })
642 }
643
644 fn validate_addr(&self, addr: DesiredAddress, length: usize) -> Result<(), Errno> {
645 if length > RESTRICTED_ASPACE_SIZE {
646 return error!(ENOMEM);
647 }
648 match addr {
649 DesiredAddress::Fixed(a) | DesiredAddress::FixedOverwrite(a) => {
650 let end = a.checked_add(length).ok_or_else(|| errno!(ENOMEM))?;
651 if end > UserAddress::from_ptr(RESTRICTED_ASPACE_HIGHEST_ADDRESS as usize) {
652 return error!(ENOMEM);
653 }
654 if self.check_has_unauthorized_splits(a, length) {
655 return error!(ENOMEM);
656 }
657 }
658 _ => {}
659 }
660 Ok(())
661 }
662
663 fn add_memory_mapping(
664 &mut self,
665 mm: &Arc<MemoryManager>,
666 addr: DesiredAddress,
667 memory: Arc<MemoryObject>,
668 memory_offset: u64,
669 length: usize,
670 flags: MappingFlags,
671 max_access: Access,
672 populate: bool,
673 name: MappingName,
674 mapping_mode: MappingMode,
675 released_mappings: &mut ReleasedMappings,
676 ) -> Result<UserAddress, Errno> {
677 self.validate_addr(addr, length)?;
678
679 let selected_address = self.select_address(addr, length, flags)?;
680 let mapped_addr = selected_address.addr();
681 if mapping_mode == MappingMode::Eager {
682 mm.mapping_context.map_in_user_vmar(
683 selected_address,
684 &memory,
685 memory_offset,
686 length,
687 flags,
688 populate,
689 )?;
690 }
691
692 let end = (mapped_addr + length)?.round_up(*PAGE_SIZE)?;
693
694 if let DesiredAddress::FixedOverwrite(addr) = addr {
695 assert_eq!(addr, mapped_addr);
696 self.update_after_unmap(mm, addr, end - addr, released_mappings);
697 }
698
699 let mapping = Mapping::with_name(
700 self.create_memory_backing(mapped_addr, memory, memory_offset),
701 flags,
702 max_access,
703 name,
704 mapping_mode,
705 );
706 released_mappings.extend(self.mappings.insert(mapped_addr..end, mapping));
707
708 Ok(mapped_addr)
709 }
710
711 fn map_private_anonymous(
712 &mut self,
713 mm: &Arc<MemoryManager>,
714 addr: DesiredAddress,
715 length: usize,
716 prot_flags: ProtectionFlags,
717 options: MappingOptions,
718 populate: bool,
719 name: MappingName,
720 released_mappings: &mut ReleasedMappings,
721 ) -> Result<UserAddress, Errno> {
722 self.validate_addr(addr, length)?;
723
724 let flags = MappingFlags::from_access_flags_and_options(prot_flags, options);
725 let selected_addr = self.select_address(addr, length, flags)?;
726 let mapped_addr = selected_addr.addr();
727 let backing_memory_offset = selected_addr.addr().ptr();
728
729 mm.mapping_context.map_in_user_vmar(
730 selected_addr,
731 &mm.mapping_context.private_anonymous.backing,
732 backing_memory_offset as u64,
733 length,
734 flags,
735 populate,
736 )?;
737
738 let end = (mapped_addr + length)?.round_up(*PAGE_SIZE)?;
739 if let DesiredAddress::FixedOverwrite(addr) = addr {
740 assert_eq!(addr, mapped_addr);
741 self.update_after_unmap(mm, addr, end - addr, released_mappings);
742 }
743
744 let mapping = Mapping::new_private_anonymous(flags, name, MappingMode::Eager);
745 released_mappings.extend(self.mappings.insert(mapped_addr..end, mapping));
746
747 Ok(mapped_addr)
748 }
749
750 fn map_anonymous(
751 &mut self,
752 mm: &Arc<MemoryManager>,
753 addr: DesiredAddress,
754 length: usize,
755 prot_flags: ProtectionFlags,
756 options: MappingOptions,
757 name: MappingName,
758 released_mappings: &mut ReleasedMappings,
759 ) -> Result<UserAddress, Errno> {
760 if !options.contains(MappingOptions::SHARED) {
761 return self.map_private_anonymous(
762 mm,
763 addr,
764 length,
765 prot_flags,
766 options,
767 options.contains(MappingOptions::POPULATE),
768 name,
769 released_mappings,
770 );
771 }
772 let memory = create_anonymous_mapping_memory(length as u64)?;
773 let flags = MappingFlags::from_access_flags_and_options(prot_flags, options);
774 self.add_memory_mapping(
775 mm,
776 addr,
777 memory,
778 0,
779 length,
780 flags,
781 Access::rwx(),
782 options.contains(MappingOptions::POPULATE),
783 name,
784 MappingMode::Eager,
785 released_mappings,
786 )
787 }
788
789 fn any_ranges_lazy<I>(&self, ranges: I) -> bool
790 where
791 I: IntoIterator<Item = (UserAddress, Option<usize>)>,
792 {
793 for (addr, length) in ranges {
794 match length {
795 None => {
796 if let Some((_, mapping)) = self.mappings.get(addr) {
797 if mapping.mapping_mode() == MappingMode::Lazy {
798 return true;
799 }
800 }
801 }
802 Some(len) => {
803 assert!(len > 0);
804 let end = addr.checked_add(len).expect("address overflowed after validation");
805 if self
806 .mappings
807 .range(addr..end)
808 .any(|(_, mapping)| mapping.mapping_mode() == MappingMode::Lazy)
809 {
810 return true;
811 }
812 }
813 }
814 }
815 false
816 }
817
818 fn ensure_range_mapped_in_user_vmar(
819 &mut self,
820 addr: UserAddress,
821 length: Option<usize>,
822 context: &MappingContext,
823 ) -> Result<bool, Errno> {
824 self.ensure_ranges_mapped_in_user_vmar(std::iter::once((addr, length)), context)
825 }
826
827 fn ensure_ranges_mapped_in_user_vmar<I>(
828 &mut self,
829 ranges: I,
830 context: &MappingContext,
831 ) -> Result<bool, Errno>
832 where
833 I: IntoIterator<Item = (UserAddress, Option<usize>)>,
834 {
835 let mut ranges_to_update = SmallVec::<[std::ops::Range<UserAddress>; 1]>::new();
838 for (addr, length) in ranges {
839 match length {
840 None => {
841 if let Some((range, mapping)) = self.mappings.get(addr) {
842 if mapping.mapping_mode() == MappingMode::Lazy {
843 ranges_to_update.push(range.clone());
844 }
845 }
846 }
847 Some(len) => {
848 assert!(len > 0);
849 let end = addr.checked_add(len).expect("address overflowed after validation");
850 for (range, mapping) in self.mappings.range(addr..end) {
851 if mapping.mapping_mode() == MappingMode::Lazy {
852 ranges_to_update.push(range.clone());
853 }
854 }
855 }
856 }
857 }
858
859 if ranges_to_update.is_empty() {
860 return Ok(false);
861 }
862
863 for range in ranges_to_update {
864 let updated = self.mappings.update_exact(&range, |mapping| {
865 let addr = SelectedAddress::FixedOverwrite(range.start);
866 let flags = mapping.flags();
867 let (backing, backing_memory_offset) = match mapping.get_backing_internal() {
868 MappingBacking::Memory(backing) => {
869 (backing.memory(), backing.address_to_offset(addr.addr()))
870 }
871 MappingBacking::PrivateAnonymous => {
872 (&context.private_anonymous.backing, addr.addr().ptr() as u64)
873 }
874 };
875
876 let mapping_length = range.end - range.start;
877 context.map_in_user_vmar(
878 addr,
879 backing,
880 backing_memory_offset,
881 mapping_length,
882 flags,
883 false,
884 )?;
885
886 mapping.set_mapping_mode(MappingMode::Eager);
887 Ok(())
888 })?;
889 assert!(updated, "Expected to update exactly one mapping");
890 }
891
892 Ok(true)
893 }
894
895 fn remap(
896 &mut self,
897 _current_task: &CurrentTask,
898 mm: &Arc<MemoryManager>,
899 old_addr: UserAddress,
900 old_length: usize,
901 new_length: usize,
902 flags: MremapFlags,
903 new_addr: UserAddress,
904 released_mappings: &mut ReleasedMappings,
905 ) -> Result<UserAddress, Errno> {
906 if flags.contains(MremapFlags::FIXED) && !flags.contains(MremapFlags::MAYMOVE) {
908 return error!(EINVAL);
909 }
910
911 if flags.contains(MremapFlags::DONTUNMAP)
914 && (!flags.contains(MremapFlags::MAYMOVE) || old_length != new_length)
915 {
916 return error!(EINVAL);
917 }
918
919 if !flags.contains(MremapFlags::MAYMOVE) && old_length == 0 {
921 return error!(ENOMEM);
922 }
923
924 if new_length == 0 {
925 return error!(EINVAL);
926 }
927
928 if !old_addr.is_aligned(*PAGE_SIZE) {
930 return error!(EINVAL);
931 }
932
933 let old_length = round_up_to_system_page_size(old_length)?;
934 let new_length = round_up_to_system_page_size(new_length)?;
935
936 if self.check_has_unauthorized_splits(old_addr, old_length) {
937 return error!(EINVAL);
938 }
939
940 if self.check_has_unauthorized_splits(new_addr, new_length) {
941 return error!(EINVAL);
942 }
943
944 if !flags.contains(MremapFlags::DONTUNMAP)
945 && !flags.contains(MremapFlags::FIXED)
946 && old_length != 0
947 {
948 if let Some(new_addr) =
951 self.try_remap_in_place(mm, old_addr, old_length, new_length, released_mappings)?
952 {
953 return Ok(new_addr);
954 }
955 }
956
957 if flags.contains(MremapFlags::MAYMOVE) {
959 let dst_address =
960 if flags.contains(MremapFlags::FIXED) { Some(new_addr) } else { None };
961 self.remap_move(
962 mm,
963 old_addr,
964 old_length,
965 dst_address,
966 new_length,
967 flags.contains(MremapFlags::DONTUNMAP),
968 released_mappings,
969 )
970 } else {
971 error!(ENOMEM)
972 }
973 }
974
975 fn try_remap_in_place(
978 &mut self,
979 mm: &Arc<MemoryManager>,
980 old_addr: UserAddress,
981 old_length: usize,
982 new_length: usize,
983 released_mappings: &mut ReleasedMappings,
984 ) -> Result<Option<UserAddress>, Errno> {
985 let old_range = old_addr..old_addr.checked_add(old_length).ok_or_else(|| errno!(EINVAL))?;
986 let new_range_in_place =
987 old_addr..old_addr.checked_add(new_length).ok_or_else(|| errno!(EINVAL))?;
988
989 if new_length <= old_length {
990 if new_length != old_length {
993 self.unmap(mm, new_range_in_place.end, old_length - new_length, released_mappings)?;
994 }
995 return Ok(Some(old_addr));
996 }
997
998 if self.mappings.range(old_range.end..new_range_in_place.end).next().is_some() {
999 return Ok(None);
1001 }
1002
1003 let (original_range, mapping) =
1005 self.mappings.get(old_addr).ok_or_else(|| errno!(EINVAL))?;
1006
1007 if old_range.end > original_range.end {
1008 return error!(EFAULT);
1009 }
1010 let original_range = original_range.clone();
1011 let original_mapping = mapping.clone();
1012
1013 let final_length = (original_range.end - original_range.start) + (new_length - old_length);
1015
1016 match self.get_mapping_backing(&original_mapping) {
1017 MappingBacking::Memory(backing) => {
1018 Ok(Some(self.add_memory_mapping(
1020 mm,
1021 DesiredAddress::FixedOverwrite(original_range.start),
1022 backing.memory().clone(),
1023 backing.address_to_offset(original_range.start),
1024 final_length,
1025 original_mapping.flags(),
1026 original_mapping.max_access(),
1027 false,
1028 original_mapping.name().to_owned(),
1029 original_mapping.mapping_mode(),
1030 released_mappings,
1031 )?))
1032 }
1033 MappingBacking::PrivateAnonymous => {
1034 let growth_start = original_range.end;
1035 let growth_length = new_length - old_length;
1036 let final_end = (original_range.start + final_length)?;
1037 mm.mapping_context.map_in_user_vmar(
1039 SelectedAddress::FixedOverwrite(growth_start),
1040 &mm.mapping_context.private_anonymous.backing,
1041 growth_start.ptr() as u64,
1042 growth_length,
1043 original_mapping.flags(),
1044 false,
1045 )?;
1046 released_mappings.extend(
1048 self.mappings.insert(original_range.start..final_end, original_mapping.clone()),
1049 );
1050 Ok(Some(original_range.start))
1051 }
1052 }
1053 }
1054
1055 fn remap_move(
1057 &mut self,
1058 mm: &Arc<MemoryManager>,
1059 src_addr: UserAddress,
1060 src_length: usize,
1061 dst_addr: Option<UserAddress>,
1062 dst_length: usize,
1063 keep_source: bool,
1064 released_mappings: &mut ReleasedMappings,
1065 ) -> Result<UserAddress, Errno> {
1066 let src_range = src_addr..src_addr.checked_add(src_length).ok_or_else(|| errno!(EINVAL))?;
1067 let (original_range, src_mapping) =
1068 self.mappings.get(src_addr).ok_or_else(|| errno!(EINVAL))?;
1069 let original_range = original_range.clone();
1070 let src_mapping = src_mapping.clone();
1071
1072 if src_length == 0 && !src_mapping.flags().contains(MappingFlags::SHARED) {
1073 return error!(EINVAL);
1076 }
1077
1078 if src_length != 0 && src_length > dst_length {
1082 self.unmap(mm, (src_addr + dst_length)?, src_length - dst_length, released_mappings)?;
1083 }
1084
1085 let dst_addr_for_map = match dst_addr {
1086 None => DesiredAddress::Any,
1087 Some(dst_addr) => {
1088 let dst_range =
1090 dst_addr..(dst_addr.checked_add(dst_length).ok_or_else(|| errno!(EINVAL))?);
1091 if !src_range.intersect(&dst_range).is_empty() {
1092 return error!(EINVAL);
1093 }
1094
1095 self.unmap(mm, dst_addr, dst_length, released_mappings)?;
1098
1099 DesiredAddress::Fixed(dst_addr)
1100 }
1101 };
1102
1103 if dst_length > src_length && src_mapping.flags().contains(MappingFlags::DONT_EXPAND) {
1106 return error!(EFAULT);
1107 }
1108
1109 if src_range.end > original_range.end {
1110 return error!(EFAULT);
1113 }
1114
1115 match self.get_mapping_backing(&src_mapping) {
1116 MappingBacking::PrivateAnonymous => {
1117 let dst_addr =
1118 self.select_address(dst_addr_for_map, dst_length, src_mapping.flags())?.addr();
1119 let dst_end = (dst_addr + dst_length)?;
1120
1121 let length_to_move = std::cmp::min(dst_length, src_length) as u64;
1122 let growth_start_addr = (dst_addr + length_to_move)?;
1123
1124 if dst_addr != src_addr {
1125 let src_move_end = (src_range.start + length_to_move)?;
1126 let range_to_move = src_range.start..src_move_end;
1127 mm.mapping_context.private_anonymous.move_pages(&range_to_move, dst_addr)?;
1129 }
1130
1131 let new_flags =
1133 src_mapping.flags().difference(MappingFlags::UFFD | MappingFlags::UFFD_MISSING);
1134 if src_mapping.mapping_mode() == MappingMode::Eager {
1135 mm.mapping_context.map_in_user_vmar(
1136 SelectedAddress::FixedOverwrite(dst_addr),
1137 &mm.mapping_context.private_anonymous.backing,
1138 dst_addr.ptr() as u64,
1139 dst_length,
1140 new_flags,
1141 false,
1142 )?;
1143
1144 if dst_length > src_length {
1145 let growth_length = dst_length - src_length;
1147
1148 self.map_private_anonymous(
1149 mm,
1150 DesiredAddress::FixedOverwrite(growth_start_addr),
1151 growth_length,
1152 new_flags.access_flags(),
1153 new_flags.options(),
1154 false,
1155 src_mapping.name().to_owned(),
1156 released_mappings,
1157 )?;
1158 }
1159 }
1160
1161 released_mappings.extend(self.mappings.insert(
1162 dst_addr..dst_end,
1163 Mapping::new_private_anonymous(
1164 new_flags,
1165 src_mapping.name().to_owned(),
1166 src_mapping.mapping_mode(),
1167 ),
1168 ));
1169
1170 if dst_addr != src_addr && src_length != 0 && !keep_source {
1171 self.unmap(mm, src_addr, src_length, released_mappings)?;
1172 }
1173
1174 return Ok(dst_addr);
1175 }
1176 MappingBacking::Memory(backing) => {
1177 let (dst_memory_offset, memory) =
1181 (backing.address_to_offset(src_addr), backing.memory().clone());
1182
1183 let new_address = self.add_memory_mapping(
1184 mm,
1185 dst_addr_for_map,
1186 memory,
1187 dst_memory_offset,
1188 dst_length,
1189 src_mapping.flags(),
1190 src_mapping.max_access(),
1191 false,
1192 src_mapping.name().to_owned(),
1193 src_mapping.mapping_mode(),
1194 released_mappings,
1195 )?;
1196
1197 if src_length != 0 && !keep_source {
1198 self.unmap(mm, src_addr, src_length, released_mappings)?;
1202 }
1203
1204 return Ok(new_address);
1205 }
1206 };
1207 }
1208
1209 fn check_has_unauthorized_splits(&self, addr: UserAddress, length: usize) -> bool {
1215 let query_range = addr..addr.saturating_add(length);
1216 let mut intersection = self.mappings.range(query_range.clone());
1217
1218 let check_if_mapping_has_unauthorized_split =
1221 |mapping: Option<(&Range<UserAddress>, &Mapping)>| {
1222 mapping.is_some_and(|(mapping_range, mapping)| {
1223 mapping.flags().contains(MappingFlags::DONT_SPLIT)
1224 && (mapping_range.start < query_range.start
1225 || query_range.end < mapping_range.end)
1226 })
1227 };
1228
1229 check_if_mapping_has_unauthorized_split(intersection.next())
1233 || check_if_mapping_has_unauthorized_split(intersection.next_back())
1234 }
1235
1236 fn unmap(
1238 &mut self,
1239 mm: &Arc<MemoryManager>,
1240 addr: UserAddress,
1241 length: usize,
1242 released_mappings: &mut ReleasedMappings,
1243 ) -> Result<(), Errno> {
1244 if !addr.is_aligned(*PAGE_SIZE) {
1245 return error!(EINVAL);
1246 }
1247 let length = round_up_to_system_page_size(length)?;
1248 if length == 0 {
1249 return error!(EINVAL);
1250 }
1251
1252 if self.check_has_unauthorized_splits(addr, length) {
1253 return error!(EINVAL);
1254 }
1255
1256 #[allow(
1259 clippy::undocumented_unsafe_blocks,
1260 reason = "Force documented unsafe blocks in Starnix"
1261 )]
1262 match unsafe { mm.mapping_context.user_vmar.unmap(addr.ptr(), length) } {
1263 Ok(_) => (),
1264 Err(zx::Status::NOT_FOUND) => (),
1265 Err(zx::Status::INVALID_ARGS) => return error!(EINVAL),
1266 Err(status) => {
1267 impossible_error(status);
1268 }
1269 };
1270
1271 self.update_after_unmap(mm, addr, length, released_mappings);
1272
1273 Ok(())
1274 }
1275
1276 fn update_after_unmap(
1288 &mut self,
1289 mm: &Arc<MemoryManager>,
1290 addr: UserAddress,
1291 length: usize,
1292 released_mappings: &mut ReleasedMappings,
1293 ) {
1294 let end_addr = addr.checked_add(length).expect("address overflow during unmap");
1295 let unmap_range = addr..end_addr;
1296
1297 released_mappings.extend_pins(self.shadow_mappings_for_mlock.remove(unmap_range.clone()));
1299
1300 for (range, mapping) in self.mappings.range(unmap_range.clone()) {
1301 if let MappingBacking::PrivateAnonymous = self.get_mapping_backing(mapping) {
1303 let unmapped_range = &unmap_range.intersect(range);
1304
1305 if let Err(e) = mm
1306 .inflight_vmspliced_payloads
1307 .handle_unmapping(&mm.mapping_context.private_anonymous.backing, unmapped_range)
1308 {
1309 log_error!("Failed to handle vmsplice unmapping: {:?}", e);
1310 }
1311
1312 if let Err(e) = mm
1313 .mapping_context
1314 .private_anonymous
1315 .zero(unmapped_range.start, unmapped_range.end - unmapped_range.start)
1316 {
1317 log_error!("Failed to zero private anonymous memory: {:?}", e);
1318 }
1319 }
1320 }
1321 released_mappings.extend(self.mappings.remove(unmap_range));
1322 }
1323
1324 fn protect(
1325 &mut self,
1326 current_task: &CurrentTask,
1327 addr: UserAddress,
1328 length: usize,
1329 prot_flags: ProtectionFlags,
1330 released_mappings: &mut ReleasedMappings,
1331 ) -> Result<(), Errno> {
1332 let vmar_flags = prot_flags.to_vmar_flags();
1333 let page_size = *PAGE_SIZE;
1334 let end = addr.checked_add(length).ok_or_else(|| errno!(EINVAL))?.round_up(page_size)?;
1335
1336 if self.check_has_unauthorized_splits(addr, length) {
1337 return error!(EINVAL);
1338 }
1339
1340 let prot_range = if prot_flags.contains(ProtectionFlags::GROWSDOWN) {
1341 let mut start = addr;
1342 let Some((range, mapping)) = self.mappings.get(start) else {
1343 return error!(EINVAL);
1344 };
1345 if !mapping.flags().contains(MappingFlags::GROWSDOWN) {
1347 return error!(EINVAL);
1348 }
1349 let access_flags = mapping.flags().access_flags();
1350 start = range.start;
1358 while let Some((range, mapping)) =
1359 self.mappings.get(start.saturating_sub(page_size as usize))
1360 {
1361 if !mapping.flags().contains(MappingFlags::GROWSDOWN)
1362 || mapping.flags().access_flags() != access_flags
1363 {
1364 break;
1365 }
1366 start = range.start;
1367 }
1368 start..end
1369 } else {
1370 addr..end
1371 };
1372
1373 let mut range_list = vec![];
1374 let mapping_context = ¤t_task.mm()?.mapping_context;
1375 let length = prot_range.end - prot_range.start;
1376 self.ensure_range_mapped_in_user_vmar(prot_range.start, Some(length), mapping_context)?;
1377
1378 for (range, mapping) in self.mappings.range(prot_range.clone()) {
1379 range_list.push((range.clone(), mapping.clone()));
1380 }
1381
1382 let mut start_cursor = prot_range.start;
1383 let mut updates = vec![];
1384 let mut final_result = Ok(());
1385
1386 for (range, mapping) in range_list {
1387 if range.start > start_cursor {
1388 final_result = error!(ENOMEM);
1389 break;
1390 }
1391
1392 let intersection = range.intersect(&prot_range);
1393 if let Err(e) =
1394 security::file_mprotect(current_task, &intersection, &mapping, prot_flags)
1395 {
1396 final_result = Err(e);
1397 break;
1398 }
1399
1400 if mapping.flags().contains(MappingFlags::UFFD) {
1401 track_stub!(
1402 TODO("https://fxbug.dev/297375964"),
1403 "mprotect on uffd-registered range should not alter protections"
1404 );
1405 final_result = error!(EINVAL);
1406 break;
1407 }
1408
1409 let mapped_len = intersection.end - intersection.start;
1410
1411 let protect_result = unsafe {
1413 mapping_context.user_vmar.protect(intersection.start.ptr(), mapped_len, vmar_flags)
1414 }
1415 .map_err(|s| match s {
1416 zx::Status::INVALID_ARGS => errno!(EINVAL),
1417 zx::Status::NOT_FOUND => errno!(ENOMEM),
1418 zx::Status::ACCESS_DENIED => errno!(EACCES),
1419 _ => impossible_error(s),
1420 });
1421
1422 if let Err(e) = protect_result {
1423 final_result = Err(e);
1424 break;
1425 }
1426
1427 let mut new_mapping = mapping.clone();
1428 new_mapping.set_flags(new_mapping.flags().with_access_flags(prot_flags));
1429 let push_range = intersection.clone();
1430 start_cursor = intersection.end;
1431 updates.push((push_range, new_mapping));
1432 }
1433
1434 if final_result.is_ok() && start_cursor < prot_range.end {
1435 final_result = error!(ENOMEM);
1436 }
1437
1438 for (r, m) in updates {
1439 released_mappings.extend(self.mappings.insert(r, m));
1440 }
1441
1442 final_result
1443 }
1444
1445 fn madvise(
1446 &mut self,
1447 context: &MappingContext,
1448 addr: UserAddress,
1449 length: usize,
1450 advice: u32,
1451 released_mappings: &mut ReleasedMappings,
1452 ) -> Result<(), Errno> {
1453 if !addr.is_aligned(*PAGE_SIZE) {
1454 return error!(EINVAL);
1455 }
1456
1457 let end_addr =
1458 addr.checked_add(length).ok_or_else(|| errno!(EINVAL))?.round_up(*PAGE_SIZE)?;
1459 if end_addr > context.max_address() {
1460 return error!(EFAULT);
1461 }
1462
1463 if advice == MADV_NORMAL {
1464 track_stub!(TODO("https://fxbug.dev/322874202"), "madvise undo hints for MADV_NORMAL");
1465 return Ok(());
1466 }
1467
1468 let mut updates = vec![];
1469 let range_for_op = addr..end_addr;
1470 for (range, mapping) in self.mappings.range(range_for_op.clone()) {
1471 let range_to_zero = range.intersect(&range_for_op);
1472 if range_to_zero.is_empty() {
1473 continue;
1474 }
1475 let start_offset = mapping.address_to_offset(range_to_zero.start);
1476 let end_offset = mapping.address_to_offset(range_to_zero.end);
1477 if advice == MADV_DONTFORK
1478 || advice == MADV_DOFORK
1479 || advice == MADV_WIPEONFORK
1480 || advice == MADV_KEEPONFORK
1481 || advice == MADV_DONTDUMP
1482 || advice == MADV_DODUMP
1483 || advice == MADV_MERGEABLE
1484 || advice == MADV_UNMERGEABLE
1485 {
1486 if advice == MADV_WIPEONFORK && !mapping.private_anonymous() {
1491 return error!(EINVAL);
1492 }
1493 let new_flags = match advice {
1494 MADV_DONTFORK => mapping.flags() | MappingFlags::DONTFORK,
1495 MADV_DOFORK => mapping.flags() & MappingFlags::DONTFORK.complement(),
1496 MADV_WIPEONFORK => mapping.flags() | MappingFlags::WIPEONFORK,
1497 MADV_KEEPONFORK => mapping.flags() & MappingFlags::WIPEONFORK.complement(),
1498 MADV_DONTDUMP => {
1499 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_DONTDUMP");
1500 mapping.flags()
1501 }
1502 MADV_DODUMP => {
1503 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_DODUMP");
1504 mapping.flags()
1505 }
1506 MADV_MERGEABLE => {
1507 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_MERGEABLE");
1508 mapping.flags()
1509 }
1510 MADV_UNMERGEABLE => {
1511 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_UNMERGEABLE");
1512 mapping.flags()
1513 }
1514 unknown_advice => unreachable!("unknown advice {unknown_advice}"),
1517 };
1518 let mut new_mapping = mapping.clone();
1519 new_mapping.set_flags(new_flags);
1520 updates.push((range_to_zero, new_mapping));
1521 } else {
1522 if mapping.flags().contains(MappingFlags::SHARED) {
1523 continue;
1524 }
1525 let op = match advice {
1526 MADV_DONTNEED if !mapping.flags().contains(MappingFlags::ANONYMOUS) => {
1527 track_stub!(
1531 TODO("https://fxbug.dev/322874496"),
1532 "MADV_DONTNEED with file-backed mapping"
1533 );
1534 return error!(EINVAL);
1535 }
1536 MADV_DONTNEED if mapping.flags().contains(MappingFlags::LOCKED) => {
1537 return error!(EINVAL);
1538 }
1539 MADV_DONTNEED => zx::VmoOp::ZERO,
1540 MADV_DONTNEED_LOCKED => {
1541 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_DONTNEED_LOCKED");
1542 return error!(EINVAL);
1543 }
1544 MADV_WILLNEED => {
1545 if mapping.flags().contains(MappingFlags::WRITE) {
1546 zx::VmoOp::COMMIT
1547 } else {
1548 zx::VmoOp::PREFETCH
1549 }
1550 }
1551 MADV_COLD => {
1552 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_COLD");
1553 return error!(EINVAL);
1554 }
1555 MADV_PAGEOUT => {
1556 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_PAGEOUT");
1557 return error!(EINVAL);
1558 }
1559 MADV_POPULATE_READ => {
1560 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_POPULATE_READ");
1561 return error!(EINVAL);
1562 }
1563 MADV_RANDOM => {
1564 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_RANDOM");
1565 return error!(EINVAL);
1566 }
1567 MADV_SEQUENTIAL => {
1568 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_SEQUENTIAL");
1569 return error!(EINVAL);
1570 }
1571 MADV_FREE if !mapping.flags().contains(MappingFlags::ANONYMOUS) => {
1572 track_stub!(
1573 TODO("https://fxbug.dev/411748419"),
1574 "MADV_FREE with file-backed mapping"
1575 );
1576 return error!(EINVAL);
1577 }
1578 MADV_FREE if mapping.flags().contains(MappingFlags::LOCKED) => {
1579 return error!(EINVAL);
1580 }
1581 MADV_FREE => {
1582 track_stub!(TODO("https://fxbug.dev/411748419"), "MADV_FREE");
1583 zx::VmoOp::ZERO
1586 }
1587 MADV_REMOVE => {
1588 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_REMOVE");
1589 return error!(EINVAL);
1590 }
1591 MADV_HWPOISON => {
1592 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_HWPOISON");
1593 return error!(EINVAL);
1594 }
1595 MADV_SOFT_OFFLINE => {
1596 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_SOFT_OFFLINE");
1597 return error!(EINVAL);
1598 }
1599 MADV_HUGEPAGE => {
1600 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_HUGEPAGE");
1601 return error!(EINVAL);
1602 }
1603 MADV_COLLAPSE => {
1604 track_stub!(TODO("https://fxbug.dev/322874202"), "MADV_COLLAPSE");
1605 return error!(EINVAL);
1606 }
1607 MADV_NOHUGEPAGE => return Ok(()),
1608 advice => {
1609 track_stub!(TODO("https://fxbug.dev/322874202"), "madvise", advice);
1610 return error!(EINVAL);
1611 }
1612 };
1613
1614 let memory = match self.get_mapping_backing(mapping) {
1615 MappingBacking::Memory(backing) => backing.memory(),
1616 MappingBacking::PrivateAnonymous => &context.private_anonymous.backing,
1617 };
1618 memory.op_range(op, start_offset, end_offset - start_offset).map_err(
1619 |s| match s {
1620 zx::Status::OUT_OF_RANGE => errno!(EINVAL),
1621 zx::Status::NO_MEMORY => errno!(ENOMEM),
1622 zx::Status::INVALID_ARGS => errno!(EINVAL),
1623 zx::Status::ACCESS_DENIED => errno!(EACCES),
1624 _ => impossible_error(s),
1625 },
1626 )?;
1627 }
1628 }
1629 for (range, mapping) in updates {
1631 released_mappings.extend(self.mappings.insert(range, mapping));
1632 }
1633 Ok(())
1634 }
1635
1636 fn mlock(
1637 &mut self,
1638 context: &MappingContext,
1639 current_task: &CurrentTask,
1640 desired_addr: UserAddress,
1641 desired_length: usize,
1642 on_fault: bool,
1643 released_mappings: &mut ReleasedMappings,
1644 ) -> Result<(), Errno> {
1645 let desired_end_addr =
1646 desired_addr.checked_add(desired_length).ok_or_else(|| errno!(EINVAL))?;
1647 let start_addr = round_down_to_system_page_size(desired_addr)?;
1648 let end_addr = round_up_to_system_page_size(desired_end_addr)?;
1649
1650 let mut updates = vec![];
1651 let mut bytes_mapped_in_range = 0;
1652 let mut num_new_locked_bytes = 0;
1653 let mut failed_to_lock = false;
1654 for (range, mapping) in self.mappings.range(start_addr..end_addr) {
1655 let mut range = range.clone();
1656 let mut mapping = mapping.clone();
1657
1658 range.start = std::cmp::max(range.start, start_addr);
1660 range.end = std::cmp::min(range.end, end_addr);
1662
1663 bytes_mapped_in_range += (range.end - range.start) as u64;
1664
1665 if !mapping
1667 .flags()
1668 .intersects(MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXEC)
1669 {
1670 failed_to_lock = true;
1671 }
1672
1673 if !mapping.flags().contains(MappingFlags::LOCKED) {
1674 num_new_locked_bytes += (range.end - range.start) as u64;
1675 let shadow_mapping = match current_task.kernel().features.mlock_pin_flavor {
1676 MlockPinFlavor::ShadowProcess => {
1678 let shadow_process =
1679 current_task.kernel().expando.get_or_try_init(|| {
1680 memory_pinning::ShadowProcess::new(zx::Name::new_lossy(
1681 "starnix_mlock_pins",
1682 ))
1683 .map(MlockShadowProcess)
1684 .map_err(|_| errno!(EPERM))
1685 })?;
1686
1687 let (vmo, offset) = match self.get_mapping_backing(&mapping) {
1688 MappingBacking::Memory(m) => (
1689 m.memory().as_vmo().ok_or_else(|| errno!(ENOMEM))?,
1690 m.address_to_offset(range.start),
1691 ),
1692 MappingBacking::PrivateAnonymous => (
1693 context
1694 .private_anonymous
1695 .backing
1696 .as_vmo()
1697 .ok_or_else(|| errno!(ENOMEM))?,
1698 range.start.ptr() as u64,
1699 ),
1700 };
1701 Some(shadow_process.0.pin_pages(vmo, offset, range.end - range.start)?)
1702 }
1703
1704 MlockPinFlavor::Noop | MlockPinFlavor::VmarAlwaysNeed => None,
1706 };
1707 mapping.set_mlock();
1708 updates.push((range, mapping, shadow_mapping));
1709 }
1710 }
1711
1712 if bytes_mapped_in_range as usize != end_addr - start_addr {
1713 return error!(ENOMEM);
1714 }
1715
1716 let memlock_rlimit = current_task.thread_group().get_rlimit(Resource::MEMLOCK);
1717 let total_locked = self.num_locked_bytes(
1718 UserAddress::from(context.user_vmar_info.base as u64)
1719 ..UserAddress::from(
1720 (context.user_vmar_info.base + context.user_vmar_info.len) as u64,
1721 ),
1722 );
1723 if total_locked + num_new_locked_bytes > memlock_rlimit {
1724 if crate::security::check_task_capable(current_task, CAP_IPC_LOCK).is_err() {
1725 let code = if memlock_rlimit > 0 { errno!(ENOMEM) } else { errno!(EPERM) };
1726 return Err(code);
1727 }
1728 }
1729
1730 let op_range_status_to_errno = |e| match e {
1731 zx::Status::BAD_STATE | zx::Status::NOT_SUPPORTED => errno!(ENOMEM),
1732 zx::Status::INVALID_ARGS | zx::Status::OUT_OF_RANGE => errno!(EINVAL),
1733 zx::Status::ACCESS_DENIED => {
1734 unreachable!("user vmar should always have needed rights")
1735 }
1736 zx::Status::BAD_HANDLE => {
1737 unreachable!("user vmar should always be a valid handle")
1738 }
1739 zx::Status::WRONG_TYPE => unreachable!("user vmar handle should be a vmar"),
1740 _ => unreachable!("unknown error from op_range on user vmar for mlock: {e}"),
1741 };
1742
1743 self.ensure_range_mapped_in_user_vmar(start_addr, Some(end_addr - start_addr), context)?;
1744
1745 if !on_fault && !current_task.kernel().features.mlock_always_onfault {
1746 context
1747 .user_vmar
1748 .op_range(zx::VmarOp::PREFETCH, start_addr.ptr(), end_addr - start_addr)
1749 .map_err(op_range_status_to_errno)?;
1750 }
1751
1752 match current_task.kernel().features.mlock_pin_flavor {
1753 MlockPinFlavor::VmarAlwaysNeed => {
1754 context
1755 .user_vmar
1756 .op_range(zx::VmarOp::ALWAYS_NEED, start_addr.ptr(), end_addr - start_addr)
1757 .map_err(op_range_status_to_errno)?;
1758 }
1759 MlockPinFlavor::Noop | MlockPinFlavor::ShadowProcess => (),
1761 }
1762
1763 for (range, mapping, shadow_mapping) in updates {
1764 if let Some(shadow_mapping) = shadow_mapping {
1765 released_mappings.extend_pins(
1766 self.shadow_mappings_for_mlock.insert(range.clone(), shadow_mapping),
1767 );
1768 }
1769 released_mappings.extend(self.mappings.insert(range, mapping));
1770 }
1771
1772 if failed_to_lock { error!(ENOMEM) } else { Ok(()) }
1773 }
1774
1775 fn munlock(
1776 &mut self,
1777 _current_task: &CurrentTask,
1778 desired_addr: UserAddress,
1779 desired_length: usize,
1780 released_mappings: &mut ReleasedMappings,
1781 ) -> Result<(), Errno> {
1782 let desired_end_addr =
1783 desired_addr.checked_add(desired_length).ok_or_else(|| errno!(EINVAL))?;
1784 let start_addr = round_down_to_system_page_size(desired_addr)?;
1785 let end_addr = round_up_to_system_page_size(desired_end_addr)?;
1786
1787 let mut updates = vec![];
1788 let mut bytes_mapped_in_range = 0;
1789 for (range, mapping) in self.mappings.range(start_addr..end_addr) {
1790 let mut range = range.clone();
1791 let mut mapping = mapping.clone();
1792
1793 range.start = std::cmp::max(range.start, start_addr);
1795 range.end = std::cmp::min(range.end, end_addr);
1797
1798 bytes_mapped_in_range += (range.end - range.start) as u64;
1799
1800 if mapping.flags().contains(MappingFlags::LOCKED) {
1801 mapping.clear_mlock();
1805 updates.push((range, mapping));
1806 }
1807 }
1808
1809 if bytes_mapped_in_range as usize != end_addr - start_addr {
1810 return error!(ENOMEM);
1811 }
1812
1813 for (range, mapping) in updates {
1814 released_mappings.extend(self.mappings.insert(range.clone(), mapping));
1815 released_mappings.extend_pins(self.shadow_mappings_for_mlock.remove(range));
1816 }
1817
1818 Ok(())
1819 }
1820
1821 pub fn num_locked_bytes(&self, range: impl RangeBounds<UserAddress>) -> u64 {
1822 self.mappings
1823 .map
1824 .range(range)
1825 .filter(|(_, mapping)| mapping.flags().contains(MappingFlags::LOCKED))
1826 .map(|(range, _)| (range.end - range.start) as u64)
1827 .sum()
1828 }
1829
1830 fn get_mappings_for_vmsplice(
1831 &self,
1832 mm: &Arc<MemoryManager>,
1833 buffers: &UserBuffers,
1834 ) -> Result<Vec<Arc<VmsplicePayload>>, Errno> {
1835 let mut vmsplice_mappings = Vec::new();
1836
1837 for UserBuffer { mut address, length } in buffers.iter().copied() {
1838 let mappings = self.get_contiguous_mappings_at(address, length, &mm.mapping_context)?;
1839 for (mapping, length) in mappings {
1840 let vmsplice_payload = match self.get_mapping_backing(mapping) {
1841 MappingBacking::Memory(m) => VmsplicePayloadSegment {
1842 addr_offset: address,
1843 length,
1844 memory: m.memory().clone(),
1845 memory_offset: m.address_to_offset(address),
1846 should_snapshot_on_unmap: false,
1847 },
1848 MappingBacking::PrivateAnonymous => VmsplicePayloadSegment {
1849 addr_offset: address,
1850 length,
1851 memory: mm.mapping_context.private_anonymous.backing.clone(),
1852 memory_offset: address.ptr() as u64,
1853 should_snapshot_on_unmap: true,
1854 },
1855 };
1856 vmsplice_mappings.push(VmsplicePayload::new(Arc::downgrade(mm), vmsplice_payload));
1857
1858 address = (address + length)?;
1859 }
1860 }
1861
1862 Ok(vmsplice_mappings)
1863 }
1864
1865 fn get_contiguous_mappings_at(
1878 &self,
1879 addr: UserAddress,
1880 length: usize,
1881 context: &MappingContext,
1882 ) -> Result<impl Iterator<Item = (&Mapping, usize)>, Errno> {
1883 let end_addr = addr.checked_add(length).ok_or_else(|| errno!(EFAULT))?;
1884 if end_addr > context.max_address() {
1885 return error!(EFAULT);
1886 }
1887
1888 let mut mappings = self.mappings.range(addr..end_addr);
1890 let mut prev_range_end = None;
1891 let mut offset = 0;
1892 let result = std::iter::from_fn(move || {
1893 if offset != length {
1894 if let Some((range, mapping)) = mappings.next() {
1895 return match prev_range_end {
1896 None if range.start > addr => None,
1899
1900 Some(prev_range_end) if range.start != prev_range_end => None,
1902
1903 _ => {
1905 let mapping_length = std::cmp::min(length, range.end - addr) - offset;
1906 offset += mapping_length;
1907 prev_range_end = Some(range.end);
1908 Some((mapping, mapping_length))
1909 }
1910 };
1911 }
1912 }
1913
1914 None
1915 });
1916
1917 Ok(result)
1918 }
1919
1920 fn find_growsdown_mapping(&self, addr: UserAddress) -> Option<(UserAddress, &Mapping)> {
1928 match self.mappings.range(addr..).next() {
1929 Some((range, mapping)) => {
1930 if range.contains(&addr) {
1931 return None;
1933 } else if !mapping.flags().contains(MappingFlags::GROWSDOWN) {
1934 None
1937 } else {
1938 Some((range.start, mapping))
1939 }
1940 }
1941 None => None,
1942 }
1943 }
1944
1945 fn extend_growsdown_mapping_to_address(
1948 &mut self,
1949 mm: &Arc<MemoryManager>,
1950 addr: UserAddress,
1951 is_write: bool,
1952 ) -> Result<bool, Error> {
1953 let Some((mapping_low_addr, mapping_to_grow)) = self.find_growsdown_mapping(addr) else {
1954 return Ok(false);
1955 };
1956 if is_write && !mapping_to_grow.can_write() {
1957 return Ok(false);
1959 }
1960 if !mapping_to_grow.flags().contains(MappingFlags::ANONYMOUS) {
1961 return Ok(false);
1963 }
1964 let low_addr = (addr - (addr.ptr() as u64 % *PAGE_SIZE))?;
1965 let high_addr = mapping_low_addr;
1966
1967 let length = high_addr
1968 .ptr()
1969 .checked_sub(low_addr.ptr())
1970 .ok_or_else(|| anyhow!("Invalid growth range"))?;
1971
1972 let mut released_mappings = ReleasedMappings::default();
1973 self.map_anonymous(
1974 mm,
1975 DesiredAddress::FixedOverwrite(low_addr),
1976 length,
1977 mapping_to_grow.flags().access_flags(),
1978 mapping_to_grow.flags().options(),
1979 mapping_to_grow.name().to_owned(),
1980 &mut released_mappings,
1981 )?;
1982 assert!(
1985 released_mappings.is_empty(),
1986 "expected to not remove mappings by inserting, got {released_mappings:#?}"
1987 );
1988 Ok(true)
1989 }
1990
1991 fn read_memory<'a>(
1997 &self,
1998 addr: UserAddress,
1999 bytes: &'a mut [MaybeUninit<u8>],
2000 context: &MappingContext,
2001 ) -> Result<&'a mut [u8], Errno> {
2002 let mut bytes_read = 0;
2003 for (mapping, len) in self.get_contiguous_mappings_at(addr, bytes.len(), context)? {
2004 let next_offset = bytes_read + len;
2005 self.read_mapping_memory(
2006 (addr + bytes_read)?,
2007 mapping,
2008 &mut bytes[bytes_read..next_offset],
2009 context,
2010 )?;
2011 bytes_read = next_offset;
2012 }
2013
2014 if bytes_read != bytes.len() {
2015 error!(EFAULT)
2016 } else {
2017 let bytes = unsafe {
2022 std::slice::from_raw_parts_mut(bytes.as_mut_ptr() as *mut u8, bytes_read)
2023 };
2024 Ok(bytes)
2025 }
2026 }
2027
2028 fn read_mapping_memory<'a>(
2034 &self,
2035 addr: UserAddress,
2036 mapping: &Mapping,
2037 bytes: &'a mut [MaybeUninit<u8>],
2038 context: &MappingContext,
2039 ) -> Result<&'a mut [u8], Errno> {
2040 if !mapping.can_read() {
2041 return error!(EFAULT, "read_mapping_memory called on unreadable mapping");
2042 }
2043 match self.get_mapping_backing(mapping) {
2044 MappingBacking::Memory(backing) => backing.read_memory(addr, bytes),
2045 MappingBacking::PrivateAnonymous => context.private_anonymous.read_memory(addr, bytes),
2046 }
2047 }
2048
2049 fn read_memory_partial<'a>(
2059 &self,
2060 addr: UserAddress,
2061 bytes: &'a mut [MaybeUninit<u8>],
2062 context: &MappingContext,
2063 ) -> Result<&'a mut [u8], Errno> {
2064 let mut bytes_read = 0;
2065 for (mapping, len) in self.get_contiguous_mappings_at(addr, bytes.len(), context)? {
2066 let next_offset = bytes_read + len;
2067 if self
2068 .read_mapping_memory(
2069 (addr + bytes_read)?,
2070 mapping,
2071 &mut bytes[bytes_read..next_offset],
2072 context,
2073 )
2074 .is_err()
2075 {
2076 break;
2077 }
2078 bytes_read = next_offset;
2079 }
2080
2081 if !bytes.is_empty() && bytes_read == 0 {
2083 error!(EFAULT)
2084 } else {
2085 let bytes = unsafe {
2090 std::slice::from_raw_parts_mut(bytes.as_mut_ptr() as *mut u8, bytes_read)
2091 };
2092 Ok(bytes)
2093 }
2094 }
2095
2096 fn read_memory_partial_until_null_byte<'a>(
2099 &self,
2100 addr: UserAddress,
2101 bytes: &'a mut [MaybeUninit<u8>],
2102 context: &MappingContext,
2103 ) -> Result<&'a mut [u8], Errno> {
2104 let read_bytes = self.read_memory_partial(addr, bytes, context)?;
2105 let max_len = memchr::memchr(b'\0', read_bytes)
2106 .map_or_else(|| read_bytes.len(), |null_index| null_index + 1);
2107 Ok(&mut read_bytes[..max_len])
2108 }
2109
2110 fn write_memory(
2118 &self,
2119 addr: UserAddress,
2120 bytes: &[u8],
2121 context: &MappingContext,
2122 ) -> Result<usize, Errno> {
2123 let mut bytes_written = 0;
2124 for (mapping, len) in self.get_contiguous_mappings_at(addr, bytes.len(), context)? {
2125 let next_offset = bytes_written + len;
2126 self.write_mapping_memory(
2127 (addr + bytes_written)?,
2128 mapping,
2129 &bytes[bytes_written..next_offset],
2130 context,
2131 )?;
2132 bytes_written = next_offset;
2133 }
2134
2135 if bytes_written != bytes.len() { error!(EFAULT) } else { Ok(bytes.len()) }
2136 }
2137
2138 fn write_mapping_memory(
2144 &self,
2145 addr: UserAddress,
2146 mapping: &Mapping,
2147 bytes: &[u8],
2148 context: &MappingContext,
2149 ) -> Result<(), Errno> {
2150 if !mapping.can_write() {
2151 return error!(EFAULT, "write_mapping_memory called on unwritable memory");
2152 }
2153 match self.get_mapping_backing(mapping) {
2154 MappingBacking::Memory(backing) => backing.write_memory(addr, bytes),
2155 MappingBacking::PrivateAnonymous => context.private_anonymous.write_memory(addr, bytes),
2156 }
2157 }
2158
2159 fn write_memory_partial(
2166 &self,
2167 addr: UserAddress,
2168 bytes: &[u8],
2169 context: &MappingContext,
2170 ) -> Result<usize, Errno> {
2171 let mut bytes_written = 0;
2172 for (mapping, len) in self.get_contiguous_mappings_at(addr, bytes.len(), context)? {
2173 let next_offset = bytes_written + len;
2174 if self
2175 .write_mapping_memory(
2176 (addr + bytes_written)?,
2177 mapping,
2178 &bytes[bytes_written..next_offset],
2179 context,
2180 )
2181 .is_err()
2182 {
2183 break;
2184 }
2185 bytes_written = next_offset;
2186 }
2187
2188 if !bytes.is_empty() && bytes_written == 0 { error!(EFAULT) } else { Ok(bytes.len()) }
2189 }
2190
2191 fn zero(
2192 &self,
2193 addr: UserAddress,
2194 length: usize,
2195 context: &MappingContext,
2196 ) -> Result<usize, Errno> {
2197 let mut bytes_written = 0;
2198 for (mapping, len) in self.get_contiguous_mappings_at(addr, length, context)? {
2199 let next_offset = bytes_written + len;
2200 if self.zero_mapping((addr + bytes_written)?, mapping, len, context).is_err() {
2201 break;
2202 }
2203 bytes_written = next_offset;
2204 }
2205
2206 if length != bytes_written { error!(EFAULT) } else { Ok(length) }
2207 }
2208
2209 fn zero_mapping(
2210 &self,
2211 addr: UserAddress,
2212 mapping: &Mapping,
2213 length: usize,
2214 context: &MappingContext,
2215 ) -> Result<usize, Errno> {
2216 if !mapping.can_write() {
2217 return error!(EFAULT);
2218 }
2219
2220 match self.get_mapping_backing(mapping) {
2221 MappingBacking::Memory(backing) => backing.zero(addr, length),
2222 MappingBacking::PrivateAnonymous => context.private_anonymous.zero(addr, length),
2223 }
2224 }
2225
2226 pub fn create_memory_backing(
2227 &self,
2228 base: UserAddress,
2229 memory: Arc<MemoryObject>,
2230 memory_offset: u64,
2231 ) -> MappingBacking {
2232 MappingBacking::Memory(Box::new(MappingBackingMemory::new(base, memory, memory_offset)))
2233 }
2234
2235 pub fn get_mapping_backing<'a>(&self, mapping: &'a Mapping) -> &'a MappingBacking {
2236 mapping.get_backing_internal()
2237 }
2238
2239 fn get_aio_context(&self, addr: UserAddress) -> Option<(Range<UserAddress>, Arc<AioContext>)> {
2240 let Some((range, mapping)) = self.mappings.get(addr) else {
2241 return None;
2242 };
2243 let MappingNameRef::AioContext(ref aio_context) = mapping.name() else {
2244 return None;
2245 };
2246 if !mapping.can_read() {
2247 return None;
2248 }
2249 Some((range.clone(), Arc::clone(aio_context)))
2250 }
2251
2252 fn find_uffd(&self, addr: UserAddress) -> Option<Arc<UserFault>> {
2253 for userfault in self.userfaultfds.iter() {
2254 if let Some(userfault) = userfault.upgrade() {
2255 if userfault.contains_addr(addr) {
2256 return Some(userfault);
2257 }
2258 }
2259 }
2260 None
2261 }
2262
2263 fn cache_flush(
2264 &self,
2265 range: Range<UserAddress>,
2266 context: &MappingContext,
2267 ) -> Result<(), Errno> {
2268 let mut addr = range.start;
2269 let size = range.end - range.start;
2270 for (mapping, len) in self.get_contiguous_mappings_at(addr, size, context)? {
2271 if !mapping.can_read() {
2272 return error!(EFAULT);
2273 }
2274 if mapping.mapping_mode() == MappingMode::Lazy {
2275 addr = (addr + len)?;
2276 continue;
2277 }
2278 zx::Status::ok(unsafe {
2280 zx::sys::zx_cache_flush(
2281 addr.ptr() as *const u8,
2282 len,
2283 zx::sys::ZX_CACHE_FLUSH_DATA | zx::sys::ZX_CACHE_FLUSH_INSN,
2284 )
2285 })
2286 .map_err(impossible_error)?;
2287
2288 addr = (addr + len).unwrap(); }
2290 if addr != range.end { error!(EFAULT) } else { Ok(()) }
2292 }
2293
2294 pub fn register_membarrier_private_expedited(
2297 &mut self,
2298 mtype: MembarrierType,
2299 ) -> Result<(), Errno> {
2300 let registrations = &mut self.forkable_state.membarrier_registrations;
2301 match mtype {
2302 MembarrierType::Memory => {
2303 registrations.memory = true;
2304 }
2305 MembarrierType::SyncCore => {
2306 registrations.sync_core = true;
2307 }
2308 }
2309 Ok(())
2310 }
2311
2312 pub fn membarrier_private_expedited_registered(&self, mtype: MembarrierType) -> bool {
2315 let registrations = &self.forkable_state.membarrier_registrations;
2316 match mtype {
2317 MembarrierType::Memory => registrations.memory,
2318 MembarrierType::SyncCore => registrations.sync_core,
2319 }
2320 }
2321
2322 fn force_write_memory(
2323 &mut self,
2324 context: &MappingContext,
2325 addr: UserAddress,
2326 bytes: &[u8],
2327 released_mappings: &mut ReleasedMappings,
2328 ) -> Result<(), Errno> {
2329 let (range, mapping) = {
2330 let (r, m) = self.mappings.get(addr).ok_or_else(|| errno!(EFAULT))?;
2331 (r.clone(), m.clone())
2332 };
2333 if range.end < addr.saturating_add(bytes.len()) {
2334 track_stub!(
2335 TODO("https://fxbug.dev/445790710"),
2336 "ptrace poke across multiple mappings"
2337 );
2338 return error!(EFAULT);
2339 }
2340
2341 if mapping.flags().contains(MappingFlags::SHARED) {
2343 if !mapping.can_write() {
2344 return error!(EIO);
2346 }
2347 return self.write_mapping_memory(addr, &mapping, &bytes, context);
2348 }
2349
2350 let backing = match self.get_mapping_backing(&mapping) {
2351 MappingBacking::PrivateAnonymous => {
2352 return context.private_anonymous.write_memory(addr, &bytes);
2354 }
2355 MappingBacking::Memory(backing) => backing,
2356 };
2357
2358 let vmo = backing.memory().as_vmo().ok_or_else(|| errno!(EFAULT))?;
2359 let addr_offset = backing.address_to_offset(addr);
2360 let can_exec =
2361 vmo.basic_info().expect("get VMO handle info").rights.contains(Rights::EXECUTE);
2362
2363 match vmo.write(&bytes, addr_offset) {
2365 Ok(()) => {
2366 if can_exec {
2367 system_barrier(BarrierType::InstructionStream);
2369 }
2370 return Ok(());
2371 }
2372
2373 Err(zx::Status::ACCESS_DENIED) => { }
2374
2375 Err(status) => {
2376 return Err(MemoryManager::get_errno_for_vmo_err(status));
2377 }
2378 }
2379
2380 let mapping_offset = backing.address_to_offset(range.start);
2382 let len = range.end - range.start;
2383
2384 let size = vmo.get_size().map_err(MemoryManager::get_errno_for_vmo_err)?;
2386 let child_vmo = vmo
2387 .create_child(VmoChildOptions::SNAPSHOT_AT_LEAST_ON_WRITE, 0, size)
2388 .map_err(MemoryManager::get_errno_for_vmo_err)?;
2389
2390 child_vmo.write(&bytes, addr_offset).map_err(MemoryManager::get_errno_for_vmo_err)?;
2392
2393 let child_vmo = if can_exec {
2396 child_vmo
2397 .replace_as_executable(&VMEX_RESOURCE)
2398 .map_err(MemoryManager::get_errno_for_vmo_err)?
2399 } else {
2400 child_vmo
2401 };
2402
2403 self.ensure_range_mapped_in_user_vmar(addr, None, context)?;
2408
2409 let memory = Arc::new(MemoryObject::from(child_vmo));
2411 context.map_in_user_vmar(
2412 SelectedAddress::FixedOverwrite(range.start),
2413 &memory,
2414 mapping_offset,
2415 len,
2416 mapping.flags(),
2417 false,
2418 )?;
2419
2420 let new_backing = MappingBackingMemory::new(range.start, memory, mapping_offset);
2422
2423 let mut new_mapping = mapping.clone();
2424 new_mapping.set_backing_internal(MappingBacking::Memory(Box::new(new_backing)));
2425
2426 released_mappings.extend(self.mappings.insert(range, new_mapping));
2427
2428 Ok(())
2429 }
2430
2431 fn set_brk(
2432 &mut self,
2433 current_task: &CurrentTask,
2434 mm: &Arc<MemoryManager>,
2435 addr: UserAddress,
2436 released_mappings: &mut ReleasedMappings,
2437 ) -> Result<UserAddress, Errno> {
2438 let rlimit_data = std::cmp::min(
2439 PROGRAM_BREAK_LIMIT,
2440 current_task.thread_group().get_rlimit(Resource::DATA),
2441 );
2442
2443 let brk = match self.brk.clone() {
2444 None => {
2445 let brk = ProgramBreak { base: self.brk_origin, current: self.brk_origin };
2446 self.brk = Some(brk.clone());
2447 brk
2448 }
2449 Some(brk) => brk,
2450 };
2451
2452 let Ok(last_address) = brk.base + rlimit_data else {
2453 return Ok(brk.current);
2456 };
2457
2458 if addr < brk.base || addr > last_address {
2459 return Ok(brk.current);
2462 }
2463
2464 let old_end = brk.current.round_up(*PAGE_SIZE).unwrap();
2465 let new_end = addr.round_up(*PAGE_SIZE).unwrap();
2466
2467 match new_end.cmp(&old_end) {
2468 std::cmp::Ordering::Less => {
2469 let delta = old_end - new_end;
2473
2474 if self.unmap(mm, new_end, delta, released_mappings).is_err() {
2475 return Ok(brk.current);
2476 }
2477 }
2478 std::cmp::Ordering::Greater => {
2479 let range = old_end..new_end;
2480 let delta = new_end - old_end;
2481
2482 if self.mappings.range(range).next().is_some() {
2484 return Ok(brk.current);
2485 }
2486
2487 if self
2488 .map_anonymous(
2489 mm,
2490 DesiredAddress::FixedOverwrite(old_end),
2491 delta,
2492 ProtectionFlags::READ | ProtectionFlags::WRITE,
2493 MappingOptions::ANONYMOUS,
2494 MappingName::Heap,
2495 released_mappings,
2496 )
2497 .is_err()
2498 {
2499 return Ok(brk.current);
2500 }
2501 }
2502 _ => {}
2503 };
2504
2505 let mut new_brk = brk;
2507 new_brk.current = addr;
2508 self.brk = Some(new_brk);
2509
2510 Ok(addr)
2511 }
2512
2513 fn register_with_uffd(
2514 &mut self,
2515 mm: &MemoryManager,
2516 addr: UserAddress,
2517 length: usize,
2518 userfault: &Arc<UserFault>,
2519 mode: FaultRegisterMode,
2520 released_mappings: &mut ReleasedMappings,
2521 ) -> Result<(), Errno> {
2522 let end_addr = addr.checked_add(length).ok_or_else(|| errno!(EINVAL))?;
2523 let range_for_op = addr..end_addr;
2524 let mut updates = vec![];
2525
2526 for (range, mapping) in self.mappings.range(range_for_op.clone()) {
2527 if !mapping.private_anonymous() {
2528 track_stub!(TODO("https://fxbug.dev/391599171"), "uffd for shmem and hugetlbfs");
2529 return error!(EINVAL);
2530 }
2531 if mapping.flags().contains(MappingFlags::UFFD) {
2532 return error!(EBUSY);
2533 }
2534 let range = range.intersect(&range_for_op);
2535 let mut mapping = mapping.clone();
2536 mapping.set_uffd(mode);
2537 updates.push((range, mapping));
2538 }
2539 if updates.is_empty() {
2540 return error!(EINVAL);
2541 }
2542
2543 mm.protect_vmar_range(addr, length, ProtectionFlags::empty())
2544 .expect("Failed to remove protections on uffd-registered range");
2545
2546 for (range, mapping) in updates {
2548 released_mappings.extend(self.mappings.insert(range, mapping));
2549 }
2550
2551 userfault.insert_pages(range_for_op, false);
2552
2553 Ok(())
2554 }
2555
2556 fn unregister_range_from_uffd(
2557 &mut self,
2558 mm: &MemoryManager,
2559 userfault: &Arc<UserFault>,
2560 addr: UserAddress,
2561 length: usize,
2562 released_mappings: &mut ReleasedMappings,
2563 ) -> Result<(), Errno> {
2564 let end_addr = addr.checked_add(length).ok_or_else(|| errno!(EINVAL))?;
2565 let range_for_op = addr..end_addr;
2566 let mut updates = vec![];
2567
2568 for (range, mapping) in self.mappings.range(range_for_op.clone()) {
2569 if !mapping.private_anonymous() {
2570 track_stub!(TODO("https://fxbug.dev/391599171"), "uffd for shmem and hugetlbfs");
2571 return error!(EINVAL);
2572 }
2573 if mapping.flags().contains(MappingFlags::UFFD) {
2574 let range = range.intersect(&range_for_op);
2575 if userfault.remove_pages(range.clone()) {
2576 let mut mapping = mapping.clone();
2577 mapping.clear_uffd();
2578 updates.push((range, mapping));
2579 }
2580 }
2581 }
2582 for (range, mapping) in updates {
2583 let length = range.end - range.start;
2584 let restored_flags = mapping.flags().access_flags();
2585
2586 released_mappings.extend(self.mappings.insert(range.clone(), mapping));
2587
2588 mm.protect_vmar_range(range.start, length, restored_flags)
2589 .expect("Failed to restore original protection bits on uffd-registered range");
2590 }
2591 Ok(())
2592 }
2593
2594 fn unregister_uffd(
2595 &mut self,
2596 mm: &MemoryManager,
2597 userfault: &Arc<UserFault>,
2598 released_mappings: &mut ReleasedMappings,
2599 ) {
2600 let mut updates = vec![];
2601
2602 for (range, mapping) in self.mappings.iter() {
2603 if mapping.flags().contains(MappingFlags::UFFD) {
2604 for range in userfault.get_registered_pages_overlapping_range(range.clone()) {
2605 let mut mapping = mapping.clone();
2606 mapping.clear_uffd();
2607 updates.push((range.clone(), mapping));
2608 }
2609 }
2610 }
2611 for (range, mapping) in updates {
2613 let length = range.end - range.start;
2614 let restored_flags = mapping.flags().access_flags();
2615 released_mappings.extend(self.mappings.insert(range.clone(), mapping));
2616 mm.protect_vmar_range(range.start, length, restored_flags)
2618 .expect("Failed to restore original protection bits on uffd-registered range");
2619 }
2620
2621 userfault.remove_pages(
2622 UserAddress::from_ptr(RESTRICTED_ASPACE_BASE)
2623 ..UserAddress::from_ptr(RESTRICTED_ASPACE_HIGHEST_ADDRESS),
2624 );
2625
2626 let weak_userfault = Arc::downgrade(userfault);
2627 self.userfaultfds.retain(|uf| !Weak::ptr_eq(uf, &weak_userfault));
2628 }
2629
2630 fn set_mapping_name(
2631 &mut self,
2632 addr: UserAddress,
2633 length: usize,
2634 name: Option<FsString>,
2635 released_mappings: &mut ReleasedMappings,
2636 ) -> Result<(), Errno> {
2637 if addr.ptr() % *PAGE_SIZE as usize != 0 {
2638 return error!(EINVAL);
2639 }
2640 let end = match addr.checked_add(length) {
2641 Some(addr) => addr.round_up(*PAGE_SIZE).map_err(|_| errno!(ENOMEM))?,
2642 None => return error!(EINVAL),
2643 };
2644
2645 let mappings_in_range =
2646 self.mappings.range(addr..end).map(|(r, m)| (r.clone(), m.clone())).collect::<Vec<_>>();
2647
2648 if mappings_in_range.is_empty() {
2649 return error!(EINVAL);
2650 }
2651 if !mappings_in_range.first().unwrap().0.contains(&addr) {
2652 return error!(ENOMEM);
2653 }
2654
2655 let mut last_range_end = None;
2656 for (mut range, mut mapping) in mappings_in_range {
2660 if mapping.name().is_file() {
2661 return error!(EBADF);
2663 }
2664 range.start = std::cmp::max(range.start, addr);
2666 range.end = std::cmp::min(range.end, end);
2668
2669 if let Some(last_range_end) = last_range_end {
2670 if last_range_end != range.start {
2671 return error!(ENOMEM);
2673 }
2674 }
2675 last_range_end = Some(range.end.round_up(*PAGE_SIZE)?);
2676 if let MappingBacking::Memory(backing) = self.get_mapping_backing(&mapping) {
2679 match &name {
2680 Some(memory_name) => {
2681 backing.memory().set_zx_name(memory_name);
2682 }
2683 None => {
2684 backing.memory().set_zx_name(b"");
2685 }
2686 }
2687 }
2688 mapping.set_name(match &name {
2689 Some(name) => MappingName::Vma(FlyByteStr::new(name.as_bytes())),
2690 None => MappingName::None,
2691 });
2692 released_mappings.extend(self.mappings.insert(range, mapping));
2693 }
2694 if let Some(last_range_end) = last_range_end {
2695 if last_range_end < end {
2696 return error!(ENOMEM);
2698 }
2699 }
2700 Ok(())
2701 }
2702}
2703
2704pub struct MlockShadowProcess(memory_pinning::ShadowProcess);
2709
2710impl MemoryManager {
2711 pub fn ensure_range_mapped_in_user_vmar(
2716 &self,
2717 addr: UserAddress,
2718 length: Option<usize>,
2719 ) -> Result<bool, Errno> {
2720 if !self.state.read().any_ranges_lazy(std::iter::once((addr, length))) {
2721 return Ok(false);
2722 }
2723 self.state.write().ensure_ranges_mapped_in_user_vmar(
2724 std::iter::once((addr, length)),
2725 &self.mapping_context,
2726 )
2727 }
2728
2729 pub fn ensure_ranges_mapped_in_user_vmar<I>(&self, ranges: I) -> Result<bool, Errno>
2734 where
2735 I: IntoIterator<Item = (UserAddress, Option<usize>)>,
2736 {
2737 let ranges = ranges.into_iter().collect::<SmallVec<[_; 4]>>();
2740 if !self.state.read().any_ranges_lazy(ranges.iter().cloned()) {
2741 return Ok(false);
2742 }
2743 self.state.write().ensure_ranges_mapped_in_user_vmar(ranges, &self.mapping_context)
2744 }
2745
2746 pub fn mrelease(&self) -> Result<(), Errno> {
2747 self.mapping_context.private_anonymous.zero(
2748 UserAddress::from_ptr(self.mapping_context.user_vmar_info.base),
2749 self.mapping_context.user_vmar_info.len,
2750 )?;
2751 Ok(())
2752 }
2753
2754 pub fn summarize(&self, summary: &mut crate::mm::MappingSummary) {
2755 let state = self.state.read();
2756 for (_, mapping) in state.mappings.iter() {
2757 summary.add(&state, mapping);
2758 }
2759 }
2760
2761 pub fn get_mappings_for_vmsplice(
2762 self: &Arc<MemoryManager>,
2763 buffers: &UserBuffers,
2764 ) -> Result<Vec<Arc<VmsplicePayload>>, Errno> {
2765 self.state.read().get_mappings_for_vmsplice(self, buffers)
2766 }
2767
2768 pub fn has_same_address_space(&self, other: &Self) -> bool {
2769 std::ptr::eq(self, other)
2770 }
2771
2772 fn unified_transfer_loop<F>(
2773 &self,
2774 addr: UserAddress,
2775 len: usize,
2776 mut transfer_fn: F,
2777 ) -> Result<usize, Errno>
2778 where
2779 F: FnMut(UserAddress, usize) -> Result<ControlFlow<usize, usize>, Errno>,
2780 {
2781 let mut copied = 0;
2782 while copied < len {
2783 match transfer_fn((addr + copied)?, copied)? {
2784 ControlFlow::Continue(num_copied) => {
2785 if num_copied == 0 {
2786 let fault_addr = (addr + copied)?;
2787 if self.ensure_range_mapped_in_user_vmar(fault_addr, None)? {
2798 continue;
2799 } else {
2800 break;
2801 }
2802 }
2803 copied += num_copied;
2804 }
2805 ControlFlow::Break(num_copied) => {
2806 copied += num_copied;
2807 break;
2808 }
2809 }
2810 }
2811 Ok(copied)
2812 }
2813
2814 pub fn unified_read_memory<'a>(
2815 &self,
2816 current_task: &CurrentTask,
2817 addr: UserAddress,
2818 bytes: &'a mut [MaybeUninit<u8>],
2819 ) -> Result<&'a mut [u8], Errno> {
2820 debug_assert!(self.has_same_address_space(¤t_task.mm().unwrap()));
2821
2822 if let Some(usercopy) = usercopy() {
2823 let buf_ptr = bytes.as_mut_ptr();
2824 let buf_len = bytes.len();
2825
2826 let copied = self.unified_transfer_loop(addr, buf_len, |cur_addr, offset| {
2827 let current_bytes = unsafe {
2829 std::slice::from_raw_parts_mut(buf_ptr.add(offset), buf_len - offset)
2830 };
2831 let (read_bytes, _unread_bytes) = usercopy.copyin(cur_addr.ptr(), current_bytes);
2832 Ok(ControlFlow::Continue(read_bytes.len()))
2833 })?;
2834 if copied < bytes.len() {
2835 error!(EFAULT)
2836 } else {
2837 Ok(unsafe { std::slice::from_raw_parts_mut(buf_ptr as *mut u8, buf_len) })
2839 }
2840 } else {
2841 self.syscall_read_memory(addr, bytes)
2842 }
2843 }
2844
2845 pub fn syscall_read_memory<'a>(
2846 &self,
2847 addr: UserAddress,
2848 bytes: &'a mut [MaybeUninit<u8>],
2849 ) -> Result<&'a mut [u8], Errno> {
2850 self.state.read().read_memory(addr, bytes, &self.mapping_context)
2851 }
2852
2853 pub fn unified_read_memory_partial_until_null_byte<'a>(
2854 &self,
2855 current_task: &CurrentTask,
2856 addr: UserAddress,
2857 bytes: &'a mut [MaybeUninit<u8>],
2858 ) -> Result<&'a mut [u8], Errno> {
2859 debug_assert!(self.has_same_address_space(¤t_task.mm().unwrap()));
2860
2861 if let Some(usercopy) = usercopy() {
2862 let buf_ptr = bytes.as_mut_ptr();
2863 let buf_len = bytes.len();
2864
2865 let copied = self.unified_transfer_loop(addr, buf_len, |cur_addr, offset| {
2866 let current_bytes = unsafe {
2868 std::slice::from_raw_parts_mut(buf_ptr.add(offset), buf_len - offset)
2869 };
2870 let (read_bytes, _unread_bytes) =
2871 usercopy.copyin_until_null_byte(cur_addr.ptr(), current_bytes);
2872
2873 let num_copied = read_bytes.len();
2874 if read_bytes.last().map(|b| *b == 0).unwrap_or(false) {
2875 Ok(ControlFlow::Break(num_copied))
2876 } else {
2877 Ok(ControlFlow::Continue(num_copied))
2878 }
2879 })?;
2880 if copied == 0 && !bytes.is_empty() {
2881 error!(EFAULT)
2882 } else {
2883 Ok(unsafe { std::slice::from_raw_parts_mut(buf_ptr as *mut u8, copied) })
2885 }
2886 } else {
2887 self.syscall_read_memory_partial_until_null_byte(addr, bytes)
2888 }
2889 }
2890
2891 pub fn syscall_read_memory_partial_until_null_byte<'a>(
2892 &self,
2893 addr: UserAddress,
2894 bytes: &'a mut [MaybeUninit<u8>],
2895 ) -> Result<&'a mut [u8], Errno> {
2896 self.state.read().read_memory_partial_until_null_byte(addr, bytes, &self.mapping_context)
2897 }
2898
2899 pub fn unified_read_memory_partial<'a>(
2900 &self,
2901 current_task: &CurrentTask,
2902 addr: UserAddress,
2903 bytes: &'a mut [MaybeUninit<u8>],
2904 ) -> Result<&'a mut [u8], Errno> {
2905 debug_assert!(self.has_same_address_space(¤t_task.mm().unwrap()));
2906
2907 if let Some(usercopy) = usercopy() {
2908 let buf_ptr = bytes.as_mut_ptr();
2909 let buf_len = bytes.len();
2910
2911 let copied = self.unified_transfer_loop(addr, buf_len, |cur_addr, offset| {
2912 let current_bytes = unsafe {
2914 std::slice::from_raw_parts_mut(buf_ptr.add(offset), buf_len - offset)
2915 };
2916 let (read_bytes, _unread_bytes) = usercopy.copyin(cur_addr.ptr(), current_bytes);
2917 Ok(ControlFlow::Continue(read_bytes.len()))
2918 })?;
2919 if copied == 0 && !bytes.is_empty() {
2920 error!(EFAULT)
2921 } else {
2922 Ok(unsafe { std::slice::from_raw_parts_mut(buf_ptr as *mut u8, copied) })
2924 }
2925 } else {
2926 self.syscall_read_memory_partial(addr, bytes)
2927 }
2928 }
2929
2930 pub fn syscall_read_memory_partial<'a>(
2931 &self,
2932 addr: UserAddress,
2933 bytes: &'a mut [MaybeUninit<u8>],
2934 ) -> Result<&'a mut [u8], Errno> {
2935 self.state.read().read_memory_partial(addr, bytes, &self.mapping_context)
2936 }
2937
2938 pub fn unified_write_memory(
2939 &self,
2940 current_task: &CurrentTask,
2941 addr: UserAddress,
2942 bytes: &[u8],
2943 ) -> Result<usize, Errno> {
2944 debug_assert!(self.has_same_address_space(¤t_task.mm().unwrap()));
2945
2946 if let Some(usercopy) = usercopy() {
2947 let len = bytes.len();
2948 let copied = self.unified_transfer_loop(addr, len, |cur_addr, offset| {
2949 Ok(ControlFlow::Continue(usercopy.copyout(&bytes[offset..], cur_addr.ptr())))
2950 })?;
2951 if copied < bytes.len() { error!(EFAULT) } else { Ok(copied) }
2952 } else {
2953 self.syscall_write_memory(addr, bytes)
2954 }
2955 }
2956
2957 pub fn force_write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<(), Errno> {
2963 let mut state = self.state.write();
2964 let mut released_mappings = ReleasedMappings::default();
2965 let result =
2966 state.force_write_memory(&self.mapping_context, addr, bytes, &mut released_mappings);
2967 released_mappings.finalize(state);
2968 result
2969 }
2970
2971 pub fn syscall_write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno> {
2972 self.state.read().write_memory(addr, bytes, &self.mapping_context)
2973 }
2974
2975 pub fn unified_write_memory_partial(
2976 &self,
2977 current_task: &CurrentTask,
2978 addr: UserAddress,
2979 bytes: &[u8],
2980 ) -> Result<usize, Errno> {
2981 debug_assert!(self.has_same_address_space(¤t_task.mm().unwrap()));
2982
2983 if let Some(usercopy) = usercopy() {
2984 let len = bytes.len();
2985 let copied = self.unified_transfer_loop(addr, len, |cur_addr, offset| {
2986 Ok(ControlFlow::Continue(usercopy.copyout(&bytes[offset..], cur_addr.ptr())))
2987 })?;
2988 if copied == 0 && !bytes.is_empty() { error!(EFAULT) } else { Ok(copied) }
2989 } else {
2990 self.syscall_write_memory_partial(addr, bytes)
2991 }
2992 }
2993
2994 pub fn syscall_write_memory_partial(
2995 &self,
2996 addr: UserAddress,
2997 bytes: &[u8],
2998 ) -> Result<usize, Errno> {
2999 self.state.read().write_memory_partial(addr, bytes, &self.mapping_context)
3000 }
3001
3002 pub fn unified_zero(
3003 &self,
3004 current_task: &CurrentTask,
3005 addr: UserAddress,
3006 length: usize,
3007 ) -> Result<usize, Errno> {
3008 debug_assert!(self.has_same_address_space(¤t_task.mm().unwrap()));
3009
3010 {
3011 let page_size = *PAGE_SIZE as usize;
3012 let next_page_boundary = round_up_to_system_page_size(addr.ptr())?;
3015 let length_with_atleast_one_full_page = page_size + (next_page_boundary - addr.ptr());
3018 if length >= length_with_atleast_one_full_page {
3025 return self.syscall_zero(addr, length);
3026 }
3027 }
3028
3029 if let Some(usercopy) = usercopy() {
3030 let copied = self.unified_transfer_loop(addr, length, |cur_addr, offset| {
3031 Ok(ControlFlow::Continue(usercopy.zero(cur_addr.ptr(), length - offset)))
3032 })?;
3033 if copied == 0 && length > 0 { error!(EFAULT) } else { Ok(copied) }
3034 } else {
3035 self.syscall_zero(addr, length)
3036 }
3037 }
3038
3039 pub fn syscall_zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno> {
3040 self.state.read().zero(addr, length, &self.mapping_context)
3041 }
3042
3043 pub fn cache_flush(&self, range: Range<UserAddress>) -> Result<(), Errno> {
3045 self.state.read().cache_flush(range, &self.mapping_context)
3046 }
3047
3048 pub fn register_membarrier_private_expedited(
3051 &self,
3052 mtype: MembarrierType,
3053 ) -> Result<(), Errno> {
3054 self.state.write().register_membarrier_private_expedited(mtype)
3055 }
3056
3057 pub fn membarrier_private_expedited_registered(&self, mtype: MembarrierType) -> bool {
3060 self.state.read().membarrier_private_expedited_registered(mtype)
3061 }
3062}
3063
3064pub struct MappingContext {
3074 pub user_vmar: zx::Vmar,
3084
3085 pub user_vmar_info: zx::VmarInfo,
3087
3088 pub private_anonymous: PrivateAnonymousMemoryManager,
3090}
3091
3092impl MappingContext {
3093 fn map_in_user_vmar(
3094 &self,
3095 addr: SelectedAddress,
3096 memory: &MemoryObject,
3097 memory_offset: u64,
3098 length: usize,
3099 flags: MappingFlags,
3100 populate: bool,
3101 ) -> Result<(), Errno> {
3102 map_in_vmar(
3103 &self.user_vmar,
3104 &self.user_vmar_info,
3105 addr,
3106 memory,
3107 memory_offset,
3108 length,
3109 flags,
3110 populate,
3111 )
3112 }
3113
3114 pub fn max_address(&self) -> UserAddress {
3115 UserAddress::from_ptr(self.user_vmar_info.base + self.user_vmar_info.len)
3116 }
3117}
3118
3119pub struct MemoryManager {
3120 pub base_addr: UserAddress,
3122
3123 pub futex: Arc<FutexTable<PrivateFutexKey>>,
3125
3126 pub mapping_context: MappingContext,
3128
3129 pub state: RwLock<MemoryManagerState>,
3131
3132 pub dumpable: LockDepMutex<DumpPolicy, MmDumpable>,
3134
3135 pub maximum_valid_user_address: UserAddress,
3137
3138 pub inflight_vmspliced_payloads: InflightVmsplicedPayloads,
3147
3148 pub drop_notifier: DropNotifier,
3150
3151 pub arch_width: ArchWidth,
3153}
3154
3155impl ArchSpecific for MemoryManager {
3156 fn is_arch32(&self) -> bool {
3157 self.arch_width.is_arch32()
3158 }
3159}
3160
3161fn check_access_permissions_in_page_fault(
3162 decoded: &PageFaultExceptionReport,
3163 mapping: &Mapping,
3164) -> bool {
3165 let exec_denied = decoded.is_execute && !mapping.can_exec();
3166 let write_denied = decoded.is_write && !mapping.can_write();
3167 let read_denied = (!decoded.is_execute && !decoded.is_write) && !mapping.can_read();
3168 !exec_denied && !write_denied && !read_denied
3169}
3170
3171impl MemoryManager {
3172 pub fn new_for_test(root_vmar: zx::Unowned<'_, zx::Vmar>, arch_width: ArchWidth) -> Arc<Self> {
3174 Self::new(root_vmar, arch_width, None, None).expect("can create MemoryManager")
3175 }
3176
3177 fn with_zx_mappings<R>(
3180 &self,
3181 current_task: &CurrentTask,
3182 op: impl FnOnce(&[zx::MapInfo]) -> R,
3183 ) -> R {
3184 MapInfoCache::get_or_init(current_task)
3185 .expect("must be able to retrieve map info cache")
3186 .with_map_infos(&self.mapping_context.user_vmar, |infos| match infos {
3187 Ok(infos) => op(infos),
3188 Err(_) => op(&[]),
3189 })
3190 }
3191
3192 fn protect_vmar_range(
3193 &self,
3194 addr: UserAddress,
3195 length: usize,
3196 prot_flags: ProtectionFlags,
3197 ) -> Result<(), Errno> {
3198 let vmar_flags = prot_flags.to_vmar_flags();
3199 unsafe { self.mapping_context.user_vmar.protect(addr.ptr(), length, vmar_flags) }.map_err(
3201 |s| match s {
3202 zx::Status::INVALID_ARGS => errno!(EINVAL),
3203 zx::Status::NOT_FOUND => errno!(ENOMEM),
3204 zx::Status::ACCESS_DENIED => errno!(EACCES),
3205 _ => impossible_error(s),
3206 },
3207 )
3208 }
3209
3210 pub fn total_locked_bytes(&self) -> u64 {
3211 self.state.read().num_locked_bytes(
3212 UserAddress::from(self.mapping_context.user_vmar_info.base as u64)
3213 ..UserAddress::from(
3214 (self.mapping_context.user_vmar_info.base
3215 + self.mapping_context.user_vmar_info.len) as u64,
3216 ),
3217 )
3218 }
3219
3220 fn new(
3224 root_vmar: zx::Unowned<'_, zx::Vmar>,
3225 arch_width: ArchWidth,
3226 executable_node: Option<NamespaceNode>,
3227 private_anonymous: Option<PrivateAnonymousMemoryManager>,
3228 ) -> Result<Arc<Self>, Errno> {
3229 debug_assert!(!root_vmar.is_invalid());
3230
3231 let mut vmar_info = root_vmar.info().map_err(|status| from_status_like_fdio!(status))?;
3232 if arch_width.is_arch32() {
3233 vmar_info.len = (LOWER_4GB_LIMIT.ptr() - vmar_info.base) as usize;
3234 }
3235
3236 let (user_vmar, ptr) = root_vmar
3237 .allocate(
3238 0,
3239 vmar_info.len,
3240 zx::VmarFlags::SPECIFIC
3241 | zx::VmarFlags::CAN_MAP_SPECIFIC
3242 | zx::VmarFlags::CAN_MAP_READ
3243 | zx::VmarFlags::CAN_MAP_WRITE
3244 | zx::VmarFlags::CAN_MAP_EXECUTE,
3245 )
3246 .map_err(|status| from_status_like_fdio!(status))?;
3247 assert_eq!(ptr, vmar_info.base);
3248
3249 let user_vmar_info = user_vmar.info().map_err(|status| from_status_like_fdio!(status))?;
3250
3251 debug_assert_eq!(RESTRICTED_ASPACE_BASE, user_vmar_info.base);
3253 if arch_width.is_arch32() {
3254 debug_assert_eq!(LOWER_4GB_LIMIT.ptr() - user_vmar_info.base, user_vmar_info.len);
3255 } else {
3256 debug_assert_eq!(RESTRICTED_ASPACE_SIZE, user_vmar_info.len);
3257 }
3258
3259 let backing_size = (user_vmar_info.base + user_vmar_info.len) as u64;
3264
3265 let stack_origin = UserAddress::from_ptr(
3268 user_vmar_info.base + user_vmar_info.len - generate_random_offset_for_aslr(arch_width),
3269 )
3270 .round_up(*PAGE_SIZE)?;
3271
3272 let mmap_top = stack_origin
3275 .checked_sub(MAX_STACK_SIZE + generate_random_offset_for_aslr(arch_width))
3276 .ok_or_else(|| errno!(EINVAL))?;
3277
3278 Ok(Arc::new(MemoryManager {
3279 base_addr: UserAddress::from_ptr(user_vmar_info.base),
3280 futex: Arc::<FutexTable<PrivateFutexKey>>::default(),
3281 mapping_context: MappingContext {
3282 user_vmar,
3283 user_vmar_info,
3284 private_anonymous: private_anonymous
3285 .unwrap_or_else(|| PrivateAnonymousMemoryManager::new(backing_size)),
3286 },
3287 state: MemoryManagerState {
3288 mappings: Default::default(),
3289 userfaultfds: Default::default(),
3290 shadow_mappings_for_mlock: Default::default(),
3291 forkable_state: MemoryManagerForkableState {
3292 executable_node,
3293 stack_origin,
3294 mmap_top,
3295 ..Default::default()
3296 },
3297 }
3298 .into(),
3299 dumpable: LockDepMutex::new(DumpPolicy::User),
3302 maximum_valid_user_address: UserAddress::from_ptr(
3303 user_vmar_info.base + user_vmar_info.len,
3304 ),
3305 inflight_vmspliced_payloads: Default::default(),
3306 drop_notifier: DropNotifier::default(),
3307 arch_width,
3308 }))
3309 }
3310
3311 pub fn set_brk(
3312 self: &Arc<Self>,
3313 current_task: &CurrentTask,
3314 addr: UserAddress,
3315 ) -> Result<UserAddress, Errno> {
3316 let mut state = self.state.write();
3317 let mut released_mappings = ReleasedMappings::default();
3318 let result = state.set_brk(current_task, self, addr, &mut released_mappings);
3319 released_mappings.finalize(state);
3320 result
3321 }
3322
3323 pub fn register_uffd(&self, userfault: &Arc<UserFault>) {
3324 let mut state = self.state.write();
3325 state.userfaultfds.push(Arc::downgrade(userfault));
3326 }
3327
3328 pub fn register_with_uffd(
3330 self: &Arc<Self>,
3331 addr: UserAddress,
3332 length: usize,
3333 userfault: &Arc<UserFault>,
3334 mode: FaultRegisterMode,
3335 ) -> Result<(), Errno> {
3336 let mut state = self.state.write();
3337 let mut released_mappings = ReleasedMappings::default();
3338 let result =
3339 state.register_with_uffd(self, addr, length, userfault, mode, &mut released_mappings);
3340 released_mappings.finalize(state);
3341 result
3342 }
3343
3344 pub fn unregister_range_from_uffd(
3346 &self,
3347 userfault: &Arc<UserFault>,
3348 addr: UserAddress,
3349 length: usize,
3350 ) -> Result<(), Errno> {
3351 let mut state = self.state.write();
3352 let mut released_mappings = ReleasedMappings::default();
3353 let result =
3354 state.unregister_range_from_uffd(self, userfault, addr, length, &mut released_mappings);
3355 released_mappings.finalize(state);
3356 result
3357 }
3358
3359 pub fn unregister_uffd(&self, userfault: &Arc<UserFault>) {
3362 let mut state = self.state.write();
3363 let mut released_mappings = ReleasedMappings::default();
3364 state.unregister_uffd(self, userfault, &mut released_mappings);
3365 released_mappings.finalize(state);
3366 }
3367
3368 pub fn populate_from_uffd<F>(
3374 &self,
3375 addr: UserAddress,
3376 length: usize,
3377 userfault: &Arc<UserFault>,
3378 populate: F,
3379 ) -> Result<usize, Errno>
3380 where
3381 F: FnOnce(&MemoryManagerState, usize) -> Result<usize, Errno>,
3382 {
3383 let state = self.state.read();
3384 let mut bytes_registered_with_uffd = 0;
3387 for (mapping, len) in
3388 state.get_contiguous_mappings_at(addr, length, &self.mapping_context)?
3389 {
3390 if mapping.flags().contains(MappingFlags::UFFD) {
3391 if !userfault.contains_addr(addr) {
3394 track_stub!(
3395 TODO("https://fxbug.dev/391599171"),
3396 "operations across different uffds"
3397 );
3398 return error!(ENOTSUP);
3399 };
3400 } else {
3401 return error!(ENOENT);
3402 }
3403 bytes_registered_with_uffd += len;
3404 }
3405 if bytes_registered_with_uffd != length {
3406 return error!(ENOENT);
3407 }
3408
3409 let end_addr = addr.checked_add(length).ok_or_else(|| errno!(EINVAL))?;
3410
3411 let first_populated =
3413 userfault.get_first_populated_page_after(addr).ok_or_else(|| errno!(ENOENT))?;
3414 if first_populated == addr {
3416 return error!(EEXIST);
3417 }
3418 let trimmed_end = std::cmp::min(first_populated, end_addr);
3421 let effective_length = trimmed_end - addr;
3422
3423 populate(&state, effective_length)?;
3424 userfault.insert_pages(addr..trimmed_end, true);
3425
3426 for (range, mapping) in state.mappings.range(addr..trimmed_end) {
3431 let range_to_protect = range.intersect(&(addr..trimmed_end));
3432 let restored_flags = mapping.flags().access_flags();
3433 let length = range_to_protect.end - range_to_protect.start;
3434 self.protect_vmar_range(range_to_protect.start, length, restored_flags)
3435 .expect("Failed to restore original protection bits on uffd-registered range");
3436 }
3437 Ok(effective_length)
3440 }
3441
3442 pub fn zero_from_uffd(
3443 &self,
3444 addr: UserAddress,
3445 length: usize,
3446 userfault: &Arc<UserFault>,
3447 ) -> Result<usize, Errno> {
3448 self.populate_from_uffd(addr, length, userfault, |state, effective_length| {
3449 state.zero(addr, effective_length, &self.mapping_context)
3450 })
3451 }
3452
3453 pub fn fill_from_uffd(
3454 &self,
3455 addr: UserAddress,
3456 buf: &[u8],
3457 length: usize,
3458 userfault: &Arc<UserFault>,
3459 ) -> Result<usize, Errno> {
3460 self.populate_from_uffd(addr, length, userfault, |state, effective_length| {
3461 state.write_memory(addr, &buf[..effective_length], &self.mapping_context)
3462 })
3463 }
3464
3465 pub fn copy_from_uffd(
3466 &self,
3467 source_addr: UserAddress,
3468 dst_addr: UserAddress,
3469 length: usize,
3470 userfault: &Arc<UserFault>,
3471 ) -> Result<usize, Errno> {
3472 self.populate_from_uffd(dst_addr, length, userfault, |state, effective_length| {
3473 let mut buf = vec![std::mem::MaybeUninit::uninit(); effective_length];
3474 let buf = state.read_memory(source_addr, &mut buf, &self.mapping_context)?;
3475 state.write_memory(dst_addr, &buf[..effective_length], &self.mapping_context)
3476 })
3477 }
3478
3479 pub fn snapshot_of(
3483 source_mm: &Arc<MemoryManager>,
3484 root_vmar: zx::Unowned<'_, zx::Vmar>,
3485 arch_width: ArchWidth,
3486 ) -> Result<Arc<Self>, Errno> {
3487 fuchsia_trace::duration!(CATEGORY_STARNIX_MM, "snapshot_of");
3488 let backing_size = (source_mm.mapping_context.user_vmar_info.base
3489 + source_mm.mapping_context.user_vmar_info.len) as u64;
3490 let private_anonymous =
3491 source_mm.mapping_context.private_anonymous.snapshot(backing_size)?;
3492 let target = MemoryManager::new(
3493 root_vmar,
3494 arch_width,
3495 source_mm.executable_node(),
3496 Some(private_anonymous),
3497 )?;
3498
3499 {
3502 let (state, mut target_state) = ordered_write_lock(&source_mm.state, &target.state);
3503 debug_assert_eq!(
3504 source_mm.mapping_context.user_vmar_info,
3505 target.mapping_context.user_vmar_info
3506 );
3507
3508 let mut clone_cache = HashMap::<zx::Koid, Arc<MemoryObject>>::new();
3509
3510 for (range, mapping) in state.mappings.iter() {
3511 if mapping.flags().contains(MappingFlags::DONTFORK) {
3512 continue;
3513 }
3514 let target_mapping_flags = mapping.flags().difference(MappingFlags::LOCKED);
3516 match state.get_mapping_backing(mapping) {
3517 MappingBacking::Memory(backing) => {
3518 fuchsia_trace::duration!(CATEGORY_STARNIX_MM, "memory_backing_clone");
3519 let memory_offset = backing.address_to_offset(range.start);
3520
3521 let target_memory = if mapping.flags().contains(MappingFlags::SHARED)
3522 || mapping.name().is_vvar()
3523 {
3524 backing.memory().clone()
3527 } else {
3528 let memory_obj = backing.memory();
3529 let options = mapping.flags().options();
3530 let memory =
3531 clone_cache.entry(memory_obj.get_koid()).or_insert_with_fallible(
3532 || memory_obj.clone_memory(memory_obj.get_rights(), options),
3533 )?;
3534 memory.clone()
3535 };
3536
3537 let mapping = Mapping::with_name(
3538 MappingBacking::Memory(Box::new(MappingBackingMemory::new(
3539 range.start,
3540 target_memory,
3541 memory_offset,
3542 ))),
3543 target_mapping_flags,
3544 mapping.max_access(),
3545 mapping.name().to_owned(),
3546 MappingMode::Lazy,
3547 );
3548 assert!(
3549 target_state.mappings.append_non_overlapping(range.clone(), mapping)
3550 );
3551 }
3552 MappingBacking::PrivateAnonymous => {
3553 fuchsia_trace::duration!(
3554 CATEGORY_STARNIX_MM,
3555 "private_anonymous_backing_clone"
3556 );
3557 let length = range.end - range.start;
3558 if mapping.flags().contains(MappingFlags::WIPEONFORK) {
3559 target
3560 .mapping_context
3561 .private_anonymous
3562 .zero(range.start, length)
3563 .map_err(|_| errno!(ENOMEM))?;
3564 }
3565
3566 let mapping = Mapping::new_private_anonymous(
3567 target_mapping_flags,
3568 mapping.name().to_owned(),
3569 MappingMode::Lazy,
3570 );
3571 assert!(
3572 target_state.mappings.append_non_overlapping(range.clone(), mapping)
3573 );
3574 }
3575 };
3576 }
3577
3578 target_state.forkable_state = state.forkable_state.clone();
3579 }
3580
3581 let self_dumpable = *source_mm.dumpable.lock();
3582 *target.dumpable.lock() = self_dumpable;
3583
3584 Ok(target)
3585 }
3586
3587 pub fn exec(
3596 root_vmar: zx::Unowned<'_, zx::Vmar>,
3597 old_mm: Option<Arc<Self>>,
3598 exe_node: NamespaceNode,
3599 arch_width: ArchWidth,
3600 ) -> Result<Arc<Self>, Errno> {
3601 if let Some(old_mm) = old_mm {
3609 let _old_mappings = {
3610 let mut state = old_mm.state.write();
3611
3612 unsafe {
3615 old_mm
3616 .mapping_context
3617 .user_vmar
3618 .destroy()
3619 .map_err(|status| from_status_like_fdio!(status))?
3620 }
3621
3622 std::mem::replace(&mut state.mappings, Default::default())
3623 };
3624 }
3625
3626 Self::new(root_vmar, arch_width, Some(exe_node), None)
3627 }
3628
3629 pub fn initialize_brk_origin(
3630 &self,
3631 arch_width: ArchWidth,
3632 executable_end: UserAddress,
3633 ) -> Result<(), Errno> {
3634 self.state.write().brk_origin = executable_end
3635 .checked_add(generate_random_offset_for_aslr(arch_width))
3636 .ok_or_else(|| errno!(EINVAL))?;
3637 Ok(())
3638 }
3639
3640 pub fn get_random_base_for_executable(
3642 &self,
3643 arch_width: ArchWidth,
3644 length: usize,
3645 ) -> Result<UserAddress, Errno> {
3646 let state = self.state.read();
3647
3648 let base = round_up_to_system_page_size(2 * state.mmap_top.ptr() / 3).unwrap()
3650 + generate_random_offset_for_aslr(arch_width);
3651 if base.checked_add(length).ok_or_else(|| errno!(EINVAL))? <= state.mmap_top.ptr() {
3652 Ok(UserAddress::from_ptr(base))
3653 } else {
3654 error!(EINVAL)
3655 }
3656 }
3657 pub fn executable_node(&self) -> Option<NamespaceNode> {
3658 self.state.read().executable_node.clone()
3659 }
3660
3661 #[track_caller]
3662 pub fn get_errno_for_map_err(status: zx::Status) -> Errno {
3663 match status {
3664 zx::Status::INVALID_ARGS => errno!(EINVAL),
3665 zx::Status::ACCESS_DENIED => errno!(EPERM),
3666 zx::Status::NOT_SUPPORTED => errno!(ENODEV),
3667 zx::Status::NO_MEMORY => errno!(ENOMEM),
3668 zx::Status::NO_RESOURCES => errno!(ENOMEM),
3669 zx::Status::OUT_OF_RANGE => errno!(ENOMEM),
3670 zx::Status::ALREADY_EXISTS => errno!(EEXIST),
3671 zx::Status::BAD_STATE => errno!(EINVAL),
3672 _ => impossible_error(status),
3673 }
3674 }
3675
3676 #[track_caller]
3677 pub fn get_errno_for_vmo_err(status: zx::Status) -> Errno {
3678 match status {
3679 zx::Status::NO_MEMORY => errno!(ENOMEM),
3680 zx::Status::ACCESS_DENIED => errno!(EPERM),
3681 zx::Status::NOT_SUPPORTED => errno!(EIO),
3682 zx::Status::BAD_STATE => errno!(EIO),
3683 _ => return impossible_error(status),
3684 }
3685 }
3686
3687 pub fn map_memory(
3688 self: &Arc<Self>,
3689 addr: DesiredAddress,
3690 memory: Arc<MemoryObject>,
3691 memory_offset: u64,
3692 length: usize,
3693 prot_flags: ProtectionFlags,
3694 max_access: Access,
3695 options: MappingOptions,
3696 name: MappingName,
3697 ) -> Result<UserAddress, Errno> {
3698 let flags = MappingFlags::from_access_flags_and_options(prot_flags, options);
3699
3700 let mut released_mappings = ReleasedMappings::default();
3702 let mut state = self.state.write();
3705 let result = state.add_memory_mapping(
3706 self,
3707 addr,
3708 memory,
3709 memory_offset,
3710 length,
3711 flags,
3712 max_access,
3713 options.contains(MappingOptions::POPULATE),
3714 name,
3715 MappingMode::Eager,
3716 &mut released_mappings,
3717 );
3718
3719 released_mappings.finalize(state);
3722
3723 result
3724 }
3725
3726 pub fn map_anonymous(
3727 self: &Arc<Self>,
3728 addr: DesiredAddress,
3729 length: usize,
3730 prot_flags: ProtectionFlags,
3731 options: MappingOptions,
3732 name: MappingName,
3733 ) -> Result<UserAddress, Errno> {
3734 let mut released_mappings = ReleasedMappings::default();
3735 let mut state = self.state.write();
3738 let result = state.map_anonymous(
3739 self,
3740 addr,
3741 length,
3742 prot_flags,
3743 options,
3744 name,
3745 &mut released_mappings,
3746 );
3747
3748 released_mappings.finalize(state);
3749
3750 result
3751 }
3752
3753 pub fn map_stack(
3755 self: &Arc<Self>,
3756 length: usize,
3757 prot_flags: ProtectionFlags,
3758 ) -> Result<UserAddress, Errno> {
3759 assert!(length <= MAX_STACK_SIZE);
3760 let addr = (self.state.read().stack_origin - length)?;
3761 let stack_addr = self.map_anonymous(
3768 DesiredAddress::Hint(addr),
3769 length,
3770 prot_flags,
3771 MappingOptions::ANONYMOUS | MappingOptions::GROWSDOWN,
3772 MappingName::Stack,
3773 )?;
3774 if stack_addr != addr {
3775 log_warn!(
3776 "An address designated for stack ({}) was unavailable, mapping at {} instead.",
3777 addr,
3778 stack_addr
3779 );
3780 }
3781 Ok(stack_addr)
3782 }
3783
3784 pub fn remap(
3785 self: &Arc<Self>,
3786 current_task: &CurrentTask,
3787 addr: UserAddress,
3788 old_length: usize,
3789 new_length: usize,
3790 flags: MremapFlags,
3791 new_addr: UserAddress,
3792 ) -> Result<UserAddress, Errno> {
3793 let mut released_mappings = ReleasedMappings::default();
3794 let mut state = self.state.write();
3797 let result = state.remap(
3798 current_task,
3799 self,
3800 addr,
3801 old_length,
3802 new_length,
3803 flags,
3804 new_addr,
3805 &mut released_mappings,
3806 );
3807
3808 released_mappings.finalize(state);
3809
3810 result
3811 }
3812
3813 pub fn unmap(self: &Arc<Self>, addr: UserAddress, length: usize) -> Result<(), Errno> {
3814 let mut released_mappings = ReleasedMappings::default();
3815 let mut state = self.state.write();
3818 let result = state.unmap(self, addr, length, &mut released_mappings);
3819
3820 released_mappings.finalize(state);
3821
3822 result
3823 }
3824
3825 pub fn protect(
3826 &self,
3827 current_task: &CurrentTask,
3828 addr: UserAddress,
3829 length: usize,
3830 prot_flags: ProtectionFlags,
3831 ) -> Result<(), Errno> {
3832 let page_size = *PAGE_SIZE;
3833 if !addr.is_aligned(page_size) {
3834 return error!(EINVAL);
3835 }
3836 if length == 0 {
3837 return Ok(());
3838 }
3839 let end = addr.checked_add(length).ok_or_else(|| errno!(ENOMEM))?.round_up(page_size)?;
3840 if end > self.maximum_valid_user_address {
3841 return error!(ENOMEM);
3842 }
3843
3844 let mut state = self.state.write();
3847 let mut released_mappings = ReleasedMappings::default();
3848 let result = state.protect(current_task, addr, length, prot_flags, &mut released_mappings);
3849 released_mappings.finalize(state);
3850 result
3851 }
3852
3853 pub fn msync(
3854 &self,
3855 current_task: &CurrentTask,
3856 addr: UserAddress,
3857 length: usize,
3858 flags: MsyncFlags,
3859 ) -> Result<(), Errno> {
3860 if flags.contains(MsyncFlags::ASYNC) && flags.contains(MsyncFlags::SYNC) {
3868 return error!(EINVAL);
3869 }
3870
3871 if !addr.is_aligned(*PAGE_SIZE) {
3872 return error!(EINVAL);
3873 }
3874
3875 let mut nodes_to_sync = {
3880 let mm_state = self.state.read();
3881
3882 let length_rounded = round_up_to_system_page_size(length)?;
3883 let end_addr = addr.checked_add(length_rounded).ok_or_else(|| errno!(EINVAL))?;
3884
3885 let mut last_end = addr;
3886 let mut nodes = vec![];
3887 for (range, mapping) in mm_state.mappings.range(addr..end_addr) {
3888 if range.start > last_end {
3891 return error!(ENOMEM);
3892 }
3893 last_end = range.end;
3894
3895 if flags.contains(MsyncFlags::INVALIDATE)
3896 && mapping.flags().contains(MappingFlags::LOCKED)
3897 {
3898 return error!(EBUSY);
3899 }
3900
3901 if flags.contains(MsyncFlags::SYNC) {
3902 if let MappingNameRef::File(file_mapping) = mapping.name() {
3903 nodes.push(file_mapping.name.entry.node.clone());
3904 }
3905 }
3906 }
3907 if last_end < end_addr {
3908 return error!(ENOMEM);
3909 }
3910 nodes
3911 };
3912
3913 nodes_to_sync.sort_by_key(|n| Arc::as_ptr(n) as usize);
3915 nodes_to_sync.dedup_by(|a, b| Arc::ptr_eq(a, b));
3916
3917 for node in nodes_to_sync {
3918 node.ops().sync(&node, current_task)?;
3924 }
3925 Ok(())
3926 }
3927
3928 pub fn madvise(&self, addr: UserAddress, length: usize, advice: u32) -> Result<(), Errno> {
3929 let mut state = self.state.write();
3930 let mut released_mappings = ReleasedMappings::default();
3931 let result =
3932 state.madvise(&self.mapping_context, addr, length, advice, &mut released_mappings);
3933 released_mappings.finalize(state);
3934 result
3935 }
3936
3937 pub fn mlock(
3938 &self,
3939 current_task: &CurrentTask,
3940 desired_addr: UserAddress,
3941 desired_length: usize,
3942 on_fault: bool,
3943 ) -> Result<(), Errno> {
3944 let mut state = self.state.write();
3945 let mut released_mappings = ReleasedMappings::default();
3946 let result = state.mlock(
3947 &self.mapping_context,
3948 current_task,
3949 desired_addr,
3950 desired_length,
3951 on_fault,
3952 &mut released_mappings,
3953 );
3954 released_mappings.finalize(state);
3955 result
3956 }
3957
3958 pub fn munlock(
3959 &self,
3960 current_task: &CurrentTask,
3961 desired_addr: UserAddress,
3962 desired_length: usize,
3963 ) -> Result<(), Errno> {
3964 let mut state = self.state.write();
3965 let mut released_mappings = ReleasedMappings::default();
3966 let result =
3967 state.munlock(current_task, desired_addr, desired_length, &mut released_mappings);
3968 released_mappings.finalize(state);
3969 result
3970 }
3971
3972 pub fn log_memory_map(&self, task: &Task, fault_address: UserAddress) {
3973 let state = self.state.read();
3974 log_warn!("Memory map for pid={}:", task.thread_group.leader);
3975 let mut last_end = UserAddress::from_ptr(0);
3976 for (range, map) in state.mappings.iter() {
3977 if fault_address >= last_end && fault_address < range.start {
3978 log_warn!("{:08x} <= FAULT", fault_address.ptr());
3979 }
3980
3981 let perms = format!(
3982 "{}{}{}{}",
3983 if map.can_read() { 'r' } else { '-' },
3984 if map.can_write() { 'w' } else { '-' },
3985 if map.can_exec() { 'x' } else { '-' },
3986 if map.flags().contains(MappingFlags::SHARED) { 's' } else { 'p' }
3987 );
3988
3989 let backing = match state.get_mapping_backing(map) {
3990 MappingBacking::Memory(backing) => backing.address_to_offset(range.start),
3991 MappingBacking::PrivateAnonymous => 0,
3992 };
3993
3994 let name_str = match &map.name() {
3995 MappingNameRef::File(file) => {
3996 let Ok(running_state) = task.running_state() else {
3997 log_warn!("Task {} is not running", task.get_tid());
3998 continue;
3999 };
4000 String::from_utf8_lossy(&file.name.path(&running_state.fs())).into_owned()
4001 }
4002 MappingNameRef::None | MappingNameRef::AioContext(_) => {
4003 if map.flags().contains(MappingFlags::SHARED)
4004 && map.flags().contains(MappingFlags::ANONYMOUS)
4005 {
4006 "/dev/zero (deleted)".to_string()
4007 } else {
4008 "".to_string()
4009 }
4010 }
4011 MappingNameRef::Stack => "[stack]".to_string(),
4012 MappingNameRef::Heap => "[heap]".to_string(),
4013 MappingNameRef::Vdso => "[vdso]".to_string(),
4014 MappingNameRef::Vvar => "[vvar]".to_string(),
4015 _ => format!("{:?}", map.name()),
4016 };
4017
4018 let fault_marker = if range.contains(&fault_address) { " <= FAULT" } else { "" };
4019
4020 log_warn!(
4021 "{:08x}-{:08x} {} {:08x} {}{}",
4022 range.start.ptr(),
4023 range.end.ptr(),
4024 perms,
4025 backing,
4026 name_str,
4027 fault_marker
4028 );
4029 last_end = range.end;
4030 }
4031
4032 if fault_address >= last_end {
4033 log_warn!("{:08x} <= FAULT", fault_address.ptr());
4034 }
4035 }
4036
4037 pub fn handle_page_fault(
4038 self: &Arc<Self>,
4039 decoded: PageFaultExceptionReport,
4040 error_code: zx::Status,
4041 ) -> ExceptionResult {
4042 #[cfg(target_arch = "aarch64")]
4043 let addr = if self.is_arch64() {
4046 UserAddress::from(decoded.faulting_address & 0x00FF_FFFF_FFFF_FFFF)
4047 } else {
4048 UserAddress::from(decoded.faulting_address)
4049 };
4050 #[cfg(not(target_arch = "aarch64"))]
4051 let addr = UserAddress::from(decoded.faulting_address);
4052
4053 if error_code == zx::Status::ACCESS_DENIED {
4055 let state = self.state.write();
4056 if let Some((_, mapping)) = state.mappings.get(addr) {
4057 if mapping.flags().contains(MappingFlags::UFFD) {
4058 assert!(mapping.flags().contains(MappingFlags::UFFD_MISSING));
4060
4061 if let Some(_uffd) = state.find_uffd(addr) {
4062 return ExceptionResult::Signal(SignalInfo::with_detail(
4068 SIGBUS,
4069 BUS_ADRERR as i32,
4070 SignalDetail::SigFault { addr: decoded.faulting_address },
4071 ));
4072 };
4073 }
4074 if check_access_permissions_in_page_fault(&decoded, mapping) {
4078 track_stub!(
4079 TODO("https://fxbug.dev/435171399"),
4080 "Inconsistent permission fault"
4081 );
4082 return ExceptionResult::Handled;
4083 }
4084 }
4085 std::mem::drop(state);
4086 }
4087
4088 if decoded.not_present {
4089 {
4090 let mut state = self.state.write();
4091 match state.ensure_range_mapped_in_user_vmar(addr, None, &self.mapping_context) {
4092 Ok(true) => return ExceptionResult::Handled,
4093 Ok(false) => {
4094 let current_gen = state.mappings.generation;
4100 let old_gen = LAST_SEEN_MAPPING_GENERATION.with(|c| c.replace(current_gen));
4101 if current_gen != old_gen {
4102 return ExceptionResult::Handled;
4103 }
4104 }
4105 Err(e) => {
4106 log_error!("Failed to map lazy memory: {e}")
4107 }
4108 }
4109 }
4110
4111 match self.extend_growsdown_mapping_to_address(
4117 UserAddress::from(decoded.faulting_address),
4118 decoded.is_write,
4119 ) {
4120 Ok(true) => {
4121 return ExceptionResult::Handled;
4122 }
4123 Err(e) => {
4124 log_warn!("Error handling page fault: {e}")
4125 }
4126 _ => {}
4127 }
4128 }
4129
4130 let (signo, si_code) = match error_code {
4138 zx::Status::OUT_OF_RANGE => (SIGBUS, linux_uapi::BUS_ADRERR as i32),
4139 _ => {
4140 let code = if self.state.read().mappings.get(addr).is_some() {
4141 linux_uapi::SEGV_ACCERR
4142 } else {
4143 linux_uapi::SEGV_MAPERR
4144 };
4145 (SIGSEGV, code as i32)
4146 }
4147 };
4148 ExceptionResult::Signal(SignalInfo::with_detail(
4149 signo,
4150 si_code,
4151 SignalDetail::SigFault { addr: decoded.faulting_address },
4152 ))
4153 }
4154
4155 pub fn set_mapping_name(
4156 &self,
4157 addr: UserAddress,
4158 length: usize,
4159 name: Option<FsString>,
4160 ) -> Result<(), Errno> {
4161 let mut state = self.state.write();
4162 let mut released_mappings = ReleasedMappings::default();
4163 let result = state.set_mapping_name(addr, length, name, &mut released_mappings);
4164 released_mappings.finalize(state);
4165 result
4166 }
4167
4168 pub fn ensure_mapped(&self, addr: UserAddress, length: usize) -> Result<(), Errno> {
4178 if !addr.is_aligned(*PAGE_SIZE) {
4179 return error!(EINVAL);
4180 }
4181
4182 let length = round_up_to_system_page_size(length)?;
4183 let end_addr = addr.checked_add(length).ok_or_else(|| errno!(EINVAL))?;
4184 let state = self.state.read();
4185 let mut last_end = addr;
4186 for (range, _) in state.mappings.range(addr..end_addr) {
4187 if range.start > last_end {
4188 return error!(ENOMEM);
4190 }
4191 last_end = range.end;
4192 }
4193 if last_end < end_addr {
4194 error!(ENOMEM)
4196 } else {
4197 Ok(())
4198 }
4199 }
4200
4201 pub fn get_mapping_memory(
4204 &self,
4205 addr: UserAddress,
4206 perms: ProtectionFlags,
4207 ) -> Result<(Arc<MemoryObject>, u64), Errno> {
4208 let state = self.state.read();
4209 let (_, mapping) = state.mappings.get(addr).ok_or_else(|| errno!(EFAULT))?;
4210 if !mapping.flags().access_flags().contains(perms) {
4211 return error!(EACCES);
4212 }
4213 match state.get_mapping_backing(mapping) {
4214 MappingBacking::Memory(backing) => {
4215 Ok((Arc::clone(backing.memory()), mapping.address_to_offset(addr)))
4216 }
4217 MappingBacking::PrivateAnonymous => {
4218 Ok((Arc::clone(&self.mapping_context.private_anonymous.backing), addr.ptr() as u64))
4219 }
4220 }
4221 }
4222
4223 pub fn check_plausible(&self, addr: UserAddress, buffer_size: usize) -> Result<(), Errno> {
4245 let state = self.state.read();
4246
4247 if let Some(range) = state.mappings.last_range() {
4248 if (range.end - buffer_size)? >= addr {
4249 return Ok(());
4250 }
4251 }
4252 error!(EFAULT)
4253 }
4254
4255 pub fn get_aio_context(&self, addr: UserAddress) -> Option<Arc<AioContext>> {
4256 let state = self.state.read();
4257 state.get_aio_context(addr).map(|(_, aio_context)| aio_context)
4258 }
4259
4260 pub fn destroy_aio_context(
4261 self: &Arc<Self>,
4262 addr: UserAddress,
4263 ) -> Result<Arc<AioContext>, Errno> {
4264 let mut released_mappings = ReleasedMappings::default();
4265
4266 let mut state = self.state.write();
4269
4270 let Some((range, aio_context)) = state.get_aio_context(addr) else {
4274 return error!(EINVAL);
4275 };
4276
4277 let length = range.end - range.start;
4278 let result = state.unmap(self, range.start, length, &mut released_mappings);
4279
4280 released_mappings.finalize(state);
4281
4282 result.map(|_| aio_context)
4283 }
4284
4285 #[cfg(test)]
4286 pub fn get_mapping_name(
4287 &self,
4288 addr: UserAddress,
4289 ) -> Result<Option<flyweights::FlyByteStr>, Errno> {
4290 let state = self.state.read();
4291 let (_, mapping) = state.mappings.get(addr).ok_or_else(|| errno!(EFAULT))?;
4292 if let MappingNameRef::Vma(name) = mapping.name() {
4293 Ok(Some(name.clone()))
4294 } else {
4295 Ok(None)
4296 }
4297 }
4298
4299 #[cfg(test)]
4300 pub fn get_mapping_count(&self) -> usize {
4301 let state = self.state.read();
4302 state.mappings.iter().count()
4303 }
4304
4305 pub fn extend_growsdown_mapping_to_address(
4306 self: &Arc<Self>,
4307 addr: UserAddress,
4308 is_write: bool,
4309 ) -> Result<bool, Error> {
4310 self.state.write().extend_growsdown_mapping_to_address(self, addr, is_write)
4311 }
4312
4313 pub fn get_total_usage(&self) -> usize {
4314 self.state.read().mappings.total_usage
4315 }
4316
4317 pub fn get_stats(&self, current_task: &CurrentTask) -> MemoryStats {
4318 let state = self.state.read();
4322
4323 let mut stats = MemoryStats::default();
4324 stats.vm_stack = state.stack_size;
4325
4326 self.with_zx_mappings(current_task, |zx_mappings| {
4327 for zx_mapping in zx_mappings {
4328 let zx_details = zx_mapping.details();
4330 let Some(zx_details) = zx_details.as_mapping() else { continue };
4331 let user_address = UserAddress::from(zx_mapping.base as u64);
4332 let (_, mm_mapping) = state
4333 .mappings
4334 .get(user_address)
4335 .unwrap_or_else(|| panic!("mapping bookkeeping must be consistent with zircon's: not found: {user_address:?}"));
4336 debug_assert_eq!(
4337 match state.get_mapping_backing(mm_mapping) {
4338 MappingBacking::Memory(m)=>m.memory().get_koid(),
4339 MappingBacking::PrivateAnonymous=>self.mapping_context.private_anonymous.backing.get_koid(),
4340 },
4341 zx_details.vmo_koid,
4342 "MemoryManager and Zircon must agree on which VMO is mapped in this range",
4343 );
4344
4345 stats.vm_size += zx_mapping.size;
4346
4347 stats.vm_rss += zx_details.committed_bytes;
4348 stats.vm_swap += zx_details.populated_bytes - zx_details.committed_bytes;
4349
4350 if mm_mapping.flags().contains(MappingFlags::SHARED) {
4351 stats.rss_shared += zx_details.committed_bytes;
4352 } else if mm_mapping.flags().contains(MappingFlags::ANONYMOUS) {
4353 stats.rss_anonymous += zx_details.committed_bytes;
4354 } else if mm_mapping.name().is_file() {
4355 stats.rss_file += zx_details.committed_bytes;
4356 }
4357
4358 if mm_mapping.flags().contains(MappingFlags::LOCKED) {
4359 stats.vm_lck += zx_details.committed_bytes;
4360 }
4361
4362 if mm_mapping.flags().contains(MappingFlags::ELF_BINARY)
4363 && mm_mapping.flags().contains(MappingFlags::WRITE)
4364 {
4365 stats.vm_data += zx_mapping.size;
4366 }
4367
4368 if mm_mapping.flags().contains(MappingFlags::ELF_BINARY)
4369 && mm_mapping.flags().contains(MappingFlags::EXEC)
4370 {
4371 stats.vm_exe += zx_mapping.size;
4372 }
4373 }
4374 });
4375
4376 stats.vm_rss_hwm = STUB_VM_RSS_HWM;
4379 stats
4380 }
4381
4382 fn run_atomic_op<F, T>(&self, futex_addr: FutexAddress, mut op: F) -> Result<T, Errno>
4383 where
4384 F: FnMut(&usercopy::Usercopy) -> Result<T, ()>,
4385 {
4386 if let Some(usercopy) = usercopy() {
4387 if let Ok(val) = op(usercopy) {
4393 return Ok(val);
4394 }
4395 self.ensure_range_mapped_in_user_vmar(futex_addr.into(), None)?;
4396 op(usercopy).map_err(|_| errno!(EFAULT))
4397 } else {
4398 unreachable!("can only control memory ordering of atomics with usercopy");
4399 }
4400 }
4401
4402 pub fn atomic_load_u32_acquire(&self, futex_addr: FutexAddress) -> Result<u32, Errno> {
4403 self.run_atomic_op(futex_addr, |uc| uc.atomic_load_u32_acquire(futex_addr.ptr()))
4404 }
4405
4406 pub fn atomic_load_u32_relaxed(&self, futex_addr: FutexAddress) -> Result<u32, Errno> {
4407 if usercopy().is_some() {
4408 self.run_atomic_op(futex_addr, |uc| uc.atomic_load_u32_relaxed(futex_addr.ptr()))
4409 } else {
4410 let buf = unsafe {
4413 read_to_array(|buf| {
4414 self.state
4415 .read()
4416 .read_memory(futex_addr.into(), buf, &self.mapping_context)
4417 .map(|bytes_read| {
4418 debug_assert_eq!(bytes_read.len(), std::mem::size_of::<u32>())
4419 })
4420 })
4421 }?;
4422 Ok(u32::from_ne_bytes(buf))
4423 }
4424 }
4425
4426 pub fn atomic_store_u32_relaxed(
4427 &self,
4428 futex_addr: FutexAddress,
4429 value: u32,
4430 ) -> Result<(), Errno> {
4431 if usercopy().is_some() {
4432 self.run_atomic_op(futex_addr, |uc| {
4433 uc.atomic_store_u32_relaxed(futex_addr.ptr(), value)
4434 })
4435 } else {
4436 self.state.read().write_memory(
4437 futex_addr.into(),
4438 value.as_bytes(),
4439 &self.mapping_context,
4440 )?;
4441 Ok(())
4442 }
4443 }
4444
4445 pub fn atomic_compare_exchange_u32_acq_rel(
4446 &self,
4447 futex_addr: FutexAddress,
4448 current: u32,
4449 new: u32,
4450 ) -> CompareExchangeResult<u32> {
4451 CompareExchangeResult::from_usercopy(self.run_atomic_op(futex_addr, |uc| {
4452 uc.atomic_compare_exchange_u32_acq_rel(futex_addr.ptr(), current, new)
4453 }))
4454 }
4455
4456 pub fn atomic_compare_exchange_weak_u32_acq_rel(
4457 &self,
4458 futex_addr: FutexAddress,
4459 current: u32,
4460 new: u32,
4461 ) -> CompareExchangeResult<u32> {
4462 CompareExchangeResult::from_usercopy(self.run_atomic_op(futex_addr, |uc| {
4463 uc.atomic_compare_exchange_weak_u32_acq_rel(futex_addr.ptr(), current, new)
4464 }))
4465 }
4466}
4467
4468#[derive(Debug, Clone)]
4470pub enum CompareExchangeResult<T> {
4471 Success,
4474 Stale { observed: T },
4476 Error(Errno),
4478}
4479
4480impl<T> CompareExchangeResult<T> {
4481 fn from_usercopy(res: Result<Result<T, T>, Errno>) -> Self {
4482 match res {
4483 Ok(Ok(_)) => Self::Success,
4484 Ok(Err(observed)) => Self::Stale { observed },
4485 Err(e) => Self::Error(e),
4486 }
4487 }
4488}
4489
4490impl<T> From<Errno> for CompareExchangeResult<T> {
4491 fn from(e: Errno) -> Self {
4492 Self::Error(e)
4493 }
4494}
4495
4496#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4498pub enum DesiredAddress {
4499 Any,
4501 Hint(UserAddress),
4504 Fixed(UserAddress),
4507 FixedOverwrite(UserAddress),
4510}
4511
4512#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4514enum SelectedAddress {
4515 Fixed(UserAddress),
4517 FixedOverwrite(UserAddress),
4519}
4520
4521impl SelectedAddress {
4522 fn addr(&self) -> UserAddress {
4523 match self {
4524 SelectedAddress::Fixed(addr) => *addr,
4525 SelectedAddress::FixedOverwrite(addr) => *addr,
4526 }
4527 }
4528}
4529
4530fn write_map(
4532 task: &Task,
4533 sink: &mut DynamicFileBuf,
4534 state: &MemoryManagerState,
4535 range: &Range<UserAddress>,
4536 map: &Mapping,
4537) -> Result<(), Errno> {
4538 let line_length = write!(
4539 sink,
4540 "{:08x}-{:08x} {}{}{}{} {:08x} 00:00 {} ",
4541 range.start.ptr(),
4542 range.end.ptr(),
4543 if map.can_read() { 'r' } else { '-' },
4544 if map.can_write() { 'w' } else { '-' },
4545 if map.can_exec() { 'x' } else { '-' },
4546 if map.flags().contains(MappingFlags::SHARED) { 's' } else { 'p' },
4547 match state.get_mapping_backing(map) {
4548 MappingBacking::Memory(backing) => backing.address_to_offset(range.start),
4549 MappingBacking::PrivateAnonymous => 0,
4550 },
4551 if let MappingNameRef::File(file) = &map.name() { file.name.entry.node.ino } else { 0 }
4552 )?;
4553 let fill_to_name = |sink: &mut DynamicFileBuf| {
4554 for _ in line_length..73 {
4556 sink.write(b" ");
4557 }
4558 };
4559 match &map.name() {
4560 MappingNameRef::None | MappingNameRef::AioContext(_) => {
4561 if map.flags().contains(MappingFlags::SHARED)
4562 && map.flags().contains(MappingFlags::ANONYMOUS)
4563 {
4564 fill_to_name(sink);
4566 sink.write(b"/dev/zero (deleted)");
4567 }
4568 }
4569 MappingNameRef::Stack => {
4570 fill_to_name(sink);
4571 sink.write(b"[stack]");
4572 }
4573 MappingNameRef::Heap => {
4574 fill_to_name(sink);
4575 sink.write(b"[heap]");
4576 }
4577 MappingNameRef::Vdso => {
4578 fill_to_name(sink);
4579 sink.write(b"[vdso]");
4580 }
4581 MappingNameRef::Vvar => {
4582 fill_to_name(sink);
4583 sink.write(b"[vvar]");
4584 }
4585 MappingNameRef::File(file) => {
4586 fill_to_name(sink);
4587 let path = file.name.path(&task.running_state()?.fs());
4591 sink.write_iter(
4592 path.iter()
4593 .flat_map(|b| if *b == b'\n' { b"\\012" } else { std::slice::from_ref(b) })
4594 .copied(),
4595 );
4596 }
4597 MappingNameRef::Vma(name) => {
4598 fill_to_name(sink);
4599 sink.write(b"[anon:");
4600 sink.write(name.as_bytes());
4601 sink.write(b"]");
4602 }
4603 MappingNameRef::Ashmem(name) => {
4604 fill_to_name(sink);
4605 sink.write(b"/dev/ashmem/");
4606 sink.write(name.as_bytes());
4607 }
4608 }
4609 sink.write(b"\n");
4610 Ok(())
4611}
4612
4613#[derive(Default)]
4614pub struct MemoryStats {
4615 pub vm_size: usize,
4616 pub vm_rss: usize,
4617 pub vm_rss_hwm: usize,
4618 pub rss_anonymous: usize,
4619 pub rss_file: usize,
4620 pub rss_shared: usize,
4621 pub vm_data: usize,
4622 pub vm_stack: usize,
4623 pub vm_exe: usize,
4624 pub vm_swap: usize,
4625 pub vm_lck: usize,
4626}
4627
4628#[derive(Clone)]
4630pub struct ProcMapsFile {
4631 mm: Weak<MemoryManager>,
4632 task: Weak<Task>,
4633}
4634impl ProcMapsFile {
4635 pub fn new(task: Arc<Task>) -> DynamicFile<Self> {
4636 let mm = task.mm().map_or_else(|_| Weak::default(), |mm| Arc::downgrade(&mm));
4638 DynamicFile::new(Self { mm, task: Arc::downgrade(&task) })
4639 }
4640}
4641
4642impl SequenceFileSource for ProcMapsFile {
4643 type Cursor = UserAddress;
4644
4645 fn next(
4646 &self,
4647 _current_task: &CurrentTask,
4648 cursor: UserAddress,
4649 sink: &mut DynamicFileBuf,
4650 ) -> Result<Option<UserAddress>, Errno> {
4651 let task = Task::from_weak(&self.task)?;
4652 let Some(mm) = self.mm.upgrade() else {
4654 return Ok(None);
4655 };
4656 let state = mm.state.read();
4657 if let Some((range, map)) = state.mappings.find_at_or_after(cursor) {
4658 write_map(&task, sink, &state, range, map)?;
4659 return Ok(Some(range.end));
4660 }
4661 Ok(None)
4662 }
4663}
4664
4665#[derive(Clone)]
4666pub struct ProcSmapsFile {
4667 mm: Weak<MemoryManager>,
4668 task: Weak<Task>,
4669}
4670impl ProcSmapsFile {
4671 pub fn new(task: Arc<Task>) -> DynamicFile<Self> {
4672 let mm = task.mm().map_or_else(|_| Weak::default(), |mm| Arc::downgrade(&mm));
4674 DynamicFile::new(Self { mm, task: Arc::downgrade(&task) })
4675 }
4676}
4677
4678impl DynamicFileSource for ProcSmapsFile {
4679 fn generate(&self, current_task: &CurrentTask, sink: &mut DynamicFileBuf) -> Result<(), Errno> {
4680 let page_size_kb = *PAGE_SIZE / 1024;
4681 let task = Task::from_weak(&self.task)?;
4682 let Some(mm) = self.mm.upgrade() else {
4684 return Ok(());
4685 };
4686
4687 let max_addr = mm.maximum_valid_user_address;
4689 mm.ensure_range_mapped_in_user_vmar(UserAddress::from(0), Some(max_addr.ptr()))?;
4690
4691 let state = mm.state.read();
4692 let committed_bytes_vec = mm.with_zx_mappings(current_task, |zx_mappings| {
4693 let mut zx_memory_info = RangeMap::<UserAddress, usize>::default();
4694 for idx in 0..zx_mappings.len() {
4695 let zx_mapping = zx_mappings[idx];
4696 let _ = zx_memory_info.insert(
4698 UserAddress::from_ptr(zx_mapping.base)
4699 ..UserAddress::from_ptr(zx_mapping.base + zx_mapping.size),
4700 idx,
4701 );
4702 }
4703
4704 let mut committed_bytes_vec = Vec::new();
4705 for (mm_range, mm_mapping) in state.mappings.iter() {
4706 let mut committed_bytes = 0;
4707
4708 for (zx_range, zx_mapping_idx) in zx_memory_info.range(mm_range.clone()) {
4709 let intersect_range = zx_range.intersect(mm_range);
4710 let zx_mapping = zx_mappings[*zx_mapping_idx];
4711 let zx_details = zx_mapping.details();
4712 let Some(zx_details) = zx_details.as_mapping() else { continue };
4713 let zx_committed_bytes = zx_details.committed_bytes;
4714
4715 committed_bytes += if intersect_range != *zx_range {
4721 let intersection_size =
4722 intersect_range.end.ptr() - intersect_range.start.ptr();
4723 let part = intersection_size as f32 / zx_mapping.size as f32;
4724 let prorated_committed_bytes: f32 = part * zx_committed_bytes as f32;
4725 prorated_committed_bytes as u64
4726 } else {
4727 zx_committed_bytes as u64
4728 };
4729 assert_eq!(
4730 match state.get_mapping_backing(mm_mapping) {
4731 MappingBacking::Memory(m) => m.memory().get_koid(),
4732 MappingBacking::PrivateAnonymous =>
4733 mm.mapping_context.private_anonymous.backing.get_koid(),
4734 },
4735 zx_details.vmo_koid,
4736 "MemoryManager and Zircon must agree on which VMO is mapped in this range",
4737 );
4738 }
4739 committed_bytes_vec.push(committed_bytes);
4740 }
4741 Ok(committed_bytes_vec)
4742 })?;
4743
4744 for ((mm_range, mm_mapping), committed_bytes) in
4745 state.mappings.iter().zip(committed_bytes_vec.into_iter())
4746 {
4747 write_map(&task, sink, &state, mm_range, mm_mapping)?;
4748
4749 let size_kb = (mm_range.end.ptr() - mm_range.start.ptr()) / 1024;
4750 writeln!(sink, "Size: {size_kb:>8} kB",)?;
4751 let share_count = match state.get_mapping_backing(mm_mapping) {
4752 MappingBacking::Memory(backing) => {
4753 let memory = backing.memory();
4754 if memory.is_clock() {
4755 1
4757 } else {
4758 let memory_info = backing.memory().info()?;
4759 memory_info.share_count as u64
4760 }
4761 }
4762 MappingBacking::PrivateAnonymous => {
4763 1 }
4765 };
4766
4767 let rss_kb = committed_bytes / 1024;
4768 writeln!(sink, "Rss: {rss_kb:>8} kB")?;
4769
4770 let pss_kb = if mm_mapping.flags().contains(MappingFlags::SHARED) {
4771 rss_kb / share_count
4772 } else {
4773 rss_kb
4774 };
4775 writeln!(sink, "Pss: {pss_kb:>8} kB")?;
4776
4777 track_stub!(TODO("https://fxbug.dev/322874967"), "smaps dirty pages");
4778 let (shared_dirty_kb, private_dirty_kb) = (0, 0);
4779
4780 let is_shared = share_count > 1;
4781 let shared_clean_kb = if is_shared { rss_kb } else { 0 };
4782 writeln!(sink, "Shared_Clean: {shared_clean_kb:>8} kB")?;
4783 writeln!(sink, "Shared_Dirty: {shared_dirty_kb:>8} kB")?;
4784
4785 let private_clean_kb = if is_shared { 0 } else { rss_kb };
4786 writeln!(sink, "Private_Clean: {private_clean_kb:>8} kB")?;
4787 writeln!(sink, "Private_Dirty: {private_dirty_kb:>8} kB")?;
4788
4789 let anonymous_kb = if mm_mapping.private_anonymous() { rss_kb } else { 0 };
4790 writeln!(sink, "Anonymous: {anonymous_kb:>8} kB")?;
4791 writeln!(sink, "KernelPageSize: {page_size_kb:>8} kB")?;
4792 writeln!(sink, "MMUPageSize: {page_size_kb:>8} kB")?;
4793
4794 let locked_kb =
4795 if mm_mapping.flags().contains(MappingFlags::LOCKED) { rss_kb } else { 0 };
4796 writeln!(sink, "Locked: {locked_kb:>8} kB")?;
4797 writeln!(sink, "VmFlags: {}", mm_mapping.vm_flags())?;
4798
4799 track_stub!(TODO("https://fxbug.dev/297444691"), "optional smaps fields");
4800 }
4801
4802 Ok(())
4803 }
4804}
4805
4806pub fn create_anonymous_mapping_memory(size: u64) -> Result<Arc<MemoryObject>, Errno> {
4808 let mut memory = MemoryObject::from(
4810 zx::Vmo::create_with_opts(zx::VmoOptions::RESIZABLE, size).map_err(|s| match s {
4811 zx::Status::NO_MEMORY => errno!(ENOMEM),
4812 zx::Status::OUT_OF_RANGE => errno!(ENOMEM),
4813 _ => impossible_error(s),
4814 })?,
4815 )
4816 .with_zx_name(b"starnix:memory_manager");
4817
4818 memory.set_zx_name(b"starnix-anon");
4819
4820 memory = memory.replace_as_executable(&VMEX_RESOURCE).map_err(impossible_error)?;
4822 Ok(Arc::new(memory))
4823}
4824
4825fn generate_random_offset_for_aslr(arch_width: ArchWidth) -> usize {
4826 let randomness = {
4828 let random_bits =
4829 if arch_width.is_arch32() { ASLR_32_RANDOM_BITS } else { ASLR_RANDOM_BITS };
4830 let mask = (1 << random_bits) - 1;
4831 let mut bytes = [0; std::mem::size_of::<usize>()];
4832 starnix_crypto::cprng_draw(&mut bytes);
4833 usize::from_le_bytes(bytes) & mask
4834 };
4835
4836 randomness * (*PAGE_SIZE as usize)
4838}
4839
4840#[cfg(test)]
4841mod tests {
4842 use super::*;
4843 use crate::mm::memory_accessor::{MemoryAccessor, MemoryAccessorExt};
4844 use crate::mm::syscalls::do_mmap;
4845 use crate::task::syscalls::sys_prctl;
4846 use crate::testing::*;
4847 use crate::vfs::FdNumber;
4848 use assert_matches::assert_matches;
4849 use itertools::assert_equal;
4850 use starnix_uapi::user_address::{UserCString, UserRef};
4851 use starnix_uapi::{
4852 MAP_ANONYMOUS, MAP_FIXED, MAP_GROWSDOWN, MAP_PRIVATE, MAP_SHARED, PR_SET_VMA,
4853 PR_SET_VMA_ANON_NAME, PROT_NONE, PROT_READ,
4854 };
4855 use std::ffi::CString;
4856 use zerocopy::{FromBytes, Immutable, KnownLayout};
4857
4858 #[::fuchsia::test]
4859 fn test_mapping_flags() {
4860 let options = MappingOptions::ANONYMOUS;
4861 let access_flags = ProtectionFlags::READ | ProtectionFlags::WRITE;
4862 let mapping_flags = MappingFlags::from_access_flags_and_options(access_flags, options);
4863 assert_eq!(mapping_flags.access_flags(), access_flags);
4864 assert_eq!(mapping_flags.options(), options);
4865
4866 let new_access_flags = ProtectionFlags::READ | ProtectionFlags::EXEC;
4867 let adusted_mapping_flags = mapping_flags.with_access_flags(new_access_flags);
4868 assert_eq!(adusted_mapping_flags.access_flags(), new_access_flags);
4869 assert_eq!(adusted_mapping_flags.options(), options);
4870 }
4871
4872 #[::fuchsia::test]
4873 async fn test_any_ranges_lazy() {
4874 spawn_kernel_and_run(async |current_task| {
4875 let mm = current_task.mm().unwrap();
4876 let page_size = *PAGE_SIZE as usize;
4877 let addr = (mm.base_addr + 10 * page_size).unwrap();
4878 let length = page_size;
4879
4880 let memory = create_anonymous_mapping_memory(length as u64).unwrap();
4881 let flags = MappingFlags::from_access_flags_and_options(
4882 ProtectionFlags::READ | ProtectionFlags::WRITE,
4883 MappingOptions::empty(),
4884 );
4885
4886 let mapping = Mapping::with_name(
4887 MappingBacking::Memory(Box::new(MappingBackingMemory::new(addr, memory, 0))),
4888 flags,
4889 Access::rwx(),
4890 MappingName::None,
4891 MappingMode::Lazy,
4892 );
4893
4894 {
4895 let mut state = mm.state.write();
4896 state.mappings.insert(addr..(addr + length).unwrap(), mapping);
4897 }
4898
4899 {
4900 let state = mm.state.read();
4901 assert!(state.any_ranges_lazy(std::iter::once((addr, Some(length)))));
4902 }
4903
4904 assert!(mm.ensure_range_mapped_in_user_vmar(addr, Some(length)).unwrap());
4905
4906 {
4907 let state = mm.state.read();
4908 assert!(!state.any_ranges_lazy(std::iter::once((addr, Some(length)))));
4909 }
4910 })
4911 .await;
4912 }
4913
4914 #[::fuchsia::test]
4915 async fn test_brk() {
4916 spawn_kernel_and_run(async |current_task| {
4917 let mm = current_task.mm().unwrap();
4918
4919 let get_range = |addr: UserAddress| {
4921 let state = mm.state.read();
4922 state
4923 .mappings
4924 .map
4925 .get(addr)
4926 .map(|(range, mapping)| (range.clone(), mapping.clone()))
4927 };
4928
4929 let base_addr = mm
4931 .set_brk(¤t_task, UserAddress::default())
4932 .expect("failed to set initial program break");
4933 assert!(base_addr > UserAddress::default());
4934
4935 assert_eq!(get_range(base_addr), None);
4937
4938 let addr0 =
4940 mm.set_brk(¤t_task, (base_addr + 1u64).unwrap()).expect("failed to grow brk");
4941 assert!(addr0 > base_addr);
4942 let (range0, _) = get_range(base_addr).expect("base_addr should be mapped");
4943 assert_eq!(range0.start, base_addr);
4944 assert_eq!(range0.end, (base_addr + *PAGE_SIZE).unwrap());
4945
4946 let addr1 =
4948 mm.set_brk(¤t_task, (base_addr + 2u64).unwrap()).expect("failed to grow brk");
4949 assert_eq!(addr1, (base_addr + 2u64).unwrap());
4950 let (range1, _) = get_range(base_addr).expect("base_addr should be mapped");
4951 assert_eq!(range1.start, range0.start);
4952 assert_eq!(range1.end, range0.end);
4953
4954 let addr2 = mm
4956 .set_brk(¤t_task, (base_addr + 24893u64).unwrap())
4957 .expect("failed to grow brk");
4958 assert_eq!(addr2, (base_addr + 24893u64).unwrap());
4959 let (range2, _) = get_range(base_addr).expect("base_addr should be mapped");
4960 assert_eq!(range2.start, base_addr);
4961 assert_eq!(range2.end, addr2.round_up(*PAGE_SIZE).unwrap());
4962
4963 let addr3 = mm
4965 .set_brk(¤t_task, (base_addr + 14832u64).unwrap())
4966 .expect("failed to shrink brk");
4967 assert_eq!(addr3, (base_addr + 14832u64).unwrap());
4968 let (range3, _) = get_range(base_addr).expect("base_addr should be mapped");
4969 assert_eq!(range3.start, base_addr);
4970 assert_eq!(range3.end, addr3.round_up(*PAGE_SIZE).unwrap());
4971
4972 let addr4 = mm
4974 .set_brk(¤t_task, (base_addr + 3u64).unwrap())
4975 .expect("failed to drastically shrink brk");
4976 assert_eq!(addr4, (base_addr + 3u64).unwrap());
4977 let (range4, _) = get_range(base_addr).expect("base_addr should be mapped");
4978 assert_eq!(range4.start, base_addr);
4979 assert_eq!(range4.end, addr4.round_up(*PAGE_SIZE).unwrap());
4980
4981 let addr5 = mm
4983 .set_brk(¤t_task, base_addr)
4984 .expect("failed to drastically shrink brk to zero");
4985 assert_eq!(addr5, base_addr);
4986 assert_eq!(get_range(base_addr), None);
4987 })
4988 .await;
4989 }
4990
4991 #[::fuchsia::test]
4992 async fn test_mm_exec() {
4993 spawn_kernel_and_run(async |current_task| {
4994 let mm = current_task.mm().unwrap();
4995
4996 let has = |addr: UserAddress| -> bool {
4997 let state = mm.state.read();
4998 state.mappings.get(addr).is_some()
4999 };
5000
5001 let brk_addr = mm
5002 .set_brk(¤t_task, UserAddress::default())
5003 .expect("failed to set initial program break");
5004 assert!(brk_addr > UserAddress::default());
5005
5006 let _ = mm
5008 .set_brk(¤t_task, (brk_addr + 1u64).unwrap())
5009 .expect("failed to grow program break");
5010 assert!(has(brk_addr));
5011
5012 let mapped_addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
5013 assert!(mapped_addr > UserAddress::default());
5014 assert!(has(mapped_addr));
5015
5016 let node = current_task.lookup_path_from_root("/".into()).unwrap();
5017 let new_mm = MemoryManager::exec(
5018 current_task.thread_group().root_vmar.unowned(),
5019 current_task.running_state().mm.to_option_arc(),
5020 node,
5021 ArchWidth::Arch64,
5022 )
5023 .expect("failed to exec memory manager");
5024 current_task.running_state().mm.update(Some(new_mm));
5025
5026 assert!(!has(brk_addr));
5027 assert!(!has(mapped_addr));
5028
5029 let brk_addr2 = map_memory(¤t_task, brk_addr, *PAGE_SIZE);
5031 assert_eq!(brk_addr, brk_addr2);
5032 let mapped_addr2 = map_memory(¤t_task, mapped_addr, *PAGE_SIZE);
5033 assert_eq!(mapped_addr, mapped_addr2);
5034 })
5035 .await;
5036 }
5037
5038 #[::fuchsia::test]
5039 async fn test_get_contiguous_mappings_at() {
5040 spawn_kernel_and_run(async |current_task| {
5041 let mm = current_task.mm().unwrap();
5042 let context = &mm.mapping_context;
5043
5044 let page_size = *PAGE_SIZE as usize;
5046 let addr_a = (mm.base_addr + 10 * page_size).unwrap();
5047 let addr_b = (mm.base_addr + 11 * page_size).unwrap();
5048 let addr_c = (mm.base_addr + 12 * page_size).unwrap();
5049 let addr_d = (mm.base_addr + 14 * page_size).unwrap();
5050 assert_eq!(map_memory(¤t_task, addr_a, *PAGE_SIZE), addr_a);
5051 assert_eq!(map_memory(¤t_task, addr_b, *PAGE_SIZE), addr_b);
5052 assert_eq!(map_memory(¤t_task, addr_c, *PAGE_SIZE), addr_c);
5053 assert_eq!(map_memory(¤t_task, addr_d, *PAGE_SIZE), addr_d);
5054
5055 {
5056 let mm_state = mm.state.read();
5057 assert_equal(
5059 mm_state
5060 .get_contiguous_mappings_at((addr_a - 100u64).unwrap(), 50, &context)
5061 .unwrap(),
5062 vec![],
5063 );
5064 assert_equal(
5065 mm_state
5066 .get_contiguous_mappings_at((addr_a - 100u64).unwrap(), 200, &context)
5067 .unwrap(),
5068 vec![],
5069 );
5070
5071 assert_equal(
5073 mm_state.get_contiguous_mappings_at(addr_a, 0, &context).unwrap(),
5074 vec![],
5075 );
5076
5077 assert_eq!(
5079 mm_state
5080 .get_contiguous_mappings_at(UserAddress::from(100), usize::MAX, &context)
5081 .err()
5082 .unwrap(),
5083 errno!(EFAULT)
5084 );
5085 assert_eq!(
5086 mm_state
5087 .get_contiguous_mappings_at(
5088 (context.max_address() + 1u64).unwrap(),
5089 0,
5090 &context
5091 )
5092 .err()
5093 .unwrap(),
5094 errno!(EFAULT)
5095 );
5096 }
5097
5098 assert_eq!(mm.get_mapping_count(), 2);
5099 let mm_state = mm.state.read();
5100 let (map_a, map_b) = {
5101 let mut it = mm_state.mappings.iter();
5102 (it.next().unwrap().1, it.next().unwrap().1)
5103 };
5104
5105 assert_equal(
5106 mm_state.get_contiguous_mappings_at(addr_a, page_size, &context).unwrap(),
5107 vec![(map_a, page_size)],
5108 );
5109
5110 assert_equal(
5111 mm_state.get_contiguous_mappings_at(addr_a, page_size / 2, &context).unwrap(),
5112 vec![(map_a, page_size / 2)],
5113 );
5114
5115 assert_equal(
5116 mm_state.get_contiguous_mappings_at(addr_a, page_size * 3, &context).unwrap(),
5117 vec![(map_a, page_size * 3)],
5118 );
5119
5120 assert_equal(
5121 mm_state.get_contiguous_mappings_at(addr_b, page_size, &context).unwrap(),
5122 vec![(map_a, page_size)],
5123 );
5124
5125 assert_equal(
5126 mm_state.get_contiguous_mappings_at(addr_d, page_size, &context).unwrap(),
5127 vec![(map_b, page_size)],
5128 );
5129
5130 assert_equal(
5132 mm_state
5133 .get_contiguous_mappings_at(
5134 (addr_a + page_size / 2).unwrap(),
5135 page_size * 10,
5136 &context,
5137 )
5138 .unwrap(),
5139 vec![(map_a, page_size * 2 + page_size / 2)],
5140 );
5141
5142 assert_equal(
5144 mm_state.get_contiguous_mappings_at(addr_d, page_size * 10, &context).unwrap(),
5145 vec![(map_b, page_size)],
5146 );
5147 })
5148 .await;
5149 }
5150
5151 #[::fuchsia::test]
5152 async fn test_read_write_crossing_mappings() {
5153 spawn_kernel_and_run(async |current_task| {
5154 let mm = current_task.mm().unwrap();
5155 let ma = current_task.deref();
5156
5157 let page_size = *PAGE_SIZE;
5159 let addr = (mm.base_addr + 10 * page_size).unwrap();
5160 assert_eq!(map_memory(¤t_task, addr, page_size), addr);
5161 assert_eq!(
5162 map_memory(¤t_task, (addr + page_size).unwrap(), page_size),
5163 (addr + page_size).unwrap()
5164 );
5165 assert_eq!(mm.get_mapping_count(), 1);
5167
5168 let test_addr = (addr + page_size / 2).unwrap();
5170 let data: Vec<u8> = (0..page_size).map(|i| (i % 256) as u8).collect();
5171 ma.write_memory(test_addr, &data).expect("failed to write test data");
5172
5173 let data_readback =
5175 ma.read_memory_to_vec(test_addr, data.len()).expect("failed to read test data");
5176 assert_eq!(&data, &data_readback);
5177 })
5178 .await;
5179 }
5180
5181 #[::fuchsia::test]
5182 async fn test_read_write_errors() {
5183 spawn_kernel_and_run(async |current_task| {
5184 let ma = current_task.deref();
5185
5186 let page_size = *PAGE_SIZE;
5187 let addr = map_memory(¤t_task, UserAddress::default(), page_size);
5188 let buf = vec![0u8; page_size as usize];
5189
5190 let partial_addr_before = (addr - page_size / 2).unwrap();
5192 assert_eq!(ma.write_memory(partial_addr_before, &buf), error!(EFAULT));
5193 assert_eq!(ma.read_memory_to_vec(partial_addr_before, buf.len()), error!(EFAULT));
5194 let partial_addr_after = (addr + page_size / 2).unwrap();
5195 assert_eq!(ma.write_memory(partial_addr_after, &buf), error!(EFAULT));
5196 assert_eq!(ma.read_memory_to_vec(partial_addr_after, buf.len()), error!(EFAULT));
5197
5198 let unmapped_addr = (addr - 10 * page_size).unwrap();
5200 assert_eq!(ma.write_memory(unmapped_addr, &buf), error!(EFAULT));
5201 assert_eq!(ma.read_memory_to_vec(unmapped_addr, buf.len()), error!(EFAULT));
5202
5203 ma.write_memory(unmapped_addr, &[]).expect("failed to write no data");
5205 ma.read_memory_to_vec(unmapped_addr, 0).expect("failed to read no data");
5206 })
5207 .await;
5208 }
5209
5210 #[::fuchsia::test]
5211 async fn test_read_c_string_to_vec_large() {
5212 spawn_kernel_and_run(async |current_task| {
5213 let mm = current_task.mm().unwrap();
5214 let ma = current_task.deref();
5215
5216 let page_size = *PAGE_SIZE;
5217 let max_size = 4 * page_size as usize;
5218 let addr = (mm.base_addr + 10 * page_size).unwrap();
5219
5220 assert_eq!(map_memory(¤t_task, addr, max_size as u64), addr);
5221
5222 let mut random_data = vec![0; max_size];
5223 starnix_crypto::cprng_draw(&mut random_data);
5224 for i in 0..random_data.len() {
5226 if random_data[i] == 0 {
5227 random_data[i] = 1;
5228 }
5229 }
5230 random_data[max_size - 1] = 0;
5231
5232 ma.write_memory(addr, &random_data).expect("failed to write test string");
5233 assert_eq!(
5235 ma.read_c_string_to_vec(UserCString::new(current_task, addr), max_size).unwrap(),
5236 random_data[..max_size - 1]
5237 );
5238 })
5239 .await;
5240 }
5241
5242 #[::fuchsia::test]
5243 async fn test_read_c_string_to_vec() {
5244 spawn_kernel_and_run(async |current_task| {
5245 let mm = current_task.mm().unwrap();
5246 let ma = current_task.deref();
5247
5248 let page_size = *PAGE_SIZE;
5249 let max_size = 2 * page_size as usize;
5250 let addr = (mm.base_addr + 10 * page_size).unwrap();
5251
5252 assert_eq!(map_memory(¤t_task, addr, page_size), addr);
5254 let test_str = b"foo!";
5255 let test_addr =
5256 addr.checked_add(page_size as usize).unwrap().checked_sub(test_str.len()).unwrap();
5257 ma.write_memory(test_addr, test_str).expect("failed to write test string");
5258
5259 assert_eq!(
5261 ma.read_c_string_to_vec(UserCString::new(current_task, test_addr), max_size),
5262 error!(ENAMETOOLONG)
5263 );
5264
5265 ma.write_memory((addr + (page_size - 1)).unwrap(), b"\0").expect("failed to write nul");
5267 assert_eq!(
5268 ma.read_c_string_to_vec(UserCString::new(current_task, test_addr), max_size)
5269 .unwrap(),
5270 "foo"
5271 );
5272
5273 assert_eq!(
5275 map_memory(¤t_task, (addr + page_size).unwrap(), page_size),
5276 (addr + page_size).unwrap()
5277 );
5278 ma.write_memory((addr + (page_size - 1)).unwrap(), b"bar\0")
5282 .expect("failed to write extra chars");
5283 assert_eq!(
5284 ma.read_c_string_to_vec(UserCString::new(current_task, test_addr), max_size)
5285 .unwrap(),
5286 "foobar",
5287 );
5288
5289 assert_eq!(
5291 ma.read_c_string_to_vec(UserCString::new(current_task, test_addr), 2),
5292 error!(ENAMETOOLONG)
5293 );
5294
5295 assert_eq!(
5297 ma.read_c_string_to_vec(UserCString::null(current_task), max_size),
5298 error!(EFAULT)
5299 );
5300 })
5301 .await;
5302 }
5303
5304 #[::fuchsia::test]
5305 async fn can_read_argv_like_regions() {
5306 spawn_kernel_and_run(async |current_task| {
5307 let ma = current_task.deref();
5308
5309 let page_size = *PAGE_SIZE;
5311 let addr = map_memory_anywhere(¤t_task, page_size);
5312 assert!(!addr.is_null());
5313
5314 let mut payload = "first".as_bytes().to_vec();
5316 let mut expected_parses = vec![];
5317 ma.write_memory(addr, &payload).unwrap();
5318
5319 expected_parses.push(payload.clone());
5321 payload.push(0);
5322 ma.write_memory(addr, &payload).unwrap();
5323 assert_eq!(
5324 ma.read_nul_delimited_c_string_list(addr, payload.len()).unwrap(),
5325 expected_parses,
5326 );
5327
5328 let second = b"second";
5330 payload.extend(second);
5331 payload.push(0);
5332 expected_parses.push(second.to_vec());
5333
5334 let third = b"third";
5335 payload.extend(third);
5336 payload.push(0);
5337 expected_parses.push(third.to_vec());
5338
5339 ma.write_memory(addr, &payload).unwrap();
5340 assert_eq!(
5341 ma.read_nul_delimited_c_string_list(addr, payload.len()).unwrap(),
5342 expected_parses,
5343 );
5344 })
5345 .await;
5346 }
5347
5348 #[::fuchsia::test]
5349 async fn truncate_argv_like_regions() {
5350 spawn_kernel_and_run(async |current_task| {
5351 let ma = current_task.deref();
5352
5353 let page_size = *PAGE_SIZE;
5355 let addr = map_memory_anywhere(¤t_task, page_size);
5356 assert!(!addr.is_null());
5357
5358 let payload = b"first\0second\0third\0";
5359 ma.write_memory(addr, payload).unwrap();
5360 assert_eq!(
5361 ma.read_nul_delimited_c_string_list(addr, payload.len() - 3).unwrap(),
5362 vec![b"first".to_vec(), b"second".to_vec(), b"thi".to_vec()],
5363 "Skipping last three bytes of payload should skip last two bytes of 3rd string"
5364 );
5365 })
5366 .await;
5367 }
5368
5369 #[::fuchsia::test]
5370 async fn test_read_c_string() {
5371 spawn_kernel_and_run(async |current_task| {
5372 let mm = current_task.mm().unwrap();
5373 let ma = current_task.deref();
5374
5375 let page_size = *PAGE_SIZE;
5376 let buf_cap = 2 * page_size as usize;
5377 let mut buf = Vec::with_capacity(buf_cap);
5378 let buf = &mut buf.spare_capacity_mut()[..buf_cap];
5381 let addr = (mm.base_addr + 10 * page_size).unwrap();
5382
5383 assert_eq!(map_memory(¤t_task, addr, page_size), addr);
5385 let test_str = b"foo!";
5386 let test_addr = (addr + (page_size - test_str.len() as u64)).unwrap();
5387 ma.write_memory(test_addr, test_str).expect("failed to write test string");
5388
5389 assert_eq!(
5391 ma.read_c_string(UserCString::new(current_task, test_addr), buf),
5392 error!(ENAMETOOLONG)
5393 );
5394
5395 ma.write_memory((addr + (page_size - 1)).unwrap(), b"\0").expect("failed to write nul");
5397 assert_eq!(
5398 ma.read_c_string(UserCString::new(current_task, test_addr), buf).unwrap(),
5399 "foo"
5400 );
5401
5402 assert_eq!(
5404 map_memory(¤t_task, (addr + page_size).unwrap(), page_size),
5405 (addr + page_size).unwrap()
5406 );
5407 ma.write_memory((addr + (page_size - 1)).unwrap(), b"bar\0")
5411 .expect("failed to write extra chars");
5412 assert_eq!(
5413 ma.read_c_string(UserCString::new(current_task, test_addr), buf).unwrap(),
5414 "foobar"
5415 );
5416
5417 assert_eq!(
5419 ma.read_c_string(
5420 UserCString::new(current_task, test_addr),
5421 &mut [MaybeUninit::uninit(); 2]
5422 ),
5423 error!(ENAMETOOLONG)
5424 );
5425
5426 assert_eq!(ma.read_c_string(UserCString::null(current_task), buf), error!(EFAULT));
5428 })
5429 .await;
5430 }
5431
5432 #[::fuchsia::test]
5433 async fn test_find_next_unused_range() {
5434 spawn_kernel_and_run(async |current_task| {
5435 let mm = current_task.mm().unwrap();
5436
5437 let mmap_top = mm.state.read().find_next_unused_range(0).unwrap().ptr();
5438 let page_size = *PAGE_SIZE as usize;
5439 assert!(mmap_top <= RESTRICTED_ASPACE_HIGHEST_ADDRESS);
5440
5441 assert_eq!(
5443 mm.state.read().find_next_unused_range(page_size).unwrap(),
5444 UserAddress::from_ptr(mmap_top - page_size)
5445 );
5446
5447 let addr = UserAddress::from_ptr(mmap_top - page_size);
5449 assert_eq!(map_memory(¤t_task, addr, *PAGE_SIZE), addr);
5450
5451 assert_eq!(
5453 mm.state.read().find_next_unused_range(page_size).unwrap(),
5454 UserAddress::from_ptr(addr.ptr() - page_size)
5455 );
5456
5457 let addr2 = UserAddress::from_ptr(addr.ptr() - 2 * page_size);
5459 assert_eq!(map_memory(¤t_task, addr2, *PAGE_SIZE), addr2);
5460
5461 assert_eq!(
5463 mm.state.read().find_next_unused_range(page_size).unwrap(),
5464 UserAddress::from_ptr(addr.ptr() - page_size)
5465 );
5466
5467 assert_eq!(
5469 mm.state.read().find_next_unused_range(2 * page_size).unwrap(),
5470 UserAddress::from_ptr(addr2.ptr() - 2 * page_size)
5471 );
5472
5473 assert_eq!(mm.state.read().find_next_unused_range(mmap_top), None);
5475 })
5476 .await;
5477 }
5478
5479 #[::fuchsia::test]
5480 async fn test_count_placements() {
5481 spawn_kernel_and_run(async |current_task| {
5482 let mm = current_task.mm().unwrap();
5483
5484 let page_size = *PAGE_SIZE as usize;
5486 let subrange_ten = UserAddress::from_ptr(RESTRICTED_ASPACE_BASE)
5487 ..UserAddress::from_ptr(RESTRICTED_ASPACE_BASE + 10 * page_size);
5488
5489 assert_eq!(
5490 mm.state.read().count_possible_placements(11 * page_size, &subrange_ten),
5491 Some(0)
5492 );
5493 assert_eq!(
5494 mm.state.read().count_possible_placements(10 * page_size, &subrange_ten),
5495 Some(1)
5496 );
5497 assert_eq!(
5498 mm.state.read().count_possible_placements(9 * page_size, &subrange_ten),
5499 Some(2)
5500 );
5501 assert_eq!(
5502 mm.state.read().count_possible_placements(page_size, &subrange_ten),
5503 Some(10)
5504 );
5505
5506 let addr = UserAddress::from_ptr(RESTRICTED_ASPACE_BASE + 5 * page_size);
5508 assert_eq!(map_memory(¤t_task, addr, *PAGE_SIZE), addr);
5509
5510 assert_eq!(
5511 mm.state.read().count_possible_placements(10 * page_size, &subrange_ten),
5512 Some(0)
5513 );
5514 assert_eq!(
5515 mm.state.read().count_possible_placements(5 * page_size, &subrange_ten),
5516 Some(1)
5517 );
5518 assert_eq!(
5519 mm.state.read().count_possible_placements(4 * page_size, &subrange_ten),
5520 Some(3)
5521 );
5522 assert_eq!(
5523 mm.state.read().count_possible_placements(page_size, &subrange_ten),
5524 Some(9)
5525 );
5526 })
5527 .await;
5528 }
5529
5530 #[::fuchsia::test]
5531 async fn test_pick_placement() {
5532 spawn_kernel_and_run(async |current_task| {
5533 let mm = current_task.mm().unwrap();
5534
5535 let page_size = *PAGE_SIZE as usize;
5536 let subrange_ten = UserAddress::from_ptr(RESTRICTED_ASPACE_BASE)
5537 ..UserAddress::from_ptr(RESTRICTED_ASPACE_BASE + 10 * page_size);
5538
5539 let addr = UserAddress::from_ptr(RESTRICTED_ASPACE_BASE + 5 * page_size);
5540 assert_eq!(map_memory(¤t_task, addr, *PAGE_SIZE), addr);
5541 assert_eq!(
5542 mm.state.read().count_possible_placements(4 * page_size, &subrange_ten),
5543 Some(3)
5544 );
5545
5546 assert_eq!(
5547 mm.state.read().pick_placement(4 * page_size, 0, &subrange_ten),
5548 Some(UserAddress::from_ptr(RESTRICTED_ASPACE_BASE))
5549 );
5550 assert_eq!(
5551 mm.state.read().pick_placement(4 * page_size, 1, &subrange_ten),
5552 Some(UserAddress::from_ptr(RESTRICTED_ASPACE_BASE + page_size))
5553 );
5554 assert_eq!(
5555 mm.state.read().pick_placement(4 * page_size, 2, &subrange_ten),
5556 Some(UserAddress::from_ptr(RESTRICTED_ASPACE_BASE + 6 * page_size))
5557 );
5558 })
5559 .await;
5560 }
5561
5562 #[::fuchsia::test]
5563 async fn test_find_random_unused_range() {
5564 spawn_kernel_and_run(async |current_task| {
5565 let mm = current_task.mm().unwrap();
5566
5567 let page_size = *PAGE_SIZE as usize;
5569 let subrange_ten = UserAddress::from_ptr(RESTRICTED_ASPACE_BASE)
5570 ..UserAddress::from_ptr(RESTRICTED_ASPACE_BASE + 10 * page_size);
5571
5572 for _ in 0..10 {
5573 let addr = mm.state.read().find_random_unused_range(page_size, &subrange_ten);
5574 assert!(addr.is_some());
5575 assert_eq!(map_memory(¤t_task, addr.unwrap(), *PAGE_SIZE), addr.unwrap());
5576 }
5577 assert_eq!(mm.state.read().find_random_unused_range(page_size, &subrange_ten), None);
5578 })
5579 .await;
5580 }
5581
5582 #[::fuchsia::test]
5583 async fn test_grows_down_near_aspace_base() {
5584 spawn_kernel_and_run(async |current_task| {
5585 let mm = current_task.mm().unwrap();
5586
5587 let page_count = 10;
5588
5589 let page_size = *PAGE_SIZE as usize;
5590 let addr =
5591 (UserAddress::from_ptr(RESTRICTED_ASPACE_BASE) + page_count * page_size).unwrap();
5592 assert_eq!(
5593 map_memory_with_flags(
5594 ¤t_task,
5595 addr,
5596 page_size as u64,
5597 MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN
5598 ),
5599 addr
5600 );
5601
5602 let subrange_ten = UserAddress::from_ptr(RESTRICTED_ASPACE_BASE)..addr;
5603 assert_eq!(mm.state.read().find_random_unused_range(page_size, &subrange_ten), None);
5604 })
5605 .await;
5606 }
5607
5608 #[::fuchsia::test]
5609 async fn test_unmap_returned_mappings() {
5610 spawn_kernel_and_run(async |current_task| {
5611 let mm = current_task.mm().unwrap();
5612
5613 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE * 2);
5614
5615 let mut released_mappings = ReleasedMappings::default();
5616 let mut mm_state = mm.state.write();
5617 let unmap_result =
5618 mm_state.unmap(&mm, addr, *PAGE_SIZE as usize, &mut released_mappings);
5619 assert!(unmap_result.is_ok());
5620 assert_eq!(released_mappings.len(), 1);
5621 released_mappings.finalize(mm_state);
5622 })
5623 .await;
5624 }
5625
5626 #[::fuchsia::test]
5627 async fn test_unmap_returns_multiple_mappings() {
5628 spawn_kernel_and_run(async |current_task| {
5629 let mm = current_task.mm().unwrap();
5630
5631 let addr = mm.state.read().find_next_unused_range(3 * *PAGE_SIZE as usize).unwrap();
5632 let addr = map_memory(¤t_task, addr, *PAGE_SIZE);
5633 let _ = map_memory(¤t_task, (addr + 2 * *PAGE_SIZE).unwrap(), *PAGE_SIZE);
5634
5635 let mut released_mappings = ReleasedMappings::default();
5636 let mut mm_state = mm.state.write();
5637 let unmap_result =
5638 mm_state.unmap(&mm, addr, (*PAGE_SIZE * 3) as usize, &mut released_mappings);
5639 assert!(unmap_result.is_ok());
5640 assert_eq!(released_mappings.len(), 2);
5641 released_mappings.finalize(mm_state);
5642 })
5643 .await;
5644 }
5645
5646 #[::fuchsia::test]
5649 async fn test_map_two_unmap_one() {
5650 spawn_kernel_and_run(async |current_task| {
5651 let mm = current_task.mm().unwrap();
5652
5653 let addr_reserve = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE * 2);
5655 let addr1 = do_mmap(
5656 ¤t_task,
5657 addr_reserve,
5658 *PAGE_SIZE as usize,
5659 PROT_READ, MAP_ANONYMOUS | MAP_SHARED | MAP_FIXED,
5661 FdNumber::from_raw(-1),
5662 0,
5663 )
5664 .expect("failed to mmap");
5665 let addr2 = map_memory_with_flags(
5666 ¤t_task,
5667 (addr_reserve + *PAGE_SIZE).unwrap(),
5668 *PAGE_SIZE,
5669 MAP_ANONYMOUS | MAP_SHARED | MAP_FIXED,
5670 );
5671 let state = mm.state.read();
5672 let (range1, _) = state.mappings.get(addr1).expect("mapping");
5673 assert_eq!(range1.start, addr1);
5674 assert_eq!(range1.end, (addr1 + *PAGE_SIZE).unwrap());
5675 let (range2, mapping2) = state.mappings.get(addr2).expect("mapping");
5676 assert_eq!(range2.start, addr2);
5677 assert_eq!(range2.end, (addr2 + *PAGE_SIZE).unwrap());
5678 let original_memory2 = {
5679 match state.get_mapping_backing(mapping2) {
5680 MappingBacking::Memory(backing) => {
5681 assert_eq!(backing.memory().get_size(), *PAGE_SIZE);
5682 backing.memory().clone()
5683 }
5684 MappingBacking::PrivateAnonymous => {
5685 panic!("Unexpected private anonymous mapping")
5686 }
5687 }
5688 };
5689 std::mem::drop(state);
5690
5691 assert_eq!(mm.unmap(addr1, *PAGE_SIZE as usize), Ok(()));
5692
5693 let state = mm.state.read();
5694
5695 assert!(state.mappings.get(addr1).is_none());
5697
5698 let (range2, mapping2) = state.mappings.get(addr2).expect("second page");
5700 assert_eq!(range2.start, addr2);
5701 assert_eq!(range2.end, (addr2 + *PAGE_SIZE).unwrap());
5702 match state.get_mapping_backing(mapping2) {
5703 MappingBacking::Memory(backing) => {
5704 assert_eq!(backing.memory().get_size(), *PAGE_SIZE);
5705 assert_eq!(original_memory2.get_koid(), backing.memory().get_koid());
5706 }
5707 MappingBacking::PrivateAnonymous => panic!("Unexpected private anonymous mapping"),
5708 }
5709 })
5710 .await;
5711 }
5712
5713 #[::fuchsia::test]
5714 async fn test_read_write_objects() {
5715 spawn_kernel_and_run(async |current_task| {
5716 let ma = current_task.deref();
5717 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
5718 let items_ref = UserRef::<i32>::new(addr);
5719
5720 let items_written = vec![0, 2, 3, 7, 1];
5721 ma.write_objects(items_ref, &items_written).expect("Failed to write object array.");
5722
5723 let items_read = ma
5724 .read_objects_to_vec(items_ref, items_written.len())
5725 .expect("Failed to read object array.");
5726
5727 assert_eq!(items_written, items_read);
5728 })
5729 .await;
5730 }
5731
5732 #[::fuchsia::test]
5733 async fn test_read_write_objects_null() {
5734 spawn_kernel_and_run(async |current_task| {
5735 let ma = current_task.deref();
5736 let items_ref = UserRef::<i32>::new(UserAddress::default());
5737
5738 let items_written = vec![];
5739 ma.write_objects(items_ref, &items_written)
5740 .expect("Failed to write empty object array.");
5741
5742 let items_read = ma
5743 .read_objects_to_vec(items_ref, items_written.len())
5744 .expect("Failed to read empty object array.");
5745
5746 assert_eq!(items_written, items_read);
5747 })
5748 .await;
5749 }
5750
5751 #[::fuchsia::test]
5752 async fn test_read_object_partial() {
5753 #[derive(Debug, Default, Copy, Clone, KnownLayout, FromBytes, Immutable, PartialEq)]
5754 struct Items {
5755 val: [i32; 4],
5756 }
5757
5758 spawn_kernel_and_run(async |current_task| {
5759 let ma = current_task.deref();
5760 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
5761 let items_array_ref = UserRef::<i32>::new(addr);
5762
5763 let items_written = vec![75, 23, 51, 98];
5765 ma.write_objects(items_array_ref, &items_written)
5766 .expect("Failed to write object array.");
5767
5768 let items_ref = UserRef::<Items>::new(addr);
5770 let items_read = ma
5771 .read_object_partial(items_ref, std::mem::size_of::<Items>())
5772 .expect("Failed to read object");
5773 assert_eq!(items_written, items_read.val);
5774
5775 let items_read = ma.read_object_partial(items_ref, 8).expect("Failed to read object");
5777 assert_eq!(vec![75, 23, 0, 0], items_read.val);
5778
5779 let items_read = ma.read_object_partial(items_ref, 0).expect("Failed to read object");
5782 assert_eq!(vec![0, 0, 0, 0], items_read.val);
5783
5784 assert_eq!(
5786 ma.read_object_partial(items_ref, std::mem::size_of::<Items>() + 8),
5787 error!(EINVAL)
5788 );
5789
5790 assert_eq!(
5792 ma.read_object_partial(UserRef::<Items>::new(UserAddress::from(1)), 16),
5793 error!(EFAULT)
5794 );
5795 })
5796 .await;
5797 }
5798
5799 #[::fuchsia::test]
5800 async fn test_partial_read() {
5801 spawn_kernel_and_run(async |current_task| {
5802 let mm = current_task.mm().unwrap();
5803 let ma = current_task.deref();
5804
5805 let addr = mm.state.read().find_next_unused_range(2 * *PAGE_SIZE as usize).unwrap();
5806 let addr = map_memory(¤t_task, addr, *PAGE_SIZE);
5807 let second_map = map_memory(¤t_task, (addr + *PAGE_SIZE).unwrap(), *PAGE_SIZE);
5808
5809 let bytes = vec![0xf; (*PAGE_SIZE * 2) as usize];
5810 assert!(ma.write_memory(addr, &bytes).is_ok());
5811 let mut state = mm.state.write();
5812 let mut released_mappings = ReleasedMappings::default();
5813 state
5814 .protect(
5815 ma,
5816 second_map,
5817 *PAGE_SIZE as usize,
5818 ProtectionFlags::empty(),
5819 &mut released_mappings,
5820 )
5821 .unwrap();
5822 released_mappings.finalize(state);
5823 assert_eq!(
5824 ma.read_memory_partial_to_vec(addr, bytes.len()).unwrap().len(),
5825 *PAGE_SIZE as usize,
5826 );
5827 })
5828 .await;
5829 }
5830
5831 fn map_memory_growsdown(current_task: &CurrentTask, length: u64) -> UserAddress {
5832 map_memory_with_flags(
5833 current_task,
5834 UserAddress::default(),
5835 length,
5836 MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN,
5837 )
5838 }
5839
5840 #[::fuchsia::test]
5841 async fn test_grow_mapping_empty_mm() {
5842 spawn_kernel_and_run(async |current_task| {
5843 let mm = current_task.mm().unwrap();
5844
5845 let addr = UserAddress::from(0x100000);
5846
5847 assert_matches!(mm.extend_growsdown_mapping_to_address(addr, false), Ok(false));
5848 })
5849 .await;
5850 }
5851
5852 #[::fuchsia::test]
5853 async fn test_grow_inside_mapping() {
5854 spawn_kernel_and_run(async |current_task| {
5855 let mm = current_task.mm().unwrap();
5856
5857 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
5858
5859 assert_matches!(mm.extend_growsdown_mapping_to_address(addr, false), Ok(false));
5860 })
5861 .await;
5862 }
5863
5864 #[::fuchsia::test]
5865 async fn test_grow_write_fault_inside_read_only_mapping() {
5866 spawn_kernel_and_run(async |current_task| {
5867 let mm = current_task.mm().unwrap();
5868
5869 let addr = do_mmap(
5870 ¤t_task,
5871 UserAddress::default(),
5872 *PAGE_SIZE as usize,
5873 PROT_READ,
5874 MAP_ANONYMOUS | MAP_PRIVATE,
5875 FdNumber::from_raw(-1),
5876 0,
5877 )
5878 .expect("Could not map memory");
5879
5880 assert_matches!(mm.extend_growsdown_mapping_to_address(addr, false), Ok(false));
5881 assert_matches!(mm.extend_growsdown_mapping_to_address(addr, true), Ok(false));
5882 })
5883 .await;
5884 }
5885
5886 #[::fuchsia::test]
5887 async fn test_grow_fault_inside_prot_none_mapping() {
5888 spawn_kernel_and_run(async |current_task| {
5889 let mm = current_task.mm().unwrap();
5890
5891 let addr = do_mmap(
5892 ¤t_task,
5893 UserAddress::default(),
5894 *PAGE_SIZE as usize,
5895 PROT_NONE,
5896 MAP_ANONYMOUS | MAP_PRIVATE,
5897 FdNumber::from_raw(-1),
5898 0,
5899 )
5900 .expect("Could not map memory");
5901
5902 assert_matches!(mm.extend_growsdown_mapping_to_address(addr, false), Ok(false));
5903 assert_matches!(mm.extend_growsdown_mapping_to_address(addr, true), Ok(false));
5904 })
5905 .await;
5906 }
5907
5908 #[::fuchsia::test]
5909 async fn test_grow_below_mapping() {
5910 spawn_kernel_and_run(async |current_task| {
5911 let mm = current_task.mm().unwrap();
5912
5913 let addr = map_memory_growsdown(¤t_task, *PAGE_SIZE) - *PAGE_SIZE;
5914
5915 assert_matches!(mm.extend_growsdown_mapping_to_address(addr.unwrap(), false), Ok(true));
5916 })
5917 .await;
5918 }
5919
5920 #[::fuchsia::test]
5921 async fn test_grow_above_mapping() {
5922 spawn_kernel_and_run(async |current_task| {
5923 let mm = current_task.mm().unwrap();
5924
5925 let addr = map_memory_growsdown(¤t_task, *PAGE_SIZE) + *PAGE_SIZE;
5926
5927 assert_matches!(
5928 mm.extend_growsdown_mapping_to_address(addr.unwrap(), false),
5929 Ok(false)
5930 );
5931 })
5932 .await;
5933 }
5934
5935 #[::fuchsia::test]
5936 async fn test_grow_write_fault_below_read_only_mapping() {
5937 spawn_kernel_and_run(async |current_task| {
5938 let mm = current_task.mm().unwrap();
5939
5940 let mapped_addr = map_memory_growsdown(¤t_task, *PAGE_SIZE);
5941
5942 mm.protect(¤t_task, mapped_addr, *PAGE_SIZE as usize, ProtectionFlags::READ)
5943 .unwrap();
5944
5945 assert_matches!(
5946 mm.extend_growsdown_mapping_to_address((mapped_addr - *PAGE_SIZE).unwrap(), true),
5947 Ok(false)
5948 );
5949
5950 assert_eq!(mm.get_mapping_count(), 1);
5951 })
5952 .await;
5953 }
5954
5955 #[::fuchsia::test]
5956 async fn test_snapshot_paged_memory() {
5957 use zx::sys::zx_page_request_command_t::ZX_PAGER_VMO_READ;
5958
5959 spawn_kernel_and_run(async |current_task| {
5960 let mm = current_task.mm().unwrap();
5961 let ma = current_task.deref();
5962
5963 let port = Arc::new(zx::Port::create());
5964 let port_clone = port.clone();
5965 let pager =
5966 Arc::new(zx::Pager::create(zx::PagerOptions::empty()).expect("create failed"));
5967 let pager_clone = pager.clone();
5968
5969 const VMO_SIZE: u64 = 128 * 1024;
5970 let vmo = Arc::new(
5971 pager
5972 .create_vmo(zx::VmoOptions::RESIZABLE, &port, 1, VMO_SIZE)
5973 .expect("create_vmo failed"),
5974 );
5975 let vmo_clone = vmo.clone();
5976
5977 let thread = std::thread::spawn(move || {
5979 loop {
5980 let packet =
5981 port_clone.wait(zx::MonotonicInstant::INFINITE).expect("wait failed");
5982 match packet.contents() {
5983 zx::PacketContents::Pager(contents) => {
5984 if contents.command() == ZX_PAGER_VMO_READ {
5985 let range = contents.range();
5986 let source_vmo = zx::Vmo::create(range.end - range.start)
5987 .expect("create failed");
5988 pager_clone
5989 .supply_pages(&vmo_clone, range, &source_vmo, 0)
5990 .expect("supply_pages failed");
5991 }
5992 }
5993 zx::PacketContents::User(_) => break,
5994 _ => {}
5995 }
5996 }
5997 });
5998
5999 let child_vmo = vmo
6000 .create_child(zx::VmoChildOptions::SNAPSHOT_AT_LEAST_ON_WRITE, 0, VMO_SIZE)
6001 .unwrap();
6002
6003 vmo.write(b"foo", 0).expect("write failed");
6005
6006 let prot_flags = ProtectionFlags::READ | ProtectionFlags::WRITE;
6007 let addr = mm
6008 .map_memory(
6009 DesiredAddress::Any,
6010 Arc::new(MemoryObject::from(child_vmo)),
6011 0,
6012 VMO_SIZE as usize,
6013 prot_flags,
6014 Access::rwx(),
6015 MappingOptions::empty(),
6016 MappingName::None,
6017 )
6018 .expect("map failed");
6019
6020 let target = current_task.clone_task_for_test(0, None);
6021
6022 let buf = target.read_memory_to_vec(addr, 3).expect("read_memory failed");
6024 assert_eq!(buf, b"foo");
6025
6026 ma.write_memory(addr, b"bar").expect("write_memory failed");
6028
6029 let buf = target.read_memory_to_vec(addr, 3).expect("read_memory failed");
6030 assert_eq!(buf, b"foo");
6031
6032 target.write_memory(addr, b"baz").expect("write_memory failed");
6033 let buf = ma.read_memory_to_vec(addr, 3).expect("read_memory failed");
6034 assert_eq!(buf, b"bar");
6035
6036 let buf = target.read_memory_to_vec(addr, 3).expect("read_memory failed");
6037 assert_eq!(buf, b"baz");
6038
6039 port.queue(&zx::Packet::from_user_packet(0, 0, zx::UserPacket::from_u8_array([0; 32])))
6040 .unwrap();
6041 thread.join().unwrap();
6042 })
6043 .await;
6044 }
6045
6046 #[::fuchsia::test]
6047 async fn test_set_vma_name() {
6048 spawn_kernel_and_run(async |mut current_task| {
6049 let name_addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
6050
6051 let vma_name = "vma name";
6052 current_task.write_memory(name_addr, vma_name.as_bytes()).unwrap();
6053
6054 let mapping_addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
6055
6056 sys_prctl(
6057 &mut current_task,
6058 PR_SET_VMA,
6059 PR_SET_VMA_ANON_NAME as u64,
6060 mapping_addr.ptr() as u64,
6061 *PAGE_SIZE,
6062 name_addr.ptr() as u64,
6063 )
6064 .unwrap();
6065
6066 assert_eq!(
6067 *current_task.mm().unwrap().get_mapping_name(mapping_addr).unwrap().unwrap(),
6068 vma_name
6069 );
6070 })
6071 .await;
6072 }
6073
6074 #[::fuchsia::test]
6075 async fn test_set_vma_name_adjacent_mappings() {
6076 spawn_kernel_and_run(async |mut current_task| {
6077 let name_addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
6078 current_task
6079 .write_memory(name_addr, CString::new("foo").unwrap().as_bytes_with_nul())
6080 .unwrap();
6081
6082 let first_mapping_addr =
6083 map_memory(¤t_task, UserAddress::default(), 2 * *PAGE_SIZE);
6084 let second_mapping_addr = map_memory_with_flags(
6085 ¤t_task,
6086 (first_mapping_addr + *PAGE_SIZE).unwrap(),
6087 *PAGE_SIZE,
6088 MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
6089 );
6090
6091 assert_eq!((first_mapping_addr + *PAGE_SIZE).unwrap(), second_mapping_addr);
6092
6093 sys_prctl(
6094 &mut current_task,
6095 PR_SET_VMA,
6096 PR_SET_VMA_ANON_NAME as u64,
6097 first_mapping_addr.ptr() as u64,
6098 2 * *PAGE_SIZE,
6099 name_addr.ptr() as u64,
6100 )
6101 .unwrap();
6102
6103 {
6104 let mm = current_task.mm().unwrap();
6105 let state = mm.state.read();
6106
6107 let (_, mapping) = state.mappings.get(first_mapping_addr).unwrap();
6109 assert_eq!(mapping.name(), MappingName::Vma("foo".into()));
6110
6111 let (_, mapping) = state.mappings.get(second_mapping_addr).unwrap();
6112 assert_eq!(mapping.name(), MappingName::Vma("foo".into()));
6113 }
6114 })
6115 .await;
6116 }
6117
6118 #[::fuchsia::test]
6119 async fn test_set_vma_name_beyond_end() {
6120 spawn_kernel_and_run(async |mut current_task| {
6121 let name_addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
6122 current_task
6123 .write_memory(name_addr, CString::new("foo").unwrap().as_bytes_with_nul())
6124 .unwrap();
6125
6126 let mapping_addr = map_memory(¤t_task, UserAddress::default(), 2 * *PAGE_SIZE);
6127
6128 let second_page = (mapping_addr + *PAGE_SIZE).unwrap();
6129 current_task.mm().unwrap().unmap(second_page, *PAGE_SIZE as usize).unwrap();
6130
6131 assert_eq!(
6133 sys_prctl(
6134 &mut current_task,
6135 PR_SET_VMA,
6136 PR_SET_VMA_ANON_NAME as u64,
6137 mapping_addr.ptr() as u64,
6138 2 * *PAGE_SIZE,
6139 name_addr.ptr() as u64,
6140 ),
6141 error!(ENOMEM)
6142 );
6143
6144 {
6146 let mm = current_task.mm().unwrap();
6147 let state = mm.state.read();
6148
6149 let (_, mapping) = state.mappings.get(mapping_addr).unwrap();
6150 assert_eq!(mapping.name(), MappingName::Vma("foo".into()));
6151 }
6152 })
6153 .await;
6154 }
6155
6156 #[::fuchsia::test]
6157 async fn test_set_vma_name_before_start() {
6158 spawn_kernel_and_run(async |mut current_task| {
6159 let name_addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
6160 current_task
6161 .write_memory(name_addr, CString::new("foo").unwrap().as_bytes_with_nul())
6162 .unwrap();
6163
6164 let mapping_addr = map_memory(¤t_task, UserAddress::default(), 2 * *PAGE_SIZE);
6165
6166 let second_page = (mapping_addr + *PAGE_SIZE).unwrap();
6167 current_task.mm().unwrap().unmap(mapping_addr, *PAGE_SIZE as usize).unwrap();
6168
6169 assert_eq!(
6171 sys_prctl(
6172 &mut current_task,
6173 PR_SET_VMA,
6174 PR_SET_VMA_ANON_NAME as u64,
6175 mapping_addr.ptr() as u64,
6176 2 * *PAGE_SIZE,
6177 name_addr.ptr() as u64,
6178 ),
6179 error!(ENOMEM)
6180 );
6181
6182 {
6185 let mm = current_task.mm().unwrap();
6186 let state = mm.state.read();
6187
6188 let (_, mapping) = state.mappings.get(second_page).unwrap();
6189 assert_eq!(mapping.name(), MappingName::None);
6190 }
6191 })
6192 .await;
6193 }
6194
6195 #[::fuchsia::test]
6196 async fn test_set_vma_name_partial() {
6197 spawn_kernel_and_run(async |mut current_task| {
6198 let name_addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
6199 current_task
6200 .write_memory(name_addr, CString::new("foo").unwrap().as_bytes_with_nul())
6201 .unwrap();
6202
6203 let mapping_addr = map_memory(¤t_task, UserAddress::default(), 3 * *PAGE_SIZE);
6204
6205 assert_eq!(
6206 sys_prctl(
6207 &mut current_task,
6208 PR_SET_VMA,
6209 PR_SET_VMA_ANON_NAME as u64,
6210 (mapping_addr + *PAGE_SIZE).unwrap().ptr() as u64,
6211 *PAGE_SIZE,
6212 name_addr.ptr() as u64,
6213 ),
6214 Ok(starnix_syscalls::SUCCESS)
6215 );
6216
6217 {
6219 let mm = current_task.mm().unwrap();
6220 let state = mm.state.read();
6221
6222 let (_, mapping) = state.mappings.get(mapping_addr).unwrap();
6223 assert_eq!(mapping.name(), MappingName::None);
6224
6225 let (_, mapping) =
6226 state.mappings.get((mapping_addr + *PAGE_SIZE).unwrap()).unwrap();
6227 assert_eq!(mapping.name(), MappingName::Vma("foo".into()));
6228
6229 let (_, mapping) =
6230 state.mappings.get((mapping_addr + (2 * *PAGE_SIZE)).unwrap()).unwrap();
6231 assert_eq!(mapping.name(), MappingName::None);
6232 }
6233 })
6234 .await;
6235 }
6236
6237 #[::fuchsia::test]
6238 async fn test_preserve_name_snapshot() {
6239 spawn_kernel_and_run(async |mut current_task| {
6240 let name_addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
6241 current_task
6242 .write_memory(name_addr, CString::new("foo").unwrap().as_bytes_with_nul())
6243 .unwrap();
6244
6245 let mapping_addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
6246
6247 assert_eq!(
6248 sys_prctl(
6249 &mut current_task,
6250 PR_SET_VMA,
6251 PR_SET_VMA_ANON_NAME as u64,
6252 mapping_addr.ptr() as u64,
6253 *PAGE_SIZE,
6254 name_addr.ptr() as u64,
6255 ),
6256 Ok(starnix_syscalls::SUCCESS)
6257 );
6258
6259 let target = current_task.clone_task_for_test(0, None);
6260
6261 {
6262 let mm = target.mm().unwrap();
6263 let state = mm.state.read();
6264
6265 let (_, mapping) = state.mappings.get(mapping_addr).unwrap();
6266 assert_eq!(mapping.name(), MappingName::Vma("foo".into()));
6267 }
6268 })
6269 .await;
6270 }
6271}