From bf7709f345ce7435dc1289afbe9ef4df4eee7c0d Mon Sep 17 00:00:00 2001 From: Wang Siyuan Date: Wed, 7 Jan 2026 13:29:25 +0000 Subject: [PATCH] Support force-write via `/proc/pid/mem` --- kernel/src/vm/vmar/vm_mapping.rs | 38 +++++++++++++++++------- test/initramfs/src/apps/procfs/pid_mem.c | 9 +++--- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/kernel/src/vm/vmar/vm_mapping.rs b/kernel/src/vm/vmar/vm_mapping.rs index e78e24183..de28b65b2 100644 --- a/kernel/src/vm/vmar/vm_mapping.rs +++ b/kernel/src/vm/vmar/vm_mapping.rs @@ -331,15 +331,7 @@ impl VmMapping { page_fault_info: &PageFaultInfo, rss_delta: &mut RssDelta, ) -> Result<()> { - if !self.perms.contains(page_fault_info.required_perms) { - trace!( - "self.perms {:?}, page_fault_info.required_perms {:?}, self.range {:?}", - self.perms, - page_fault_info.required_perms, - self.range() - ); - return_errno_with_message!(Errno::EACCES, "perm check fails"); - } + self.check_perms_for_page_fault(page_fault_info)?; let page_aligned_addr = page_fault_info.address.align_down(PAGE_SIZE); let is_write = page_fault_info.required_perms.contains(VmPerms::WRITE); @@ -379,6 +371,33 @@ impl VmMapping { ) } + fn check_perms_for_page_fault(&self, page_fault_info: &PageFaultInfo) -> Result<()> { + trace!( + "self.perms {:?}, page_fault_info.required_perms {:?}, self.range {:?}", + self.perms, + page_fault_info.required_perms, + self.range() + ); + + let mut perms = self.perms; + + // Reference: + if page_fault_info.is_forced { + if perms.contains(VmPerms::MAY_READ) { + perms.insert(VmPerms::READ); + } + if self.is_cow() { + perms.insert(VmPerms::WRITE); + } + } + + if !perms.contains(page_fault_info.required_perms) { + return_errno_with_message!(Errno::EACCES, "perm check fails"); + } + + Ok(()) + } + fn handle_single_page_fault( &self, vm_space: &VmSpace, @@ -430,7 +449,6 @@ impl VmMapping { let new_frame = duplicate_frame(&frame)?; prop.flags |= new_flags; cursor.map(new_frame.into(), prop); - rss_delta.add(self.rss_type(), 1); } cursor.flusher().sync_tlb_flush(); } diff --git a/test/initramfs/src/apps/procfs/pid_mem.c b/test/initramfs/src/apps/procfs/pid_mem.c index 9d6d838ef..1b6cb2916 100644 --- a/test/initramfs/src/apps/procfs/pid_mem.c +++ b/test/initramfs/src/apps/procfs/pid_mem.c @@ -37,10 +37,11 @@ FN_TEST(proc_mem_remote) CHECK(close(pipe_p2c[1])); int fd = CHECK(open(FILE_NAME, O_RDONLY)); - void *addr = - CHECK_WITH(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, - MAP_PRIVATE, fd, 0), - _ret != MAP_FAILED); + // The parent should successfully read from and (force) write to this + // memory region via `/proc/pid/mem`, although it isn't `PROT_WRITE`. + void *addr = CHECK_WITH(mmap(NULL, PAGE_SIZE, PROT_READ, + MAP_PRIVATE, fd, 0), + _ret != MAP_FAILED); CHECK(write(pipe_c2p[1], &addr, sizeof(addr))); // Wait for the parent to read and write.