bytecodealliance / bytecodealliance/rustix

Miri reports UB on MacOS when using fstat

Aperta
#1,668 5 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Rust
Stelle
2.1k
Fork
294
Merge medio
6g 22h
PR unite (30g)
4

Descrizione

Reproduction, testing via [`tempfile`](https://crates.io/crates/tempfile) (`3.27.0`):

```rust
#[test]
fn test123() {
let a = tempfile::NamedTempFile::new().unwrap();
a.reopen().unwrap();
}
```

- For reference this is on macOS 26.5.2

Running test:

```sh
test123 (main)$ MIRIFLAGS="-Zmiri-disable-isolation" cargo +nightly miri test
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.00s
Running unittests src/main.rs (/Users/jeffrey/.cargo_target_cache/miri/aarch64-apple-darwin/debug/deps/test123-9a724f3234e25023)

running 1 test
test tests::test123 ... error: Undefined Behavior: constructing invalid value of type libc::unix::bsd::apple::stat: at .st_lspare, encountered uninitialized memory, but expected an integer
--> /Users/jeffrey/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustix-1.1.4/src/backend/libc/fs/syscalls.rs:1570:20
|
1570 | let stat = stat.assume_init();
| ^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: this is on thread `tests::test123`
= note: stack backtrace:
0: rustix::backend::fs::syscalls::fstat
at /Users/jeffrey/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustix-1.1.4/src/backend/libc/fs/syscalls.rs:1570:20: 1570:38
1: rustix::fs::fd::fstat::<&std::fs::File>
at /Users/jeffrey/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustix-1.1.4/src/fs/fd.rs:157:5: 157:45
2: tempfile::file::imp::platform::reopen
at /Users/jeffrey/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tempfile-3.27.0/src/file/imp/unix.rs:83:20: 83:43
3: tempfile::NamedTempFile::reopen
at /Users/jeffrey/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tempfile-3.27.0/src/file/mod.rs:952:9: 952:63
4: tests::test123
at src/main.rs:10:9: 10:19
5: tests::test123::{closure#0}
at src/main.rs:8:17: 8:17

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error

error: test failed, to rerun pass `--bin test123`

Caused by:
process didn't exit successfully: `/Users/jeffrey/.rustup/toolchains/nightly-aarch64-apple-darwin/bin/cargo-miri runner /Users/jeffrey/.cargo_target_cache/miri/aarch64-apple-darwin/debug/deps/test123-9a724f3234e25023` (exit status: 1)
note: test exited abnormally; to see the full output pass --no-capture to the harness.
```

It seems at this stat call:

https://github.com/bytecodealliance/rustix/blob/9640071aef0dfd65d21bf01c1dd1baa0a1b13310/src/backend/libc/fs/syscalls.rs#L1568-L1570

In the Miri shim they don't initialize fields `st_lspare` and `st_qspare`:

- https://github.com/rust-lang/miri/blob/2b466864cf2e0c6301854461b857b6ece8be7349/src/shims/unix/fs.rs#L261-L319
- https://github.com/rust-lang/miri/blob/2b466864cf2e0c6301854461b857b6ece8be7349/tests/pass-dep/libc/libc-fstat-non-file.rs#L19-L26
- This test suggests its intentional

As the man page states they are reserved:

```
struct stat { /* when _DARWIN_FEATURE_64_BIT_INODE is defined */
dev_t st_dev; /* ID of device containing file */
mode_t st_mode; /* Mode of file (see below) */
nlink_t st_nlink; /* Number of hard links */
ino_t st_ino; /* File serial number */
uid_t st_uid; /* User ID of the file */
gid_t st_gid; /* Group ID of the file */
dev_t st_rdev; /* Device ID */
struct timespec st_atimespec; /* time of last access */
struct timespec st_mtimespec; /* time of last data modification */
struct timespec st_ctimespec; /* time of last status change */
struct timespec st_birthtimespec; /* time of file creation(birth) */
off_t st_size; /* file size, in bytes */
blkcnt_t st_blocks; /* blocks allocated for file */
blksize_t st_blksize; /* optimal blocksize for I/O */
uint32_t st_flags; /* user defined flags for file */
uint32_t st_gen; /* file generation number */
int32_t st_lspare; /* RESERVED: DO NOT USE! */
int64_t st_qspare[2]; /* RESERVED: DO NOT USE! */
};
```

- https://man.freebsd.org/cgi/man.cgi?query=fstat&sektion=2&manpath=macOS+13.6.5
- https://docs.rs/libc/latest/aarch64-apple-darwin/libc/struct.stat.html

But above code assumes the struct (and all fields) are initialized

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Riprodurre il fallimento di macOS Miri con l’esempio tempfile, quindi esaminare src/backend/libc/fs/syscalls.rs intorno alla riga 1570 e confrontarlo con il Unix filesystem shim di Miri e libc-fstat-non-file.rs. Determinare se i campi riservati non validi richiedono una modifica a rustix o Miri e verificare la correzione scelta con la riproduzione e la copertura fstat pertinente.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
rust
Ambito
operating-systems
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Attiva
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.