mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 19:58:32 +00:00
Auto merge of #115200 - rcvalle:rust-cfi-fix-115199, r=workingjubilee
Disable CFI for core and std CFI violations Work around https://github.com/rust-lang/rust/issues/115199 by temporarily disabling CFI for core and std CFI violations to allow the user rebuild and use both core and std with CFI enabled using the Cargo build-std feature.
This commit is contained in:
commit
eea26141ec
@ -133,6 +133,10 @@ impl<'a> Argument<'a> {
|
|||||||
Self::new(x, USIZE_MARKER)
|
Self::new(x, USIZE_MARKER)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Transmuting formatter in new and indirectly branching to/calling
|
||||||
|
// it here is an explicit CFI violation.
|
||||||
|
#[allow(inline_no_sanitize)]
|
||||||
|
#[no_sanitize(cfi, kcfi)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(super) fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
pub(super) fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
(self.formatter)(self.value, f)
|
(self.formatter)(self.value, f)
|
||||||
|
@ -238,6 +238,7 @@
|
|||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(no_core)]
|
#![feature(no_core)]
|
||||||
|
#![feature(no_sanitize)]
|
||||||
#![feature(platform_intrinsics)]
|
#![feature(platform_intrinsics)]
|
||||||
#![feature(prelude_import)]
|
#![feature(prelude_import)]
|
||||||
#![feature(repr_simd)]
|
#![feature(repr_simd)]
|
||||||
|
@ -270,6 +270,7 @@
|
|||||||
#![feature(allow_internal_unstable)]
|
#![feature(allow_internal_unstable)]
|
||||||
#![feature(c_unwind)]
|
#![feature(c_unwind)]
|
||||||
#![feature(cfg_target_thread_local)]
|
#![feature(cfg_target_thread_local)]
|
||||||
|
#![feature(cfi_encoding)]
|
||||||
#![feature(concat_idents)]
|
#![feature(concat_idents)]
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
@ -292,6 +293,7 @@
|
|||||||
#![feature(needs_panic_runtime)]
|
#![feature(needs_panic_runtime)]
|
||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
#![feature(no_sanitize)]
|
||||||
#![feature(platform_intrinsics)]
|
#![feature(platform_intrinsics)]
|
||||||
#![feature(prelude_import)]
|
#![feature(prelude_import)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
@ -11,28 +11,47 @@
|
|||||||
// Note, however, that we run on lots older linuxes, as well as cross
|
// Note, however, that we run on lots older linuxes, as well as cross
|
||||||
// compiling from a newer linux to an older linux, so we also have a
|
// compiling from a newer linux to an older linux, so we also have a
|
||||||
// fallback implementation to use as well.
|
// fallback implementation to use as well.
|
||||||
|
#[allow(unexpected_cfgs)]
|
||||||
#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "redox", target_os = "hurd"))]
|
#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "redox", target_os = "hurd"))]
|
||||||
|
// FIXME: The Rust compiler currently omits weakly function definitions (i.e.,
|
||||||
|
// __cxa_thread_atexit_impl) and its metadata from LLVM IR.
|
||||||
|
#[no_sanitize(cfi, kcfi)]
|
||||||
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
|
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::sys_common::thread_local_dtor::register_dtor_fallback;
|
use crate::sys_common::thread_local_dtor::register_dtor_fallback;
|
||||||
|
|
||||||
|
/// This is necessary because the __cxa_thread_atexit_impl implementation
|
||||||
|
/// std links to by default may be a C or C++ implementation that was not
|
||||||
|
/// compiled using the Clang integer normalization option.
|
||||||
|
#[cfg(not(sanitizer_cfi_normalize_integers))]
|
||||||
|
#[cfi_encoding = "i"]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct c_int(pub libc::c_int);
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[linkage = "extern_weak"]
|
#[linkage = "extern_weak"]
|
||||||
static __dso_handle: *mut u8;
|
static __dso_handle: *mut u8;
|
||||||
#[linkage = "extern_weak"]
|
#[linkage = "extern_weak"]
|
||||||
static __cxa_thread_atexit_impl: *const libc::c_void;
|
static __cxa_thread_atexit_impl: Option<
|
||||||
|
extern "C" fn(
|
||||||
|
unsafe extern "C" fn(*mut libc::c_void),
|
||||||
|
*mut libc::c_void,
|
||||||
|
*mut libc::c_void,
|
||||||
|
) -> c_int,
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
if !__cxa_thread_atexit_impl.is_null() {
|
|
||||||
type F = unsafe extern "C" fn(
|
if let Some(f) = __cxa_thread_atexit_impl {
|
||||||
dtor: unsafe extern "C" fn(*mut u8),
|
unsafe {
|
||||||
arg: *mut u8,
|
f(
|
||||||
dso_handle: *mut u8,
|
mem::transmute::<
|
||||||
) -> libc::c_int;
|
unsafe extern "C" fn(*mut u8),
|
||||||
mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl)(
|
unsafe extern "C" fn(*mut libc::c_void),
|
||||||
dtor,
|
>(dtor),
|
||||||
t,
|
t.cast(),
|
||||||
&__dso_handle as *const _ as *mut _,
|
&__dso_handle as *const _ as *mut _,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
register_dtor_fallback(t, dtor);
|
register_dtor_fallback(t, dtor);
|
||||||
|
@ -197,22 +197,26 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
|
|||||||
|
|
||||||
# ControlFlowIntegrity
|
# ControlFlowIntegrity
|
||||||
|
|
||||||
The LLVM Control Flow Integrity (CFI) support in the Rust compiler provides
|
The LLVM CFI support in the Rust compiler provides forward-edge control flow
|
||||||
forward-edge control flow protection for both Rust-compiled code only and for C
|
protection for both Rust-compiled code only and for C or C++ and Rust -compiled
|
||||||
or C++ and Rust -compiled code mixed-language binaries, also known as “mixed
|
code mixed-language binaries, also known as “mixed binaries” (i.e., for when C
|
||||||
binaries” (i.e., for when C or C++ and Rust -compiled code share the same
|
or C++ and Rust -compiled code share the same virtual address space), by
|
||||||
virtual address space), by aggregating function pointers in groups identified by
|
aggregating function pointers in groups identified by their return and parameter
|
||||||
their return and parameter types.
|
types.
|
||||||
|
|
||||||
LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e., `-Clto`).
|
LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e.,
|
||||||
Cross-language LLVM CFI can be enabled with `-Zsanitizer=cfi`, and requires the
|
`-Clinker-plugin-lto` or `-Clto`). Cross-language LLVM CFI can be enabled with
|
||||||
`-Zsanitizer-cfi-normalize-integers` option to be used with Clang
|
`-Zsanitizer=cfi`, and requires the `-Zsanitizer-cfi-normalize-integers` option
|
||||||
`-fsanitize-cfi-icall-normalize-integers` for normalizing integer types, and
|
to be used with Clang `-fsanitize-cfi-icall-experimental-normalize-integers`
|
||||||
proper (i.e., non-rustc) LTO (i.e., `-Clinker-plugin-lto`).
|
option for cross-language LLVM CFI support, and proper (i.e., non-rustc) LTO
|
||||||
|
(i.e., `-Clinker-plugin-lto`).
|
||||||
|
|
||||||
|
It is recommended to rebuild the standard library with CFI enabled by using the
|
||||||
|
Cargo build-std feature (i.e., `-Zbuild-std`) when enabling CFI.
|
||||||
|
|
||||||
See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details.
|
See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details.
|
||||||
|
|
||||||
## Example
|
## Example 1: Redirecting control flow using an indirect branch/call to an invalid destination
|
||||||
|
|
||||||
```rust,ignore (making doc tests pass cross-platform is hard)
|
```rust,ignore (making doc tests pass cross-platform is hard)
|
||||||
#![feature(naked_functions)]
|
#![feature(naked_functions)]
|
||||||
@ -239,7 +243,7 @@ pub extern "C" fn add_two(x: i32) {
|
|||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
lea eax, [edi+2]
|
lea eax, [rdi+2]
|
||||||
ret
|
ret
|
||||||
",
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
@ -258,8 +262,9 @@ fn main() {
|
|||||||
|
|
||||||
println!("With CFI enabled, you should not see the next answer");
|
println!("With CFI enabled, you should not see the next answer");
|
||||||
let f: fn(i32) -> i32 = unsafe {
|
let f: fn(i32) -> i32 = unsafe {
|
||||||
// Offsets 0-8 make it land in the landing pad/nop block, and offsets 1-8 are
|
// Offset 0 is a valid branch/call destination (i.e., the function entry
|
||||||
// invalid branch/call destinations (i.e., within the body of the function).
|
// point), but offsets 1-8 within the landing pad/nop block are invalid
|
||||||
|
// branch/call destinations (i.e., within the body of the function).
|
||||||
mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5))
|
mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5))
|
||||||
};
|
};
|
||||||
let next_answer = do_twice(f, 5);
|
let next_answer = do_twice(f, 5);
|
||||||
@ -267,38 +272,40 @@ fn main() {
|
|||||||
println!("The next answer is: {}", next_answer);
|
println!("The next answer is: {}", next_answer);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Fig. 1. Modified example from the [Advanced Functions and
|
Fig. 1. Redirecting control flow using an indirect branch/call to an invalid
|
||||||
Closures][rust-book-ch19-05] chapter of the [The Rust Programming
|
destination (i.e., within the body of the function).
|
||||||
Language][rust-book] book.
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ cargo run --release
|
$ cargo run --release
|
||||||
Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
|
Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
|
||||||
Finished release [optimized] target(s) in 0.76s
|
Finished release [optimized] target(s) in 0.42s
|
||||||
Running `target/release/rust-cfi-1`
|
Running `target/release/rust-cfi-1`
|
||||||
The answer is: 12
|
The answer is: 12
|
||||||
With CFI enabled, you should not see the next answer
|
With CFI enabled, you should not see the next answer
|
||||||
The next answer is: 14
|
The next answer is: 14
|
||||||
$
|
$
|
||||||
```
|
```
|
||||||
Fig. 2. Build and execution of the modified example with LLVM CFI disabled.
|
Fig. 2. Build and execution of Fig. 1 with LLVM CFI disabled.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
|
$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
|
||||||
|
...
|
||||||
Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
|
Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
|
||||||
Finished release [optimized] target(s) in 3.39s
|
Finished release [optimized] target(s) in 1m 08s
|
||||||
Running `target/release/rust-cfi-1`
|
Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-1`
|
||||||
The answer is: 12
|
The answer is: 12
|
||||||
With CFI enabled, you should not see the next answer
|
With CFI enabled, you should not see the next answer
|
||||||
Illegal instruction
|
Illegal instruction
|
||||||
$
|
$
|
||||||
```
|
```
|
||||||
Fig. 3. Build and execution of the modified example with LLVM CFI enabled.
|
Fig. 3. Build and execution of Fig. 1 with LLVM CFI enabled.
|
||||||
|
|
||||||
When LLVM CFI is enabled, if there are any attempts to change/hijack control
|
When LLVM CFI is enabled, if there are any attempts to change/hijack control
|
||||||
flow using an indirect branch/call to an invalid destination, the execution is
|
flow using an indirect branch/call to an invalid destination, the execution is
|
||||||
terminated (see Fig. 3).
|
terminated (see Fig. 3).
|
||||||
|
|
||||||
|
## Example 2: Redirecting control flow using an indirect branch/call to a function with a different number of parameters
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
@ -327,39 +334,42 @@ fn main() {
|
|||||||
println!("The next answer is: {}", next_answer);
|
println!("The next answer is: {}", next_answer);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Fig. 4. Another modified example from the [Advanced Functions and
|
Fig. 4. Redirecting control flow using an indirect branch/call to a function
|
||||||
Closures][rust-book-ch19-05] chapter of the [The Rust Programming
|
with a different number of parameters than arguments intended/passed in the
|
||||||
Language][rust-book] book.
|
call/branch site.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ cargo run --release
|
$ cargo run --release
|
||||||
Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
|
Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
|
||||||
Finished release [optimized] target(s) in 0.76s
|
Finished release [optimized] target(s) in 0.43s
|
||||||
Running `target/release/rust-cfi-2`
|
Running `target/release/rust-cfi-2`
|
||||||
The answer is: 12
|
The answer is: 12
|
||||||
With CFI enabled, you should not see the next answer
|
With CFI enabled, you should not see the next answer
|
||||||
The next answer is: 14
|
The next answer is: 14
|
||||||
$
|
$
|
||||||
```
|
```
|
||||||
Fig. 5. Build and execution of the modified example with LLVM CFI disabled.
|
Fig. 5. Build and execution of Fig. 4 with LLVM CFI disabled.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release
|
$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
|
||||||
|
...
|
||||||
Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
|
Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
|
||||||
Finished release [optimized] target(s) in 3.38s
|
Finished release [optimized] target(s) in 1m 08s
|
||||||
Running `target/release/rust-cfi-2`
|
Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-2`
|
||||||
The answer is: 12
|
The answer is: 12
|
||||||
With CFI enabled, you should not see the next answer
|
With CFI enabled, you should not see the next answer
|
||||||
Illegal instruction
|
Illegal instruction
|
||||||
$
|
$
|
||||||
```
|
```
|
||||||
Fig. 6. Build and execution of the modified example with LLVM CFI enabled.
|
Fig. 6. Build and execution of Fig. 4 with LLVM CFI enabled.
|
||||||
|
|
||||||
When LLVM CFI is enabled, if there are any attempts to change/hijack control
|
When LLVM CFI is enabled, if there are any attempts to change/hijack control
|
||||||
flow using an indirect branch/call to a function with different number of
|
flow using an indirect branch/call to a function with different number of
|
||||||
parameters than arguments intended/passed in the call/branch site, the
|
parameters than arguments intended/passed in the call/branch site, the
|
||||||
execution is also terminated (see Fig. 6).
|
execution is also terminated (see Fig. 6).
|
||||||
|
|
||||||
|
## Example 3: Redirecting control flow using an indirect branch/call to a function with different return and parameter types
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
@ -388,42 +398,46 @@ fn main() {
|
|||||||
println!("The next answer is: {}", next_answer);
|
println!("The next answer is: {}", next_answer);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Fig. 7. Another modified example from the [Advanced Functions and
|
Fig. 7. Redirecting control flow using an indirect branch/call to a function
|
||||||
Closures][rust-book-ch19-05] chapter of the [The Rust Programming
|
with different return and parameter types than the return type expected and
|
||||||
Language][rust-book] book.
|
arguments intended/passed at the call/branch site.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ cargo run --release
|
$ cargo run --release
|
||||||
Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
|
Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
|
||||||
Finished release [optimized] target(s) in 0.74s
|
Finished release [optimized] target(s) in 0.44s
|
||||||
Running `target/release/rust-cfi-3`
|
Running `target/release/rust-cfi-3`
|
||||||
The answer is: 12
|
The answer is: 12
|
||||||
With CFI enabled, you should not see the next answer
|
With CFI enabled, you should not see the next answer
|
||||||
The next answer is: 14
|
The next answer is: 14
|
||||||
$
|
$
|
||||||
```
|
```
|
||||||
Fig. 8. Build and execution of the modified example with LLVM CFI disabled.
|
Fig. 8. Build and execution of Fig. 7 with LLVM CFI disabled.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release
|
$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
|
||||||
|
...
|
||||||
Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
|
Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
|
||||||
Finished release [optimized] target(s) in 3.40s
|
Finished release [optimized] target(s) in 1m 07s
|
||||||
Running `target/release/rust-cfi-3`
|
Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-3`
|
||||||
The answer is: 12
|
The answer is: 12
|
||||||
With CFI enabled, you should not see the next answer
|
With CFI enabled, you should not see the next answer
|
||||||
Illegal instruction
|
Illegal instruction
|
||||||
$
|
$
|
||||||
```
|
```
|
||||||
Fig. 9. Build and execution of the modified example with LLVM CFI enabled.
|
Fig. 9. Build and execution of Fig. 7 with LLVM CFI enabled.
|
||||||
|
|
||||||
When LLVM CFI is enabled, if there are any attempts to change/hijack control
|
When LLVM CFI is enabled, if there are any attempts to change/hijack control
|
||||||
flow using an indirect branch/call to a function with different return and
|
flow using an indirect branch/call to a function with different return and
|
||||||
parameter types than the return type expected and arguments intended/passed in
|
parameter types than the return type expected and arguments intended/passed in
|
||||||
the call/branch site, the execution is also terminated (see Fig. 9).
|
the call/branch site, the execution is also terminated (see Fig. 9).
|
||||||
|
|
||||||
|
## Example 4: Redirecting control flow using an indirect branch/call to a function with different return and parameter types across the FFI boundary
|
||||||
|
|
||||||
```ignore (cannot-test-this-because-uses-custom-build)
|
```ignore (cannot-test-this-because-uses-custom-build)
|
||||||
int
|
int
|
||||||
do_twice(int (*fn)(int), int arg) {
|
do_twice(int (*fn)(int), int arg)
|
||||||
|
{
|
||||||
return fn(arg) + fn(arg);
|
return fn(arg) + fn(arg);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -459,54 +473,49 @@ fn main() {
|
|||||||
println!("The next answer is: {}", next_answer);
|
println!("The next answer is: {}", next_answer);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Fig. 11. Another modified example from the [Advanced Functions and
|
Fig. 11. Redirecting control flow using an indirect branch/call to a function
|
||||||
Closures][rust-book-ch19-05] chapter of the [The Rust Programming
|
with different return and parameter types than the return type expected and
|
||||||
Language][rust-book] book.
|
arguments intended/passed in the call/branch site, across the FFI boundary.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ make
|
$ make
|
||||||
mkdir -p target/debug
|
mkdir -p target/release
|
||||||
clang -I. -Isrc -Wall -flto -fvisibility=hidden -c -emit-llvm src/foo.c -o target/debug/libfoo.bc
|
clang -I. -Isrc -Wall -c src/foo.c -o target/release/libfoo.o
|
||||||
llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc
|
llvm-ar rcs target/release/libfoo.a target/release/libfoo.o
|
||||||
RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build
|
RUSTFLAGS="-L./target/release -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release
|
||||||
Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1)
|
Compiling rust-cfi-4 v0.1.0 (/home/rcvalle/rust-cfi-4)
|
||||||
Finished dev [unoptimized + debuginfo] target(s) in 0.45s
|
Finished release [optimized] target(s) in 0.49s
|
||||||
$ ./target/debug/main
|
$ ./target/release/rust-cfi-4
|
||||||
The answer is: 12
|
The answer is: 12
|
||||||
With CFI enabled, you should not see the next answer
|
With CFI enabled, you should not see the next answer
|
||||||
The next answer is: 14
|
The next answer is: 14
|
||||||
$
|
$
|
||||||
```
|
```
|
||||||
Fig. 12. Build and execution of the modified example with LLVM CFI disabled.
|
Fig. 12. Build and execution of Figs. 10–11 with LLVM CFI disabled.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ make
|
$ make
|
||||||
mkdir -p target/debug
|
mkdir -p target/release
|
||||||
clang -I. -Isrc -Wall -flto -fvisibility=hidden -fsanitize=cfi -fsanitize-cfi-icall-normalize-integers -c -emit-llvm src/foo.c -o target/debug/libfoo.bc
|
clang -I. -Isrc -Wall -flto -fsanitize=cfi -fsanitize-cfi-icall-experimental-normalize-integers -fvisibility=hidden -c -emit-llvm src/foo.c -o target/release/libfoo.bc
|
||||||
llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc
|
llvm-ar rcs target/release/libfoo.a target/release/libfoo.bc
|
||||||
RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build
|
RUSTFLAGS="-L./target/release -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
|
||||||
Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1)
|
...
|
||||||
Finished dev [unoptimized + debuginfo] target(s) in 0.45s
|
Compiling rust-cfi-4 v0.1.0 (/home/rcvalle/rust-cfi-4)
|
||||||
$ ./target/debug/main
|
Finished release [optimized] target(s) in 1m 06s
|
||||||
|
$ ./target/x86_64-unknown-linux-gnu/release/rust-cfi-4
|
||||||
The answer is: 12
|
The answer is: 12
|
||||||
With CFI enabled, you should not see the next answer
|
With CFI enabled, you should not see the next answer
|
||||||
Illegal instruction
|
Illegal instruction
|
||||||
$
|
$
|
||||||
```
|
```
|
||||||
Fig. 13. Build and execution of the modified example with LLVM CFI enabled.
|
Fig. 13. Build and execution of FIgs. 10–11 with LLVM CFI enabled.
|
||||||
|
|
||||||
When LLVM CFI is enabled, if there are any attempts to change/hijack control
|
When LLVM CFI is enabled, if there are any attempts to redirect control flow
|
||||||
flow using an indirect branch/call to a function with different return and
|
using an indirect branch/call to a function with different return and parameter
|
||||||
parameter types than the return type expected and arguments intended/passed in
|
types than the return type expected and arguments intended/passed in the
|
||||||
the call/branch site, even across the FFI boundary and for extern "C" function
|
call/branch site, even across the FFI boundary and for extern "C" function types
|
||||||
types indirectly called (i.e., callbacks/function pointers) across the FFI
|
indirectly called (i.e., callbacks/function pointers) across the FFI boundary,
|
||||||
boundary, in C or C++ and Rust -compiled code mixed-language binaries, also
|
the execution is also terminated (see Fig. 13).
|
||||||
known as “mixed binaries” (i.e., for when C or C++ and Rust -compiled code share
|
|
||||||
the same virtual address space), the execution is also terminated (see Fig. 13).
|
|
||||||
|
|
||||||
|
|
||||||
[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
|
|
||||||
[rust-book]: https://doc.rust-lang.org/book/title-page.html
|
|
||||||
|
|
||||||
# HWAddressSanitizer
|
# HWAddressSanitizer
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user