@@ -90,14 +90,6 @@ impl Supervisor {
90
90
// Unwinding might be messed up due to partly protected memory, so let's abort if something
91
91
// breaks inside here.
92
92
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
-
101
93
// Send over the info.
102
94
// NB: if we do not wait to receive a blank confirmation response, it is
103
95
// possible that the supervisor is alerted of the SIGSTOP *before* it has
@@ -110,16 +102,14 @@ impl Supervisor {
110
102
// count.
111
103
signal:: raise ( signal:: SIGSTOP ) . unwrap ( ) ;
112
104
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
+ }
114
111
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 ( ) ;
123
113
124
114
// SAFETY: We set memory back to normal, so this is safe.
125
115
unsafe {
@@ -130,6 +120,12 @@ impl Supervisor {
130
120
. unwrap ( ) ;
131
121
}
132
122
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
+
133
129
res
134
130
} ) ;
135
131
0 commit comments