miri
miri copied to clipboard
Miri should warn or error when accessing file at `/proc/self/fd/X`
If your program attempts to open and read from a file in /proc/self/fd/, then cargo miri run (with isolation disabled) hangs.
use std::os::fd::AsRawFd;
use std::fs::File;
use std::io::{Read, Seek, Write};
fn main() {
let mut file = tempfile::tempfile().unwrap();
file.write_all(b"hello").unwrap();
file.rewind().unwrap();
// opening and reading from /proc cause miri to become stuck
let mut new_file = File::open(format!("/proc/self/fd/{}", file.as_raw_fd())).unwrap();
//let mut new_file = file;
let mut buf = Vec::new();
new_file.read_to_end(&mut buf).unwrap();
println!("{buf:?}");
}
$ cargo --version
cargo 1.85.0-nightly (769f622e1 2024-12-14)
$ MIRIFLAGS=-Zmiri-disable-isolation cargo miri run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
Running `/home/steve/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/miri-test`
This is also reproducible at: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=d05155bb1f3c7aff5e705b0e2904d21c
I'm guessing that miri virtualizes filesystem operations in some way, and maybe files in /proc just aren't supported?
Miri virtualizes file descriptors, so the FD number you see may have nothing to do with the FD numbers in /proc.
So I am inclined to close this as not-a-bug; we don't support bypassing Miri and directly accessing the underlying OS. You will run into similar issues trying to access /proc/self/mem. Maybe we should print a warning or even halt execution when we detect a path in /proc, but that would just be a best-effort check.
Is there a general guideline about what Linux features Miri emulates (or wants to emulate) and which ones it doesn't? For example Miri is emulating Linux file descriptor handles (and I'm guessing some syscalls), but is not emulating /proc.
I think it sounds fine to not support /proc, but it would be nice if a warning was shown when possible. Running tests in miri can already take ~20 minutes for some projects, and having a correct test which can block indefinitely under miri can be a bit difficult to debug.
On the other hand, I believe that some glibc functions read from files in /proc, so it might be noisy showing warnings for all file accesses in /proc. Maybe the filter could be a bit more specific than just /proc.
On the other hand, I believe that some glibc functions read from files in /proc, so it might be noisy showing warnings for all file accesses in /proc. Maybe the filter could be a bit more specific than just /proc.
Miri doesn't run glibc. Instead it emulates the api surface exposed by glibc, so any accesses to /proc that glibc would do are irrelevant.
Is there a general guideline about what Linux features Miri emulates (or wants to emulate) and which ones it doesn't?
Generally we throw an error when you hit something we can't emulate. But we didn't consider the interactions with /proc...
That should be fairly easy to do: in the code for open, check for some bad paths. It won't catch everything but we can catch the obvious ones.
Actually should reading from symlink works in miri? I realised most of the stuff in proc/self/fd seems to be symlink.
If it doesn't, maybe we can throw an error when it tries to read from symlink.
I slightly looked into this, this seems to be the place where miri hangs: https://github.com/rust-lang/miri/blob/b9a24fc85858c662c2aeea67655464bce386d1f7/src/shims/unix/fs.rs#L33-L49
and self.file happens to be a symlink, that's why I have the question above.
Symlinks are fine. It will just read through them transparently.
EDIT:
oh this should be a symlink, is_symlink seems to be always false when retrieving from File::metadata. But since symlinks are fine, this is not relevant now.