-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CFI: Fix SIGILL reached via trait objects
Fix #106547 by transforming the concrete self into a reference to a trait object before emitting type metadata identifiers for trait methods.
- Loading branch information
Showing
10 changed files
with
247 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Verifies that type metadata identifiers for trait objects are emitted correctly. | ||
// | ||
// needs-sanitizer-cfi | ||
// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi | ||
|
||
#![crate_type="lib"] | ||
|
||
trait Trait1 { | ||
fn foo(&self); | ||
} | ||
|
||
struct Type1; | ||
|
||
impl Trait1 for Type1 { | ||
fn foo(&self) { | ||
} | ||
} | ||
|
||
pub fn foo() { | ||
let a = Type1; | ||
a.foo(); | ||
// CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} | ||
// CHECK: call <sanitizer_cfi_emit_type_metadata_trait_objects::Type1 as sanitizer_cfi_emit_type_metadata_trait_objects::Trait1>::foo | ||
} | ||
|
||
pub fn bar() { | ||
let a = Type1; | ||
let b = &a as &dyn Trait1; | ||
b.foo(); | ||
// CHECK-LABEL: define{{.*}}bar{{.*}}!type !{{[0-9]+}} | ||
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0|%1}}, metadata !"[[TYPE1:[[:print:]]+]]") | ||
} | ||
|
||
pub fn baz() { | ||
let a = Type1; | ||
let b = &a as &dyn Trait1; | ||
a.foo(); | ||
b.foo(); | ||
// CHECK-LABEL: define{{.*}}baz{{.*}}!type !{{[0-9]+}} | ||
// CHECK: call <sanitizer_cfi_emit_type_metadata_trait_objects::Type1 as sanitizer_cfi_emit_type_metadata_trait_objects::Trait1>::foo | ||
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0|%1}}, metadata !"[[TYPE1:[[:print:]]+]]") | ||
} | ||
|
||
// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE1]]"} |
69 changes: 69 additions & 0 deletions
69
tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Verifies that type metadata identifiers for trait objects are emitted correctly. | ||
// | ||
// revisions: aarch64 x86_64 | ||
// [aarch64] compile-flags: --target aarch64-unknown-none | ||
// [aarch64] needs-llvm-components: aarch64 | ||
// [x86_64] compile-flags: --target x86_64-unknown-none | ||
// [x86_64] needs-llvm-components: | ||
// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 | ||
|
||
#![crate_type="lib"] | ||
#![feature(arbitrary_self_types, no_core, lang_items)] | ||
#![no_core] | ||
|
||
#[lang="sized"] | ||
trait Sized { } | ||
#[lang="copy"] | ||
trait Copy { } | ||
#[lang="receiver"] | ||
trait Receiver { } | ||
#[lang="dispatch_from_dyn"] | ||
trait DispatchFromDyn<T> { } | ||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} | ||
#[lang = "unsize"] | ||
trait Unsize<T: ?Sized> { } | ||
#[lang = "coerce_unsized"] | ||
pub trait CoerceUnsized<T: ?Sized> { } | ||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
#[lang="freeze"] | ||
trait Freeze { } | ||
#[lang="drop_in_place"] | ||
fn drop_in_place_fn<T>() { } | ||
|
||
trait Trait1 { | ||
fn foo(&self); | ||
} | ||
|
||
struct Type1; | ||
|
||
impl Trait1 for Type1 { | ||
fn foo(&self) { | ||
} | ||
} | ||
|
||
pub fn foo() { | ||
let a = Type1; | ||
a.foo(); | ||
// CHECK-LABEL: define{{.*}}foo{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}} | ||
// CHECK: call <sanitizer_kcfi_emit_type_metadata_trait_objects::Type1 as sanitizer_kcfi_emit_type_metadata_trait_objects::Trait1>::foo | ||
} | ||
|
||
pub fn bar() { | ||
let a = Type1; | ||
let b = &a as &dyn Trait1; | ||
b.foo(); | ||
// CHECK-LABEL: define{{.*}}bar{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}} | ||
// CHECK: call void %0({{\{\}\*|ptr}} align 1 {{%b\.0|%_1}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ] | ||
} | ||
|
||
pub fn baz() { | ||
let a = Type1; | ||
let b = &a as &dyn Trait1; | ||
a.foo(); | ||
b.foo(); | ||
// CHECK-LABEL: define{{.*}}baz{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}} | ||
// CHECK: call <sanitizer_kcfi_emit_type_metadata_trait_objects::Type1 as sanitizer_kcfi_emit_type_metadata_trait_objects::Trait1>::foo | ||
// CHECK: call void %0({{\{\}\*|ptr}} align 1 {{%b\.0|%_1}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ] | ||
} | ||
|
||
// CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]} |