kernel: resolve /proc/self/fd/N and /proc/self/stat etc.

Extended /proc/self resolution to handle sub-paths like
/proc/self/fd/0, /proc/self/stat, /proc/self/status, etc.

Previously only /proc/self (the directory itself) was resolved.
Now /proc/self/fd, /proc/self/stat, /proc/self/maps, and all
other sub-paths are resolved by replacing 'self' with the
current PID and delegating to the standard proc_open() parser.

Cross-referenced with Linux 7.1 fs/proc/self.c proc_self_get_link()
which creates a symlink to the current PID directory. This
completes the /proc/self implementation for all sub-entries.
This commit is contained in:
2026-07-09 11:16:13 +03:00
parent ffa502b2cb
commit 6b69974f70
+21 -2
View File
@@ -534,7 +534,7 @@ impl ProcScheme {
token: &mut CleanLockToken,
) -> Result<(usize, InternalFlags)> {
let operation_name = operation_str.ok_or(Error::new(EINVAL))?;
// /proc/self → resolve to /proc/<current-pid>
// /proc/self[/...] → resolve /proc/<current-pid>[/...]
if operation_name == "proc/self" || operation_name == "self" {
let pid = context::current().read(token.token()).pid;
let handle = Handle {
@@ -542,7 +542,26 @@ impl ProcScheme {
kind: ContextHandle::ProcDir { pid },
};
return new_handle((handle, InternalFlags::POSITIONED), token);
};
}
if operation_name.starts_with("proc/self/") || operation_name.starts_with("self/") {
let pid = context::current().read(token.token()).pid;
let rest = if operation_name.starts_with("proc/self/") {
&operation_name["proc/self/".len()..]
} else {
&operation_name["self/".len()..]
};
let resolved = format!("proc/{}/{}", pid, rest);
let mut parts = resolved.split('/');
let _ = parts.next(); // "proc"
let pid = parts.next().and_then(|p| p.parse::<usize>().ok()).unwrap_or(pid);
if let Some(kind) = Self::proc_open(&resolved) {
let handle = Handle {
context: context::current(),
kind,
};
return new_handle((handle, InternalFlags::POSITIONED), token);
}
}
if let Some(kind) = Self::proc_open(operation_name) {
let handle = Handle {
context: context::current(),