-
Notifications
You must be signed in to change notification settings - Fork 825
/
probestack.rs
64 lines (62 loc) · 2.93 KB
/
probestack.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// This file contains code from external sources.
// Attributions: https://github.com/wasmerio/wasmer/blob/main/docs/ATTRIBUTIONS.md
//! This section defines the `PROBESTACK` intrinsic which is used in the
//! implementation of "stack probes" on certain platforms.
//!
//! The purpose of a stack probe is to provide a static guarantee that if a
//! thread has a guard page then a stack overflow is guaranteed to hit that
//! guard page. If a function did not have a stack probe then there's a risk of
//! having a stack frame *larger* than the guard page, so a function call could
//! skip over the guard page entirely and then later hit maybe the heap or
//! another thread, possibly leading to security vulnerabilities such as [The
//! Stack Clash], for example.
//!
//! [The Stack Clash]: https://blog.qualys.com/securitylabs/2017/06/19/the-stack-clash
// A declaration for the stack probe function in Rust's standard library, for
// catching callstack overflow.
cfg_if::cfg_if! {
if #[cfg(all(
target_os = "windows",
target_env = "msvc",
target_pointer_width = "64"
))] {
extern "C" {
pub fn __chkstk();
}
/// The probestack for 64bit Windows when compiled with MSVC (note the double underscore)
pub const PROBESTACK: unsafe extern "C" fn() = __chkstk;
} else if #[cfg(all(
target_os = "windows",
target_env = "msvc",
target_pointer_width = "32"
))] {
extern "C" {
pub fn _chkstk();
}
/// The probestack for 32bit Windows when compiled with MSVC (note the singular underscore)
pub const PROBESTACK: unsafe extern "C" fn() = _chkstk;
} else if #[cfg(all(target_os = "windows", target_env = "gnu"))] {
extern "C" {
// ___chkstk (note the triple underscore) is implemented in compiler-builtins/src/x86_64.rs
// by the Rust compiler for the MinGW target
#[cfg(all(target_os = "windows", target_env = "gnu"))]
pub fn ___chkstk_ms();
}
/// The probestack for Windows when compiled with GNU
pub const PROBESTACK: unsafe extern "C" fn() = ___chkstk_ms;
} else if #[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))] {
// As per
// https://github.com/rust-lang/compiler-builtins/blob/cae3e6ea23739166504f9f9fb50ec070097979d4/src/probestack.rs#L39,
// LLVM only has stack-probe support on x86-64 and x86. Thus, on any other CPU
// architecture, we simply use an empty stack-probe function.
extern "C" fn empty_probestack() {}
/// A default probestack for other architectures
pub const PROBESTACK: unsafe extern "C" fn() = empty_probestack;
} else {
extern "C" {
pub fn __rust_probestack();
}
/// The probestack based on the Rust probestack
pub static PROBESTACK: unsafe extern "C" fn() = __rust_probestack;
}
}