]> git.proxmox.com Git - rustc.git/blame - src/doc/unstable-book/src/compiler-flags/sanitizer.md
New upstream version 1.68.2+dfsg1
[rustc.git] / src / doc / unstable-book / src / compiler-flags / sanitizer.md
CommitLineData
dfeec247
XL
1# `sanitizer`
2
3c0e092e
XL
3The tracking issues for this feature are:
4
5* [#39699](https://github.com/rust-lang/rust/issues/39699).
6* [#89653](https://github.com/rust-lang/rust/issues/89653).
dfeec247
XL
7
8------------------------
9
10This feature allows for use of one of following sanitizers:
11
f2b60f7d
FG
12* [AddressSanitizer](#addresssanitizer) a fast memory error detector.
13* [ControlFlowIntegrity](#controlflowintegrity) LLVM Control Flow Integrity (CFI) provides
3c0e092e 14 forward-edge control flow protection.
f2b60f7d 15* [HWAddressSanitizer](#hwaddresssanitizer) a memory error detector similar to
6a06907d 16 AddressSanitizer, but based on partial hardware assistance.
6522a427
EL
17* [KernelControlFlowIntegrity](#kernelcontrolflowintegrity) LLVM Kernel Control
18 Flow Integrity (KCFI) provides forward-edge control flow protection for
19 operating systems kernels.
f2b60f7d
FG
20* [LeakSanitizer](#leaksanitizer) a run-time memory leak detector.
21* [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads.
22* [MemTagSanitizer](#memtagsanitizer) fast memory error detector based on
5099ac24 23 Armv8.5-A Memory Tagging Extension.
f2b60f7d
FG
24* [ShadowCallStack](#shadowcallstack) provides backward-edge control flow protection.
25* [ThreadSanitizer](#threadsanitizer) a fast data race detector.
dfeec247 26
3c0e092e 27To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`,
5099ac24 28`-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`,
064997fb
FG
29`-Zsanitizer=memtag`, `-Zsanitizer=shadow-call-stack`, or `-Zsanitizer=thread`.
30You might also need the `--target` and `build-std` flags. Example:
923072b8
FG
31```shell
32$ RUSTFLAGS=-Zsanitizer=address cargo build -Zbuild-std --target x86_64-unknown-linux-gnu
33```
dfeec247 34
ba9703b0 35# AddressSanitizer
dfeec247 36
ba9703b0
XL
37AddressSanitizer is a memory error detector. It can detect the following types
38of bugs:
dfeec247 39
ba9703b0
XL
40* Out of bound accesses to heap, stack and globals
41* Use after free
42* Use after return (runtime flag `ASAN_OPTIONS=detect_stack_use_after_return=1`)
43* Use after scope
44* Double-free, invalid free
45* Memory leaks
46
3dfed10e
XL
47The memory leak detection is enabled by default on Linux, and can be enabled
48with runtime flag `ASAN_OPTIONS=detect_leaks=1` on macOS.
49
ba9703b0
XL
50AddressSanitizer is supported on the following targets:
51
5869c6ff 52* `aarch64-apple-darwin`
6522a427 53* `aarch64-unknown-fuchsia`
5869c6ff 54* `aarch64-unknown-linux-gnu`
ba9703b0 55* `x86_64-apple-darwin`
6522a427 56* `x86_64-unknown-fuchsia`
5869c6ff 57* `x86_64-unknown-freebsd`
ba9703b0
XL
58* `x86_64-unknown-linux-gnu`
59
60AddressSanitizer works with non-instrumented code although it will impede its
61ability to detect some bugs. It is not expected to produce false positive
62reports.
63
f2b60f7d
FG
64See the [Clang AddressSanitizer documentation][clang-asan] for more details.
65
ba9703b0 66## Examples
dfeec247
XL
67
68Stack buffer overflow:
69
ba9703b0 70```rust
dfeec247
XL
71fn main() {
72 let xs = [0, 1, 2, 3];
73 let _y = unsafe { *xs.as_ptr().offset(4) };
74}
ba9703b0
XL
75```
76
77```shell
78$ export RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address
79$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
80==37882==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe400e6250 at pc 0x5609a841fb20 bp 0x7ffe400e6210 sp 0x7ffe400e6208
81READ of size 4 at 0x7ffe400e6250 thread T0
82 #0 0x5609a841fb1f in example::main::h628ffc6626ed85b2 /.../src/main.rs:3:23
83 ...
84
85Address 0x7ffe400e6250 is located in stack of thread T0 at offset 48 in frame
86 #0 0x5609a841f8af in example::main::h628ffc6626ed85b2 /.../src/main.rs:1
dfeec247
XL
87
88 This frame has 1 object(s):
ba9703b0 89 [32, 48) 'xs' (line 2) <== Memory access at offset 48 overflows this variable
dfeec247
XL
90HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
91 (longjmp and C++ exceptions *are* supported)
ba9703b0 92SUMMARY: AddressSanitizer: stack-buffer-overflow /.../src/main.rs:3:23 in example::main::h628ffc6626ed85b2
dfeec247 93Shadow bytes around the buggy address:
ba9703b0
XL
94 0x100048014bf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
95 0x100048014c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
96 0x100048014c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
97 0x100048014c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
98 0x100048014c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
99=>0x100048014c40: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
100 0x100048014c50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
101 0x100048014c60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
102 0x100048014c70: f1 f1 f1 f1 00 00 f3 f3 00 00 00 00 00 00 00 00
103 0x100048014c80: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
104 0x100048014c90: 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
dfeec247
XL
105Shadow byte legend (one shadow byte represents 8 application bytes):
106 Addressable: 00
ba9703b0 107 Partially addressable: 01 02 03 04 05 06 07
dfeec247
XL
108 Heap left redzone: fa
109 Freed heap region: fd
110 Stack left redzone: f1
111 Stack mid redzone: f2
112 Stack right redzone: f3
113 Stack after return: f5
114 Stack use after scope: f8
115 Global redzone: f9
116 Global init order: f6
117 Poisoned by user: f7
118 Container overflow: fc
119 Array cookie: ac
120 Intra object redzone: bb
121 ASan internal: fe
122 Left alloca redzone: ca
123 Right alloca redzone: cb
124 Shadow gap: cc
ba9703b0 125==37882==ABORTING
dfeec247
XL
126```
127
74b04a01
XL
128Use of a stack object after its scope has already ended:
129
ba9703b0 130```rust
74b04a01
XL
131static mut P: *mut usize = std::ptr::null_mut();
132
133fn main() {
134 unsafe {
135 {
136 let mut x = 0;
137 P = &mut x;
138 }
139 std::ptr::write_volatile(P, 123);
140 }
141}
ba9703b0
XL
142```
143
144```shell
145$ export RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address
146$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
74b04a01 147=================================================================
ba9703b0
XL
148==39249==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffc7ed3e1a0 at pc 0x55c98b262a8e bp 0x7ffc7ed3e050 sp 0x7ffc7ed3e048
149WRITE of size 8 at 0x7ffc7ed3e1a0 thread T0
150 #0 0x55c98b262a8d in core::ptr::write_volatile::he21f1df5a82f329a /.../src/rust/src/libcore/ptr/mod.rs:1048:5
151 #1 0x55c98b262cd2 in example::main::h628ffc6626ed85b2 /.../src/main.rs:9:9
152 ...
153
154Address 0x7ffc7ed3e1a0 is located in stack of thread T0 at offset 32 in frame
155 #0 0x55c98b262bdf in example::main::h628ffc6626ed85b2 /.../src/main.rs:3
74b04a01
XL
156
157 This frame has 1 object(s):
ba9703b0 158 [32, 40) 'x' (line 6) <== Memory access at offset 32 is inside this variable
74b04a01
XL
159HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
160 (longjmp and C++ exceptions *are* supported)
ba9703b0 161SUMMARY: AddressSanitizer: stack-use-after-scope /.../src/rust/src/libcore/ptr/mod.rs:1048:5 in core::ptr::write_volatile::he21f1df5a82f329a
74b04a01 162Shadow bytes around the buggy address:
ba9703b0
XL
163 0x10000fd9fbe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
164 0x10000fd9fbf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
165 0x10000fd9fc00: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
166 0x10000fd9fc10: f8 f8 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
167 0x10000fd9fc20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
168=>0x10000fd9fc30: f1 f1 f1 f1[f8]f3 f3 f3 00 00 00 00 00 00 00 00
169 0x10000fd9fc40: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
170 0x10000fd9fc50: 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
171 0x10000fd9fc60: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3
172 0x10000fd9fc70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
173 0x10000fd9fc80: 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3 00 00 00 00
74b04a01
XL
174Shadow byte legend (one shadow byte represents 8 application bytes):
175 Addressable: 00
176 Partially addressable: 01 02 03 04 05 06 07
177 Heap left redzone: fa
178 Freed heap region: fd
179 Stack left redzone: f1
180 Stack mid redzone: f2
181 Stack right redzone: f3
182 Stack after return: f5
183 Stack use after scope: f8
184 Global redzone: f9
185 Global init order: f6
186 Poisoned by user: f7
187 Container overflow: fc
188 Array cookie: ac
189 Intra object redzone: bb
190 ASan internal: fe
191 Left alloca redzone: ca
192 Right alloca redzone: cb
193 Shadow gap: cc
ba9703b0 194==39249==ABORTING
74b04a01
XL
195```
196
3c0e092e
XL
197# ControlFlowIntegrity
198
199The LLVM Control Flow Integrity (CFI) support in the Rust compiler initially
200provides forward-edge control flow protection for Rust-compiled code only by
064997fb
FG
201aggregating function pointers in groups identified by their return and parameter
202types.
3c0e092e
XL
203
204Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
205binaries" (i.e., for when C or C++ and Rust -compiled code share the same
206virtual address space) will be provided in later work by defining and using
207compatible type identifiers (see Type metadata in the design document in the
208tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
209
210LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto).
211
f2b60f7d
FG
212See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details.
213
3c0e092e
XL
214## Example
215
216```text
a2a8927a 217#![feature(naked_functions)]
3c0e092e 218
a2a8927a 219use std::arch::asm;
3c0e092e
XL
220use std::mem;
221
222fn add_one(x: i32) -> i32 {
223 x + 1
224}
225
226#[naked]
227pub extern "C" fn add_two(x: i32) {
5e7ed085 228 // x + 2 preceded by a landing pad/nop block
3c0e092e
XL
229 unsafe {
230 asm!(
231 "
232 nop
233 nop
234 nop
235 nop
236 nop
237 nop
238 nop
239 nop
240 nop
241 lea rax, [rdi+2]
242 ret
243 ",
244 options(noreturn)
245 );
246 }
247}
248
249fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
250 f(arg) + f(arg)
251}
252
253fn main() {
254 let answer = do_twice(add_one, 5);
255
064997fb 256 println!("The answer is: {}", answer);
3c0e092e
XL
257
258 println!("With CFI enabled, you should not see the next answer");
259 let f: fn(i32) -> i32 = unsafe {
260 // Offsets 0-8 make it land in the landing pad/nop block, and offsets 1-8 are
261 // invalid branch/call destinations (i.e., within the body of the function).
262 mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5))
263 };
264 let next_answer = do_twice(f, 5);
265
064997fb 266 println!("The next answer is: {}", next_answer);
3c0e092e
XL
267}
268```
269Fig. 1. Modified example from the [Advanced Functions and
270Closures][rust-book-ch19-05] chapter of the [The Rust Programming
271Language][rust-book] book.
272
3c0e092e 273```shell
064997fb
FG
274$ cargo run --release
275 Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
276 Finished release [optimized] target(s) in 0.76s
277 Running `target/release/rust-cfi-1`
3c0e092e
XL
278The answer is: 12
279With CFI enabled, you should not see the next answer
280The next answer is: 14
281$
282```
283Fig. 2. Build and execution of the modified example with LLVM CFI disabled.
284
3c0e092e 285```shell
064997fb
FG
286$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
287 Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
288 Finished release [optimized] target(s) in 3.39s
289 Running `target/release/rust-cfi-1`
3c0e092e
XL
290The answer is: 12
291With CFI enabled, you should not see the next answer
292Illegal instruction
293$
294```
295Fig. 3. Build and execution of the modified example with LLVM CFI enabled.
296
297When LLVM CFI is enabled, if there are any attempts to change/hijack control
298flow using an indirect branch/call to an invalid destination, the execution is
299terminated (see Fig. 3).
300
301```rust
302use std::mem;
303
304fn add_one(x: i32) -> i32 {
305 x + 1
306}
307
308fn add_two(x: i32, _y: i32) -> i32 {
309 x + 2
310}
311
312fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
313 f(arg) + f(arg)
314}
315
316fn main() {
317 let answer = do_twice(add_one, 5);
318
064997fb 319 println!("The answer is: {}", answer);
3c0e092e
XL
320
321 println!("With CFI enabled, you should not see the next answer");
322 let f: fn(i32) -> i32 =
323 unsafe { mem::transmute::<*const u8, fn(i32) -> i32>(add_two as *const u8) };
324 let next_answer = do_twice(f, 5);
325
064997fb 326 println!("The next answer is: {}", next_answer);
3c0e092e
XL
327}
328```
329Fig. 4. Another modified example from the [Advanced Functions and
330Closures][rust-book-ch19-05] chapter of the [The Rust Programming
331Language][rust-book] book.
332
3c0e092e 333```shell
064997fb
FG
334$ cargo run --release
335 Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
336 Finished release [optimized] target(s) in 0.76s
337 Running `target/release/rust-cfi-2`
3c0e092e
XL
338The answer is: 12
339With CFI enabled, you should not see the next answer
340The next answer is: 14
341$
342```
343Fig. 5. Build and execution of the modified example with LLVM CFI disabled.
344
3c0e092e 345```shell
064997fb
FG
346$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
347 Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
348 Finished release [optimized] target(s) in 3.38s
349 Running `target/release/rust-cfi-2`
3c0e092e
XL
350The answer is: 12
351With CFI enabled, you should not see the next answer
352Illegal instruction
353$
354```
355Fig. 6. Build and execution of the modified example with LLVM CFI enabled.
356
357When LLVM CFI is enabled, if there are any attempts to change/hijack control
358flow using an indirect branch/call to a function with different number of
064997fb
FG
359parameters than arguments intended/passed in the call/branch site, the
360execution is also terminated (see Fig. 6).
361
362```rust
363use std::mem;
364
365fn add_one(x: i32) -> i32 {
366 x + 1
367}
368
369fn add_two(x: i64) -> i64 {
370 x + 2
371}
372
373fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
374 f(arg) + f(arg)
375}
376
377fn main() {
378 let answer = do_twice(add_one, 5);
379
380 println!("The answer is: {}", answer);
381
382 println!("With CFI enabled, you should not see the next answer");
383 let f: fn(i32) -> i32 =
384 unsafe { mem::transmute::<*const u8, fn(i32) -> i32>(add_two as *const u8) };
385 let next_answer = do_twice(f, 5);
3c0e092e 386
064997fb
FG
387 println!("The next answer is: {}", next_answer);
388}
389```
390Fig. 7. Another modified example from the [Advanced Functions and
391Closures][rust-book-ch19-05] chapter of the [The Rust Programming
392Language][rust-book] book.
393
394```shell
395 cargo run --release
396 Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
397 Finished release [optimized] target(s) in 0.74s
398 Running `target/release/rust-cfi-3`
399The answer is: 12
400With CFI enabled, you should not see the next answer
401The next answer is: 14
402$
403```
404Fig. 8. Build and execution of the modified example with LLVM CFI disabled.
405
406```shell
407$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
408 Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
409 Finished release [optimized] target(s) in 3.40s
410 Running `target/release/rust-cfi-3`
411The answer is: 12
412With CFI enabled, you should not see the next answer
413Illegal instruction
414$
415```
416Fig. 9. Build and execution of the modified example with LLVM CFI enabled.
417
418When LLVM CFI is enabled, if there are any attempts to change/hijack control
419flow using an indirect branch/call to a function with different return and
420parameter types than the return type expected and arguments intended/passed in
421the call/branch site, the execution is also terminated (see Fig. 9).
3c0e092e 422
6522a427
EL
423[rust-book-ch19-05]: ../../book/ch19-05-advanced-functions-and-closures.html
424[rust-book]: ../../book/title-page.html
3c0e092e 425
6a06907d
XL
426# HWAddressSanitizer
427
428HWAddressSanitizer is a newer variant of AddressSanitizer that consumes much
429less memory.
430
431HWAddressSanitizer is supported on the following targets:
432
433* `aarch64-linux-android`
434* `aarch64-unknown-linux-gnu`
435
436HWAddressSanitizer requires `tagged-globals` target feature to instrument
437globals. To enable this target feature compile with `-C
438target-feature=+tagged-globals`
439
f2b60f7d
FG
440See the [Clang HWAddressSanitizer documentation][clang-hwasan] for more details.
441
6a06907d
XL
442## Example
443
444Heap buffer overflow:
445
446```rust
447fn main() {
448 let xs = vec![0, 1, 2, 3];
449 let _y = unsafe { *xs.as_ptr().offset(4) };
450}
451```
452
453```shell
454$ rustc main.rs -Zsanitizer=hwaddress -C target-feature=+tagged-globals -C
455linker=aarch64-linux-gnu-gcc -C link-arg=-fuse-ld=lld --target
456aarch64-unknown-linux-gnu
457```
458
459```shell
460$ ./main
461==241==ERROR: HWAddressSanitizer: tag-mismatch on address 0xefdeffff0050 at pc 0xaaaae0ae4a98
462READ of size 4 at 0xefdeffff0050 tags: 2c/00 (ptr/mem) in thread T0
463 #0 0xaaaae0ae4a94 (/.../main+0x54a94)
464 ...
465
466[0xefdeffff0040,0xefdeffff0060) is a small allocated heap chunk; size: 32 offset: 16
4670xefdeffff0050 is located 0 bytes to the right of 16-byte region [0xefdeffff0040,0xefdeffff0050)
468allocated here:
469 #0 0xaaaae0acb80c (/.../main+0x3b80c)
470 ...
471
472Thread: T0 0xeffe00002000 stack: [0xffffc28ad000,0xffffc30ad000) sz: 8388608 tls: [0xffffaa10a020,0xffffaa10a7d0)
473Memory tags around the buggy address (one tag corresponds to 16 bytes):
474 0xfefcefffef80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
475 0xfefcefffef90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
476 0xfefcefffefa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
477 0xfefcefffefb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
478 0xfefcefffefc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
479 0xfefcefffefd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
480 0xfefcefffefe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
481 0xfefcefffeff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
482=>0xfefceffff000: d7 d7 05 00 2c [00] 00 00 00 00 00 00 00 00 00 00
483 0xfefceffff010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
484 0xfefceffff020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
485 0xfefceffff030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
486 0xfefceffff040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
487 0xfefceffff050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
488 0xfefceffff060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
489 0xfefceffff070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
490 0xfefceffff080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
491Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
492 0xfefcefffeff0: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
493=>0xfefceffff000: .. .. 8c .. .. [..] .. .. .. .. .. .. .. .. .. ..
494 0xfefceffff010: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
495See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#short-granules for a description of short granule tags
496Registers where the failure occurred (pc 0xaaaae0ae4a98):
497 x0 2c00efdeffff0050 x1 0000000000000004 x2 0000000000000004 x3 0000000000000000
498 x4 0000fffefc30ac37 x5 000000000000005d x6 00000ffffc30ac37 x7 0000efff00000000
499 x8 2c00efdeffff0050 x9 0200efff00000000 x10 0000000000000000 x11 0200efff00000000
500 x12 0200effe00000310 x13 0200effe00000310 x14 0000000000000008 x15 5d00ffffc30ac360
501 x16 0000aaaae0ad062c x17 0000000000000003 x18 0000000000000001 x19 0000ffffc30ac658
502 x20 4e00ffffc30ac6e0 x21 0000aaaae0ac5e10 x22 0000000000000000 x23 0000000000000000
503 x24 0000000000000000 x25 0000000000000000 x26 0000000000000000 x27 0000000000000000
504 x28 0000000000000000 x29 0000ffffc30ac5a0 x30 0000aaaae0ae4a98
505SUMMARY: HWAddressSanitizer: tag-mismatch (/.../main+0x54a94)
506```
507
6522a427
EL
508# KernelControlFlowIntegrity
509
510The LLVM Kernel Control Flow Integrity (CFI) support to the Rust compiler
511initially provides forward-edge control flow protection for operating systems
512kernels for Rust-compiled code only by aggregating function pointers in groups
513identified by their return and parameter types. (See [LLVM commit cff5bef "KCFI
514sanitizer"](https://github.com/llvm/llvm-project/commit/cff5bef948c91e4919de8a5fb9765e0edc13f3de).)
515
516Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
517binaries" (i.e., for when C or C++ and Rust -compiled code share the same
518virtual address space) will be provided in later work by defining and using
519compatible type identifiers (see Type metadata in the design document in the
520tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
521
522LLVM KCFI can be enabled with `-Zsanitizer=kcfi`.
523
524LLVM KCFI is supported on the following targets:
525
526* `aarch64-linux-android`
527* `aarch64-unknown-linux-gnu`
528* `x86_64-linux-android`
529* `x86_64-unknown-linux-gnu`
530
531See the [Clang KernelControlFlowIntegrity documentation][clang-kcfi] for more
532details.
533
5869c6ff
XL
534# LeakSanitizer
535
536LeakSanitizer is run-time memory leak detector.
537
538LeakSanitizer is supported on the following targets:
539
540* `aarch64-apple-darwin`
541* `aarch64-unknown-linux-gnu`
542* `x86_64-apple-darwin`
543* `x86_64-unknown-linux-gnu`
544
f2b60f7d
FG
545See the [Clang LeakSanitizer documentation][clang-lsan] for more details.
546
ba9703b0
XL
547# MemorySanitizer
548
5869c6ff
XL
549MemorySanitizer is detector of uninitialized reads.
550
551MemorySanitizer is supported on the following targets:
552
553* `aarch64-unknown-linux-gnu`
554* `x86_64-unknown-freebsd`
555* `x86_64-unknown-linux-gnu`
ba9703b0
XL
556
557MemorySanitizer requires all program code to be instrumented. C/C++ dependencies
558need to be recompiled using Clang with `-fsanitize=memory` option. Failing to
559achieve that will result in false positive reports.
560
f2b60f7d
FG
561See the [Clang MemorySanitizer documentation][clang-msan] for more details.
562
ba9703b0 563## Example
dfeec247 564
ba9703b0
XL
565Detecting the use of uninitialized memory. The `-Zbuild-std` flag rebuilds and
566instruments the standard library, and is strictly necessary for the correct
6a06907d
XL
567operation of the tool. The `-Zsanitizer-memory-track-origins` enables tracking
568of the origins of uninitialized memory:
dfeec247 569
ba9703b0 570```rust
dfeec247
XL
571use std::mem::MaybeUninit;
572
573fn main() {
574 unsafe {
575 let a = MaybeUninit::<[usize; 4]>::uninit();
576 let a = a.assume_init();
577 println!("{}", a[2]);
578 }
579}
ba9703b0 580```
dfeec247 581
ba9703b0 582```shell
74b04a01 583$ export \
74b04a01
XL
584 RUSTFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins' \
585 RUSTDOCFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins'
586$ cargo clean
ba9703b0 587$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
dfeec247
XL
588==9416==WARNING: MemorySanitizer: use-of-uninitialized-value
589 #0 0x560c04f7488a in core::fmt::num::imp::fmt_u64::haa293b0b098501ca $RUST/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/src/libcore/fmt/num.rs:202:16
590...
591 Uninitialized value was stored to memory at
592 #0 0x560c04ae898a in __msan_memcpy.part.0 $RUST/src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cc:1558:3
593 #1 0x560c04b2bf88 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:6:16
594
595 Uninitialized value was created by an allocation of 'a' in the stack frame of function '_ZN6memory4main17hd2333c1899d997f5E'
596 #0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3
597```
598
5099ac24
FG
599# MemTagSanitizer
600
601MemTagSanitizer detects a similar class of errors as AddressSanitizer and HardwareAddressSanitizer, but with lower overhead suitable for use as hardening for production binaries.
602
603MemTagSanitizer is supported on the following targets:
604
605* `aarch64-linux-android`
606* `aarch64-unknown-linux-gnu`
607
608MemTagSanitizer requires hardware support and the `mte` target feature.
609To enable this target feature compile with `-C target-feature="+mte"`.
610
f2b60f7d 611See the [LLVM MemTagSanitizer documentation][llvm-memtag] for more details.
5099ac24 612
064997fb
FG
613# ShadowCallStack
614
615ShadowCallStack provides backward edge control flow protection by storing a function's return address in a separately allocated 'shadow call stack' and loading the return address from that shadow call stack.
616
617ShadowCallStack requires a platform ABI which reserves `x18` as the instrumentation makes use of this register.
618
619ShadowCallStack can be enabled with `-Zsanitizer=shadow-call-stack` option and is supported on the following targets:
620
621* `aarch64-linux-android`
622
f2b60f7d
FG
623A runtime must be provided by the application or operating system.
624
625See the [Clang ShadowCallStack documentation][clang-scs] for more details.
064997fb 626
ba9703b0
XL
627# ThreadSanitizer
628
629ThreadSanitizer is a data race detection tool. It is supported on the following
630targets:
631
5869c6ff
XL
632* `aarch64-apple-darwin`
633* `aarch64-unknown-linux-gnu`
ba9703b0 634* `x86_64-apple-darwin`
5869c6ff 635* `x86_64-unknown-freebsd`
ba9703b0
XL
636* `x86_64-unknown-linux-gnu`
637
638To work correctly ThreadSanitizer needs to be "aware" of all synchronization
639operations in a program. It generally achieves that through combination of
640library interception (for example synchronization performed through
641`pthread_mutex_lock` / `pthread_mutex_unlock`) and compile time instrumentation
642(e.g. atomic operations). Using it without instrumenting all the program code
643can lead to false positive reports.
644
645ThreadSanitizer does not support atomic fences `std::sync::atomic::fence`,
646nor synchronization performed using inline assembly code.
647
f2b60f7d
FG
648See the [Clang ThreadSanitizer documentation][clang-tsan] for more details.
649
ba9703b0
XL
650## Example
651
652```rust
653static mut A: usize = 0;
654
655fn main() {
656 let t = std::thread::spawn(|| {
657 unsafe { A += 1 };
658 });
659 unsafe { A += 1 };
660
661 t.join().unwrap();
662}
663```
664
665```shell
666$ export RUSTFLAGS=-Zsanitizer=thread RUSTDOCFLAGS=-Zsanitizer=thread
667$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
668==================
669WARNING: ThreadSanitizer: data race (pid=10574)
670 Read of size 8 at 0x5632dfe3d030 by thread T1:
671 #0 example::main::_$u7b$$u7b$closure$u7d$$u7d$::h23f64b0b2f8c9484 ../src/main.rs:5:18 (example+0x86cec)
672 ...
673
674 Previous write of size 8 at 0x5632dfe3d030 by main thread:
675 #0 example::main::h628ffc6626ed85b2 /.../src/main.rs:7:14 (example+0x868c8)
676 ...
677 #11 main <null> (example+0x86a1a)
678
679 Location is global 'example::A::h43ac149ddf992709' of size 8 at 0x5632dfe3d030 (example+0x000000bd9030)
680```
dfeec247
XL
681
682# Instrumentation of external dependencies and std
683
684The sanitizers to varying degrees work correctly with partially instrumented
685code. On the one extreme is LeakSanitizer that doesn't use any compile time
686instrumentation, on the other is MemorySanitizer that requires that all program
687code to be instrumented (failing to achieve that will inevitably result in
688false positives).
689
690It is strongly recommended to combine sanitizers with recompiled and
691instrumented standard library, for example using [cargo `-Zbuild-std`
692functionality][build-std].
693
6522a427 694[build-std]: ../../cargo/reference/unstable.html#build-std
dfeec247
XL
695
696# Build scripts and procedural macros
697
698Use of sanitizers together with build scripts and procedural macros is
699technically possible, but in almost all cases it would be best avoided. This
700is especially true for procedural macros which would require an instrumented
701version of rustc.
702
703In more practical terms when using cargo always remember to pass `--target`
704flag, so that rustflags will not be applied to build scripts and procedural
705macros.
706
ba9703b0
XL
707# Symbolizing the Reports
708
709Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PATH`.
710
dfeec247
XL
711# Additional Information
712
713* [Sanitizers project page](https://github.com/google/sanitizers/wiki/)
714* [AddressSanitizer in Clang][clang-asan]
3c0e092e 715* [ControlFlowIntegrity in Clang][clang-cfi]
6a06907d 716* [HWAddressSanitizer in Clang][clang-hwasan]
dfeec247
XL
717* [LeakSanitizer in Clang][clang-lsan]
718* [MemorySanitizer in Clang][clang-msan]
f2b60f7d 719* [MemTagSanitizer in LLVM][llvm-memtag]
dfeec247
XL
720* [ThreadSanitizer in Clang][clang-tsan]
721
722[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
3c0e092e 723[clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html
6a06907d 724[clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
6522a427 725[clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi
dfeec247
XL
726[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
727[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
064997fb 728[clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html
dfeec247 729[clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
f2b60f7d 730[llvm-memtag]: https://llvm.org/docs/MemTagSanitizer.html