Rollup merge of #127843 - workingjubilee:break-up-big-ass-stack-overf… · patricklam/verify-rust-std@bd26295 (original) (raw)
`@@ -87,13 +87,18 @@ mod imp {
`
87
87
`// out many large systems and all implementations allow returning from a
`
88
88
`// signal handler to work. For a more detailed explanation see the
`
89
89
`// comments on #26458.
`
``
90
`+
/// SIGSEGV/SIGBUS entry point
`
``
91
`+
/// # Safety
`
``
92
`+
/// Rust doesn't call this, it gets called.
`
``
93
`+
#[forbid(unsafe_op_in_unsafe_fn)]
`
90
94
`unsafe extern "C" fn signal_handler(
`
91
95
`signum: libc::c_int,
`
92
96
`info: *mut libc::siginfo_t,
`
93
97
`_data: *mut libc::c_void,
`
94
98
`) {
`
95
99
`let (start, end) = GUARD.get();
`
96
``
`-
let addr = (*info).si_addr() as usize;
`
``
100
`` +
// SAFETY: this pointer is provided by the system and will always point to a valid siginfo_t
.
``
``
101
`+
let addr = unsafe { (*info).si_addr().addr() };
`
97
102
``
98
103
`// If the faulting address is within the guard page, then we print a
`
99
104
`// message saying so and abort.
`
`@@ -105,9 +110,11 @@ mod imp {
`
105
110
`rtabort!("stack overflow");
`
106
111
`} else {
`
107
112
`// Unregister ourselves by reverting back to the default behavior.
`
108
``
`-
let mut action: sigaction = mem::zeroed();
`
``
113
`+
// SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
`
``
114
`+
let mut action: sigaction = unsafe { mem::zeroed() };
`
109
115
` action.sa_sigaction = SIG_DFL;
`
110
``
`-
sigaction(signum, &action, ptr::null_mut());
`
``
116
`+
// SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction
`
``
117
`+
unsafe { sigaction(signum, &action, ptr::null_mut()) };
`
111
118
``
112
119
`// See comment above for why this function returns.
`
113
120
`}
`
`@@ -117,32 +124,45 @@ mod imp {
`
117
124
`static MAIN_ALTSTACK: AtomicPtrlibc::c_void = AtomicPtr::new(ptr::null_mut());
`
118
125
`static NEED_ALTSTACK: AtomicBool = AtomicBool::new(false);
`
119
126
``
``
127
`+
/// # Safety
`
``
128
`+
/// Must be called only once
`
``
129
`+
#[forbid(unsafe_op_in_unsafe_fn)]
`
120
130
`pub unsafe fn init() {
`
121
131
`PAGE_SIZE.store(os::page_size(), Ordering::Relaxed);
`
122
132
``
123
133
`// Always write to GUARD to ensure the TLS variable is allocated.
`
124
``
`-
let guard = install_main_guard().unwrap_or(0..0);
`
``
134
`+
let guard = unsafe { install_main_guard().unwrap_or(0..0) };
`
125
135
`GUARD.set((guard.start, guard.end));
`
126
136
``
127
``
`-
let mut action: sigaction = mem::zeroed();
`
``
137
`+
// SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
`
``
138
`+
let mut action: sigaction = unsafe { mem::zeroed() };
`
128
139
`for &signal in &[SIGSEGV, SIGBUS] {
`
129
``
`-
sigaction(signal, ptr::null_mut(), &mut action);
`
``
140
`+
// SAFETY: just fetches the current signal handler into action
`
``
141
`+
unsafe { sigaction(signal, ptr::null_mut(), &mut action) };
`
130
142
`// Configure our signal handler if one is not already set.
`
131
143
`if action.sa_sigaction == SIG_DFL {
`
``
144
`+
if !NEED_ALTSTACK.load(Ordering::Relaxed) {
`
``
145
`+
// haven't set up our sigaltstack yet
`
``
146
`+
NEED_ALTSTACK.store(true, Ordering::Release);
`
``
147
`+
let handler = unsafe { make_handler(true) };
`
``
148
`+
MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed);
`
``
149
`+
mem::forget(handler);
`
``
150
`+
}
`
132
151
` action.sa_flags = SA_SIGINFO | SA_ONSTACK;
`
133
152
` action.sa_sigaction = signal_handler as sighandler_t;
`
134
``
`-
sigaction(signal, &action, ptr::null_mut());
`
135
``
`-
NEED_ALTSTACK.store(true, Ordering::Relaxed);
`
``
153
`+
// SAFETY: only overriding signals if the default is set
`
``
154
`+
unsafe { sigaction(signal, &action, ptr::null_mut()) };
`
136
155
`}
`
137
156
`}
`
138
``
-
139
``
`-
let handler = make_handler(true);
`
140
``
`-
MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed);
`
141
``
`-
mem::forget(handler);
`
142
157
`}
`
143
158
``
``
159
`+
/// # Safety
`
``
160
`+
/// Must be called only once
`
``
161
`+
#[forbid(unsafe_op_in_unsafe_fn)]
`
144
162
`pub unsafe fn cleanup() {
`
145
``
`-
drop_handler(MAIN_ALTSTACK.load(Ordering::Relaxed));
`
``
163
`+
// FIXME: I probably cause more bugs than I'm worth!
`
``
164
`+
// see https://github.com/rust-lang/rust/issues/111272
`
``
165
`+
unsafe { drop_handler(MAIN_ALTSTACK.load(Ordering::Relaxed)) };
`
146
166
`}
`
147
167
``
148
168
`unsafe fn get_stack() -> libc::stack_t {
`
`@@ -187,34 +207,48 @@ mod imp {
`
187
207
` libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size }
`
188
208
`}
`
189
209
``
``
210
`+
/// # Safety
`
``
211
`+
/// Mutates the alternate signal stack
`
``
212
`+
#[forbid(unsafe_op_in_unsafe_fn)]
`
190
213
`pub unsafe fn make_handler(main_thread: bool) -> Handler {
`
191
``
`-
if !NEED_ALTSTACK.load(Ordering::Relaxed) {
`
``
214
`+
if !NEED_ALTSTACK.load(Ordering::Acquire) {
`
192
215
`return Handler::null();
`
193
216
`}
`
194
217
``
195
218
`if !main_thread {
`
196
219
`// Always write to GUARD to ensure the TLS variable is allocated.
`
197
``
`-
let guard = current_guard().unwrap_or(0..0);
`
``
220
`+
let guard = unsafe { current_guard() }.unwrap_or(0..0);
`
198
221
`GUARD.set((guard.start, guard.end));
`
199
222
`}
`
200
223
``
201
``
`-
let mut stack = mem::zeroed();
`
202
``
`-
sigaltstack(ptr::null(), &mut stack);
`
``
224
`+
// SAFETY: assuming stack_t is zero-initializable
`
``
225
`+
let mut stack = unsafe { mem::zeroed() };
`
``
226
`+
// SAFETY: reads current stack_t into stack
`
``
227
`+
unsafe { sigaltstack(ptr::null(), &mut stack) };
`
203
228
`// Configure alternate signal stack, if one is not already set.
`
204
229
`if stack.ss_flags & SS_DISABLE != 0 {
`
205
``
`-
stack = get_stack();
`
206
``
`-
sigaltstack(&stack, ptr::null_mut());
`
``
230
`+
// SAFETY: We warned our caller this would happen!
`
``
231
`+
unsafe {
`
``
232
`+
stack = get_stack();
`
``
233
`+
sigaltstack(&stack, ptr::null_mut());
`
``
234
`+
}
`
207
235
`Handler { data: stack.ss_sp as *mut libc::c_void }
`
208
236
`} else {
`
209
237
`Handler::null()
`
210
238
`}
`
211
239
`}
`
212
240
``
``
241
`+
/// # Safety
`
``
242
`+
/// Must be called
`
``
243
`+
/// - only with our handler or nullptr
`
``
244
`+
/// - only when done with our altstack
`
``
245
`+
/// This disables the alternate signal stack!
`
``
246
`+
#[forbid(unsafe_op_in_unsafe_fn)]
`
213
247
`pub unsafe fn drop_handler(data: *mut libc::c_void) {
`
214
248
`if !data.is_null() {
`
215
249
`let sigstack_size = sigstack_size();
`
216
250
`let page_size = PAGE_SIZE.load(Ordering::Relaxed);
`
217
``
`-
let stack = libc::stack_t {
`
``
251
`+
let disabling_stack = libc::stack_t {
`
218
252
`ss_sp: ptr::null_mut(),
`
219
253
`ss_flags: SS_DISABLE,
`
220
254
`// Workaround for bug in macOS implementation of sigaltstack
`
`@@ -223,10 +257,11 @@ mod imp {
`
223
257
`// both ss_sp and ss_size should be ignored in this case.
`
224
258
`ss_size: sigstack_size,
`
225
259
`};
`
226
``
`-
sigaltstack(&stack, ptr::null_mut());
`
227
``
`` -
// We know from get_stackp
that the alternate stack we installed is part of a mapping
``
228
``
`-
// that started one page earlier, so walk back a page and unmap from there.
`
229
``
`-
munmap(data.sub(page_size), sigstack_size + page_size);
`
``
260
`+
// SAFETY: we warned the caller this disables the alternate signal stack!
`
``
261
`+
unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) };
`
``
262
`` +
// SAFETY: We know from get_stackp
that the alternate stack we installed is part of
``
``
263
`+
// a mapping that started one page earlier, so walk back a page and unmap from there.
`
``
264
`+
unsafe { munmap(data.sub(page_size), sigstack_size + page_size) };
`
230
265
`}
`
231
266
`}
`
232
267
``
`@@ -455,6 +490,7 @@ mod imp {
`
455
490
`}
`
456
491
``
457
492
`#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
`
``
493
`+
// FIXME: I am probably not unsafe.
`
458
494
`unsafe fn current_guard() -> Option<Range> {
`
459
495
`let stackptr = get_stack_start()?;
`
460
496
`let stackaddr = stackptr.addr();
`
`@@ -469,6 +505,7 @@ mod imp {
`
469
505
` target_os = "netbsd",
`
470
506
` target_os = "l4re"
`
471
507
`))]
`
``
508
`+
// FIXME: I am probably not unsafe.
`
472
509
`unsafe fn current_guard() -> Option<Range> {
`
473
510
`let mut ret = None;
`
474
511
`let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
`