Skip to content

Commit f2ff4c2

Browse files
committed
native-lib mode: avoid unsoundness due to mrpotect
1 parent 4beb15f commit f2ff4c2

File tree

1 file changed

+13
-17
lines changed
  • src/tools/miri/src/shims/native_lib/trace

1 file changed

+13
-17
lines changed

src/tools/miri/src/shims/native_lib/trace/child.rs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,6 @@ impl Supervisor {
9090
// Unwinding might be messed up due to partly protected memory, so let's abort if something
9191
// breaks inside here.
9292
let res = std::panic::abort_unwind(|| {
93-
// SAFETY: We do not access machine memory past this point until the
94-
// supervisor is ready to allow it.
95-
// FIXME: this is sketchy, as technically the memory is still in the Rust Abstract Machine,
96-
// and the compiler would be allowed to reorder accesses below this block...
97-
unsafe {
98-
Self::protect_pages(alloc.pages(), mman::ProtFlags::PROT_NONE).unwrap();
99-
}
100-
10193
// Send over the info.
10294
// NB: if we do not wait to receive a blank confirmation response, it is
10395
// possible that the supervisor is alerted of the SIGSTOP *before* it has
@@ -110,16 +102,14 @@ impl Supervisor {
110102
// count.
111103
signal::raise(signal::SIGSTOP).unwrap();
112104

113-
let res = f();
105+
// SAFETY: We have coordinated with the supervisor to ensure that this memory will keep
106+
// working as normal, just with extra tracing. So even if the compiler moves memory
107+
// accesses down to after the `mprotect`, they won't actually segfault.
108+
unsafe {
109+
Self::protect_pages(alloc.pages(), mman::ProtFlags::PROT_NONE).unwrap();
110+
}
114111

115-
// We can't use IPC channels here to signal that FFI mode has ended,
116-
// since they might allocate memory which could get us stuck in a SIGTRAP
117-
// with no easy way out! While this could be worked around, it is much
118-
// simpler and more robust to simply use the signals which are left for
119-
// arbitrary usage. Since this will block until we are continued by the
120-
// supervisor, we can assume past this point that everything is back to
121-
// normal.
122-
signal::raise(signal::SIGUSR1).unwrap();
112+
let res = f();
123113

124114
// SAFETY: We set memory back to normal, so this is safe.
125115
unsafe {
@@ -130,6 +120,12 @@ impl Supervisor {
130120
.unwrap();
131121
}
132122

123+
// Signal the supervisor that we are done. Will block until the supervisor continues us.
124+
// This will also shut down the segfault handler, so it's important that all memory is
125+
// reset back to normal above. There must not be a window in time where accessing the
126+
// pages we protected above actually causes the program to abort.
127+
signal::raise(signal::SIGUSR1).unwrap();
128+
133129
res
134130
});
135131

0 commit comments

Comments
 (0)