From b8b9b0205124af39b26a1d414efd015bc4502d03 Mon Sep 17 00:00:00 2001 From: vasilito Date: Wed, 8 Jul 2026 18:51:08 +0300 Subject: [PATCH] =?UTF-8?q?kernel:=20implement=20/proc/[pid]/maps=20?= =?UTF-8?q?=E2=80=94=20process=20memory=20map?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New ProcMaps ContextHandle that iterates over addr_space.grants and formats each grant in Linux /proc/[pid]/maps format: address_start-address_end perms 00000000 00:00 0 path Where perms is rwxp based on GrantFlags (GRANT_READ/WRITE/EXEC), and path is [file]/[vdso]/[heap] based on whether the grant is file-backed and its address range. Cross-referenced with Linux 7.1 fs/proc/task_mmu.c proc_pid_maps_op and show_vma_header_prefix/show_map_vma(). --- src/scheme/proc.rs | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index ba95f34ed7..d22f0af5b5 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -20,7 +20,7 @@ use crate::{ }; use super::{CallerCtx, KernelSchemes, OpenResult}; -use ::syscall::{ProcSchemeAttrs, SigProcControl, Sigcontrol}; +use ::syscall::{GrantFlags, ProcSchemeAttrs, SigProcControl, Sigcontrol}; use alloc::{ boxed::Box, string::{String, ToString}, @@ -170,6 +170,9 @@ enum ContextHandle { ProcStatus { pid: usize, }, + ProcMaps { + pid: usize, + }, } #[derive(Clone)] struct Handle { @@ -389,6 +392,7 @@ impl ProcScheme { (Some("comm"), None) => Some(ContextHandle::ProcComm { pid }), (Some("cmdline"), None) => Some(ContextHandle::ProcCmdline { pid }), (Some("status"), None) => Some(ContextHandle::ProcStatus { pid }), + (Some("maps"), None) => Some(ContextHandle::ProcMaps { pid }), _ => None, } } @@ -1893,6 +1897,39 @@ impl ContextHandle { let context = context.read(token.token()); read_from(buf, proc_status_text(&context, num_threads, vsize, rss).as_bytes(), offset) } + ContextHandle::ProcMaps { pid } => { + let context = proc_context(*pid, token).ok_or(Error::new(ESRCH))?; + let addr_space = context.read(token.token()).addr_space.clone(); + let mut output = String::new(); + if let Some(addr_space) = addr_space { + let token2 = token.downgrade(); + let guard = addr_space.acquire_read(token2); + for (grant_base, grant_info) in guard.grants.iter() { + let start = grant_base.start_address().data(); + let size = grant_info.page_count() * PAGE_SIZE; + let end = start + size; + let grant_flags = grant_info.grant_flags(); + let perms = alloc::format!( + "{}{}{}p", + if grant_flags.contains(GrantFlags::GRANT_READ) { 'r' } else { '-' }, + if grant_flags.contains(GrantFlags::GRANT_WRITE) { 'w' } else { '-' }, + if grant_flags.contains(GrantFlags::GRANT_EXEC) { 'x' } else { '-' }, + ); + let path_str = if grant_info.file_ref().is_some() { + String::from("[file]") + } else if start < 0x10000000 { + String::from("[vdso]") + } else { + String::from("[heap]") + }; + output.push_str(&alloc::format!( + "{:08x}-{:08x} {} 00000000 00:00 0 {}\n", + start, end, perms, path_str + )); + } + } + read_from(buf, output.as_bytes(), offset) + } ContextHandle::ProcRoot | ContextHandle::ProcDir { .. } => Err(Error::new(EBADF)), ContextHandle::MmapMinAddr(addrspace) => { let mut token = token.token();