kernel: implement /proc/[pid]/maps — process memory map

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().
This commit is contained in:
2026-07-08 18:51:08 +03:00
parent ae03a7e60b
commit b8b9b02051
+38 -1
View File
@@ -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();