diff --git a/src/context/memory.rs b/src/context/memory.rs index 09e0f4027b5310b2765aaf65c0eebf0930a90c38..36b447b70f7c4db200d64a9d284b5990424894fa 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -34,8 +34,6 @@ pub fn map_flags(page_flags: PageFlags<RmmA>) -> MapFlags { let mut flags = MapFlags::PROT_READ; if page_flags.has_write() { flags |= MapFlags::PROT_WRITE; } if page_flags.has_execute() { flags |= MapFlags::PROT_EXEC; } - // TODO: MAP_SHARED/MAP_PRIVATE (requires that grants keep track of what they borrow and if - // they borrow shared or CoW). flags } diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index 41537b5ab727e2662df8069e1fc93c5b6b127e88..74aff40cc7d968feb4dcc262df688026a05ec9aa 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -592,7 +592,7 @@ impl Scheme for ProcScheme { match handle.info.operation { Operation::AwaitingAddrSpaceChange { new, new_sp, new_ip } => { - stop_context(handle.info.pid, |context: &mut Context| unsafe { + let prev_addr_space = stop_context(handle.info.pid, |context: &mut Context| unsafe { if let Some(saved_regs) = ptrace::regs_for_mut(context) { #[cfg(target_arch = "aarch64")] { @@ -615,9 +615,7 @@ impl Scheme for ProcScheme { context.clone_entry = Some([new_ip, new_sp]); } - let _prev_addr_space = context.set_addr_space(new); - - Ok(()) + Ok(context.set_addr_space(new)) })?; let _ = ptrace::send_event(crate::syscall::ptrace_event!(PTRACE_EVENT_ADDRSPACE_SWITCH, 0)); } diff --git a/src/scheme/user.rs b/src/scheme/user.rs index 62db18104fec289efd966ce6be95aa26ef7d4ba2..b0a1c0907680fbec5a8523f1426b9710d0a84866 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -543,10 +543,15 @@ impl UserInner { }; let page_count_nz = NonZeroUsize::new(page_count).expect("already validated map.size != 0"); - let dst_base = dst_addr_space.write().mmap(dst_base, page_count_nz, map.flags | MAP_FIXED_NOREPLACE, &mut Vec::new(), |dst_base, flags, mapper, flusher| { + let mut notify_files = Vec::new(); + let dst_base = dst_addr_space.write().mmap(dst_base, page_count_nz, map.flags | MAP_FIXED_NOREPLACE, &mut notify_files, |dst_base, flags, mapper, flusher| { Grant::borrow_fmap(PageSpan::new(dst_base, page_count), page_flags(map.flags), file_ref, src, mapper, flusher) })?; + for map in notify_files { + let _ = map.unmap(); + } + Ok(dst_base.start_address().data()) } } @@ -829,6 +834,20 @@ impl KernelScheme for UserScheme { inner.fmap_inner(Arc::clone(addr_space), file, map) } + fn kfunmap(&self, number: usize, offset: usize, size: usize) -> Result<()> { + let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; + + let res = inner.call_extended(CallerCtx { + pid: context::context_id().into(), + uid: offset as u32, + gid: (offset >> 32) as u32, + }, [KSMSG_MUNMAP, number, size, 0])?; + + match res { + Response::Regular(_) => Ok(()), + Response::Fd(_) => Err(Error::new(EIO)), + } + } fn as_user_inner(&self) -> Option<Result<Arc<UserInner>>> { Some(self.inner.upgrade().ok_or(Error::new(ENODEV))) diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index 68e399c17ed35f4bea486053293c51fb9caaed37..cc97aee39a574fa2ca6e47203a2c2767732710da 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -387,6 +387,12 @@ pub fn fstat(fd: FileHandle, user_buf: UserSliceWo) -> Result<usize> { } pub fn funmap(virtual_address: usize, length: usize) -> Result<usize> { + // Partial lengths in funmap are allowed according to POSIX, but not particularly meaningful; + // since the memory needs to SIGSEGV if later read, the entire page needs to disappear. + // + // Thus, while (temporarily) allowing unaligned lengths for compatibility, aligning the length + // should be done by libc. + let length_aligned = length.next_multiple_of(PAGE_SIZE); if length != length_aligned { log::warn!("funmap passed length {:#x} instead of {:#x}", length, length_aligned); @@ -395,7 +401,11 @@ pub fn funmap(virtual_address: usize, length: usize) -> Result<usize> { let addr_space = Arc::clone(context::current()?.read().addr_space()?); let span = PageSpan::validate_nonempty(VirtualAddress::new(virtual_address), length_aligned).ok_or(Error::new(EINVAL))?; let unpin = false; - addr_space.write().munmap(span, unpin)?; + let notify = addr_space.write().munmap(span, unpin)?; + + for map in notify { + let _ = map.unmap(); + } Ok(0) } diff --git a/syscall b/syscall index ff149946c07628dde39db05997e221b5024ccb95..ed28083b73ed2b163e2d64ee3753f1d6ff6c94d1 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit ff149946c07628dde39db05997e221b5024ccb95 +Subproject commit ed28083b73ed2b163e2d64ee3753f1d6ff6c94d1