diff options
| author | Ramon de C Valle <rcvalle@users.noreply.github.com> | 2021-10-07 15:33:13 -0700 |
|---|---|---|
| committer | Ramon de C Valle <rcvalle@users.noreply.github.com> | 2021-10-25 16:23:01 -0700 |
| commit | 5d30e9318900dd4f034c21f1378fea7b40998b07 (patch) | |
| tree | 0132f1f3b8ef91edf7c0a97c7fc7310fcc3017b0 /src/test/codegen | |
| parent | 1067e2ca5e9cfe5c79f956e49ffc684c5142d49b (diff) | |
| download | rust-5d30e9318900dd4f034c21f1378fea7b40998b07.tar.gz rust-5d30e9318900dd4f034c21f1378fea7b40998b07.zip | |
Add LLVM CFI support to the Rust compiler
This commit adds LLVM Control Flow Integrity (CFI) support to the Rust compiler. It initially provides forward-edge control flow protection for Rust-compiled code only by aggregating function pointers in groups identified by their number of arguments. Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed binaries" (i.e., for when C or C++ and Rust -compiled code share the same virtual address space) will be provided in later work as part of this project by defining and using compatible type identifiers (see Type metadata in the design document in the tracking issue #89653). LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto).
Diffstat (limited to 'src/test/codegen')
3 files changed, 69 insertions, 0 deletions
diff --git a/src/test/codegen/sanitizer_cfi_add_canonical_jump_tables_flag.rs b/src/test/codegen/sanitizer_cfi_add_canonical_jump_tables_flag.rs new file mode 100644 index 00000000000..68f81808861 --- /dev/null +++ b/src/test/codegen/sanitizer_cfi_add_canonical_jump_tables_flag.rs @@ -0,0 +1,14 @@ +// Verifies that "CFI Canonical Jump Tables" module flag is added. +// +// ignore-windows +// needs-sanitizer-cfi +// only-aarch64 +// only-x86_64 +// compile-flags: -Clto -Zsanitizer=cfi + +#![crate_type="lib"] + +pub fn foo() { +} + +// CHECK: !{{[0-9]+}} = !{i32 2, !"CFI Canonical Jump Tables", i32 1} diff --git a/src/test/codegen/sanitizer_cfi_emit_type_checks.rs b/src/test/codegen/sanitizer_cfi_emit_type_checks.rs new file mode 100644 index 00000000000..9ed0422ceff --- /dev/null +++ b/src/test/codegen/sanitizer_cfi_emit_type_checks.rs @@ -0,0 +1,24 @@ +// Verifies that pointer type membership tests for indirect calls are emitted. +// +// ignore-windows +// needs-sanitizer-cfi +// only-aarch64 +// only-x86_64 +// compile-flags: -Clto -Cno-prepopulate-passes -Zsanitizer=cfi + +#![crate_type="lib"] + +pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { + // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} + // CHECK: start: + // CHECK-NEXT: %0 = bitcast i32 (i32)* %f to i8* + // CHECK-NEXT: %1 = call i1 @llvm.type.test(i8* %0, metadata !"{{[[:print:]]+}}") + // CHECK-NEXT: br i1 %1, label %type_test.pass, label %type_test.fail + // CHECK: type_test.pass: + // CHECK-NEXT: %2 = call i32 %f(i32 %arg) + // CHECK-NEXT: br label %bb1 + // CHECK: type_test.fail: + // CHECK-NEXT: call void @llvm.trap() + // CHECK-NEXT: unreachable + f(arg) +} diff --git a/src/test/codegen/sanitizer_cfi_emit_type_metadata.rs b/src/test/codegen/sanitizer_cfi_emit_type_metadata.rs new file mode 100644 index 00000000000..96fced47e78 --- /dev/null +++ b/src/test/codegen/sanitizer_cfi_emit_type_metadata.rs @@ -0,0 +1,31 @@ +// Verifies that type metadata for functions are emitted. +// +// ignore-windows +// needs-sanitizer-cfi +// only-aarch64 +// only-x86_64 +// compile-flags: -Clto -Cno-prepopulate-passes -Zsanitizer=cfi + +#![crate_type="lib"] + +pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { + // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} + // CHECK: %1 = call i1 @llvm.type.test(i8* %0, metadata !"typeid1") + f(arg) +} + +pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 { + // CHECK-LABEL: define{{.*}}bar{{.*}}!type !{{[0-9]+}} + // CHECK: %1 = call i1 @llvm.type.test(i8* %0, metadata !"typeid2") + f(arg1, arg2) +} + +pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 { + // CHECK-LABEL: define{{.*}}baz{{.*}}!type !{{[0-9]+}} + // CHECK: %1 = call i1 @llvm.type.test(i8* %0, metadata !"typeid3") + f(arg1, arg2, arg3) +} + +// CHECK: !{{[0-9]+}} = !{i64 0, !"typeid2"} +// CHECK: !{{[0-9]+}} = !{i64 0, !"typeid3"} +// CHECK: !{{[0-9]+}} = !{i64 0, !"typeid4"} |
