| Crates.io | proc-canonicalize |
| lib.rs | proc-canonicalize |
| version | 0.1.2 |
| created_at | 2025-12-09 21:54:49.49239+00 |
| updated_at | 2025-12-16 14:49:56.701121+00 |
| description | Fix std::fs::canonicalize for /proc/PID/root and /proc/PID/cwd paths on Linux |
| homepage | |
| repository | https://github.com/DK26/proc-canonicalize-rs |
| max_upload_size | |
| id | 1976811 |
| size | 178,951 |
A patch for std::fs::canonicalize that preserves Linux /proc/PID/root namespace boundaries.
On Linux, /proc/PID/root is a "magic symlink" that crosses into a process's mount namespace. When you access files through it, you're accessing the container's filesystem:
# Reading a container's file from the host:
cat /proc/1234/root/etc/os-release # Shows container's OS, not host's!
However, std::fs::canonicalize resolves this magic symlink to /, breaking security boundaries. This crate preserves the /proc/PID/root, /proc/PID/cwd, and /proc/PID/task/TID/root prefixes:
use std::path::Path;
// BROKEN: std::fs::canonicalize loses the namespace prefix!
let std_resolved = std::fs::canonicalize("/proc/self/root/etc")?;
assert_eq!(std_resolved, Path::new("/etc")); // Resolves to host's /etc!
// FIXED: Namespace prefix is preserved!
let resolved = proc_canonicalize::canonicalize("/proc/self/root/etc")?;
assert_eq!(resolved, Path::new("/proc/self/root/etc"));
Container monitoring and security tools that need to:
/proc/PID/rootuse proc_canonicalize::canonicalize;
fn read_container_file(container_pid: u32, path: &str) -> std::io::Result<Vec<u8>> {
let container_root = format!("/proc/{container_pid}/root");
let full_path = format!("{container_root}/{path}");
let canonical = canonicalize(&full_path)?;
// Security: canonical path must stay inside container_root
assert!(canonical.starts_with(&container_root));
std::fs::read(&canonical)
}
| Path Pattern | Preserved |
|---|---|
/proc/PID/root |
✅ |
/proc/PID/root/... |
✅ |
/proc/PID/cwd |
✅ |
/proc/PID/cwd/... |
✅ |
/proc/self/root |
✅ |
/proc/self/cwd |
✅ |
/proc/thread-self/root |
✅ |
/proc/thread-self/cwd |
✅ |
| All other paths | Same as std::fs::canonicalize |
std::fs::canonicalize (no-op)dunce (Windows Only)Simplifies Windows extended-length paths by removing the \\?\ prefix when possible:
[dependencies]
proc-canonicalize = { version = "0.1.2", features = ["dunce"] }
Behavior:
dunce: Returns \\?\C:\Users\Alice\file.txt (Windows extended-length format)dunce: Returns C:\Users\Alice\file.txt (simplified format)Benefits:
\\?\ prefix when needed (e.g., for paths longer than 260 characters)This crate has no dependencies beyond the Rust standard library.
[dependencies]
proc-canonicalize = "0.1.2"
MIT OR Apache-2.0