Intercept fstatfs and synthesize procfs magic for all /proc files#207
Intercept fstatfs and synthesize procfs magic for all /proc files#207doanbaotrung wants to merge 1 commit into
Conversation
To fix fstatfs returning the incorrect magic on open descriptors of procfs magic links and symlinks, exclude paths like /proc/self/exe, /proc/self/cwd, /proc/self/root, /proc/self/fd/N, and task-specific equivalents from resolving to a virtual proc_path stamp. This prevents the guest fd table from recording these entries as part of the emulated procfs, letting fstatfs correctly query the filesystem information of their resolved host file targets. Fix sysprog21#142
| * then fall back to the same intercept open/fstatfs/close that | ||
| * sys_newfstatat uses via proc_intercept_stat. | ||
| */ | ||
| if (statfs_path_is_proc(tx.intercept_path)) { |
There was a problem hiding this comment.
statfs on a nonexistent /proc path now returns success instead of ENOENT. statfs_path_is_proc() matches any /proc-prefixed path, so this block fills PROC_SUPER_MAGIC and returns 0 without confirming the entry exists. The previous code fell through proc_intercept_statfs -> proc_intercept_open -> statfs(host_path), so a miss propagated ENOENT.
Trigger: statfs("/proc/bogus", &buf) or statfs("/proc/self/not_a_file", &buf) -- real Linux and pre-PR return -ENOENT; this returns 0 with f_type=0x9fa0. Programs that use statfs as an existence/feature probe are misled.
Fix: gate synthesis on a positive existence check (only synthesize when proc_intercept_stat(tx.intercept_path, ...) recognizes the path, otherwise fall through to the host statfs that yields ENOENT). Only f_type needed to change; existence semantics should be preserved.
| return true; | ||
| } | ||
|
|
||
| /* If it has a valid /proc prefix, normalize it and record it. */ |
There was a problem hiding this comment.
Stamping proc_path for every non-symlink /proc/* entry -- including regular files like /proc/cpuinfo and /proc/self/maps -- leaks dirfd semantics into consumers that key off proc_path. dirfd_guest_base_path (path.c:883) accepts any fd with a non-empty proc_path as a resolution base and returns before the snap.type != FD_DIR -> ENOTDIR guard at path.c:909 -- unlike resolve_proc_dirfd_path (path.c:522), which requires FD_DIR.
Trigger: open /proc/cpuinfo as fd 5, then openat(5, "x", ...). Real Linux returns ENOTDIR; this builds /proc/cpuinfo/x and resolves it (wrong errno / wrong target). It also reroutes plain fstat on such fds through proc_intercept_stat.
Fix: only stamp proc_path for /proc entries that are directories (the cases where the fd is a legitimate dirfd), or record a separate proc-mount flag used solely by the statfs path rather than overloading proc_path, which carries dirfd-resolution meaning.
| return !strncmp(path, "/proc", 5) && (path[5] == '\0' || path[5] == '/'); | ||
| } | ||
|
|
||
| static void fill_proc_statfs(linux_statfs_t *lin) |
There was a problem hiding this comment.
The linux_statfs_t layout here is complete and correct (all fields covered by memset(0); f_type/f_bsize/f_namelen/f_frsize consistent with a real procfs). No regression test asserts the magic, though -- the existing tests only compare statfs vs fstatfs, not the value 0x9fa0. Worth adding one assertion for f_type == 0x9fa0 on both statfs("/proc/...") and fstatfs(open("/proc/...")).
When fstatfs is called on open file descriptors pointing to /proc files (e.g., /proc/self/maps, /proc/uptime, /proc/loadavg), it returned the host filesystem magic (e.g. APFS) instead of LINUX_PROC_SUPER_MAGIC (0x9fa0).
Fix this by:
Fix #142
Summary by cubic
Return the correct procfs magic for
/procfiles by interceptingstatfs/fstatfsand normalizing/procpaths, while skipping procfs symlinks so only real proc entries report procfs. Fixes #142./procpaths inresolve_virtual_path, mapping/proc/<pid>(for the current pid) to/proc/self, and exclude procfs symlinks (/proc/self/{exe,cwd,root},/proc/self/fd/<n>, and task equivalents) so they report the target filesystem.fill_proc_statfsto synthesize alinux_statfs_twithPROC_SUPER_MAGIC(0x9fa0), 4K block size, and zeroed counts.sys_statfsandsys_fstatfsfor/proctargets and return the synthesized procfs stats.Written for commit 92599f3. Summary will update on new commits.