diff options
| author | Ralf Jung <post@ralfj.de> | 2025-08-30 14:29:17 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2025-08-30 14:50:43 +0200 |
| commit | f2ff4c2598609992d476e3d937233534fd137571 (patch) | |
| tree | 3837ad2cc5cc5523c957e0a1d105275f14aea3fa /src | |
| parent | 4beb15f2708781cf9b1f79c251da9c337d8cc9de (diff) | |
| download | rust-f2ff4c2598609992d476e3d937233534fd137571.tar.gz rust-f2ff4c2598609992d476e3d937233534fd137571.zip | |
native-lib mode: avoid unsoundness due to mrpotect
Diffstat (limited to 'src')
| -rw-r--r-- | src/tools/miri/src/shims/native_lib/trace/child.rs | 30 |
1 files changed, 13 insertions, 17 deletions
diff --git a/src/tools/miri/src/shims/native_lib/trace/child.rs b/src/tools/miri/src/shims/native_lib/trace/child.rs index b998ba822dd..95b0617a026 100644 --- a/src/tools/miri/src/shims/native_lib/trace/child.rs +++ b/src/tools/miri/src/shims/native_lib/trace/child.rs @@ -90,14 +90,6 @@ impl Supervisor { // Unwinding might be messed up due to partly protected memory, so let's abort if something // breaks inside here. let res = std::panic::abort_unwind(|| { - // SAFETY: We do not access machine memory past this point until the - // supervisor is ready to allow it. - // FIXME: this is sketchy, as technically the memory is still in the Rust Abstract Machine, - // and the compiler would be allowed to reorder accesses below this block... - unsafe { - Self::protect_pages(alloc.pages(), mman::ProtFlags::PROT_NONE).unwrap(); - } - // Send over the info. // NB: if we do not wait to receive a blank confirmation response, it is // possible that the supervisor is alerted of the SIGSTOP *before* it has @@ -110,16 +102,14 @@ impl Supervisor { // count. signal::raise(signal::SIGSTOP).unwrap(); - let res = f(); + // SAFETY: We have coordinated with the supervisor to ensure that this memory will keep + // working as normal, just with extra tracing. So even if the compiler moves memory + // accesses down to after the `mprotect`, they won't actually segfault. + unsafe { + Self::protect_pages(alloc.pages(), mman::ProtFlags::PROT_NONE).unwrap(); + } - // We can't use IPC channels here to signal that FFI mode has ended, - // since they might allocate memory which could get us stuck in a SIGTRAP - // with no easy way out! While this could be worked around, it is much - // simpler and more robust to simply use the signals which are left for - // arbitrary usage. Since this will block until we are continued by the - // supervisor, we can assume past this point that everything is back to - // normal. - signal::raise(signal::SIGUSR1).unwrap(); + let res = f(); // SAFETY: We set memory back to normal, so this is safe. unsafe { @@ -130,6 +120,12 @@ impl Supervisor { .unwrap(); } + // Signal the supervisor that we are done. Will block until the supervisor continues us. + // This will also shut down the segfault handler, so it's important that all memory is + // reset back to normal above. There must not be a window in time where accessing the + // pages we protected above actually causes the program to abort. + signal::raise(signal::SIGUSR1).unwrap(); + res }); |
