-
Notifications
You must be signed in to change notification settings - Fork 12.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang] Implement type/address discrimination of type_info vtable. #99726
[clang] Implement type/address discrimination of type_info vtable. #99726
Conversation
We want to be able to support full type and address discrimination of type_info on targets that don't have existing ABI compatibility constraints. This patch does not enable such behavior on any platform, it just adds the necessary machinery. In clang we add a new commandline argument to control the type_info vtable ABI: -fptrauth-type-info-vtable-pointer-discrimination and a feature flag to allow source level detection of the ABI: __has_feature(ptrauth_type_info_vtable_pointer_discrimination)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
Co-authored-by: Daniil Kovalev <kovdan01@yandex.ru>
@llvm/pr-subscribers-clang Author: Ahmed Bougacha (ahmedbougacha) ChangesWe want to be able to support full type and address discrimination of type_info on targets that don't have existing ABI compatibility constraints. This patch does not enable such behavior on any platform, it just adds the necessary machinery. In clang we add a new commandline argument to control the type_info vtable ABI:
and a feature flag to allow source level detection of the ABI:
Co-authored-by: Oliver Hunt <oliver@apple.com> Full diff: https://github.com/llvm/llvm-project/pull/99726.diff 6 Files Affected:
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index 2f864ff1c0edf..14572bc0407fc 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -108,6 +108,7 @@ FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination)
FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination)
+FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls)
FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination)
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index a6f36b23f07dc..8b09049b5cb97 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -168,6 +168,7 @@ LANGOPT(PointerAuthReturns, 1, 0, "return pointer authentication")
LANGOPT(PointerAuthAuthTraps, 1, 0, "pointer authentication failure traps")
LANGOPT(PointerAuthVTPtrAddressDiscrimination, 1, 0, "incorporate address discrimination in authenticated vtable pointers")
LANGOPT(PointerAuthVTPtrTypeDiscrimination, 1, 0, "incorporate type discrimination in authenticated vtable pointers")
+LANGOPT(PointerAuthTypeInfoVTPtrDiscrimination, 1, 0, "incorporate type and address discrimination in authenticated vtable pointers for std::type_info")
LANGOPT(PointerAuthInitFini, 1, 0, "sign function pointers in init/fini arrays")
BENIGN_LANGOPT(PointerAuthFunctionTypeDiscrimination, 1, 0,
"Use type discrimination when signing function pointers")
diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h
index 197d63642ca6d..6153209410843 100644
--- a/clang/include/clang/Basic/PointerAuthOptions.h
+++ b/clang/include/clang/Basic/PointerAuthOptions.h
@@ -25,6 +25,11 @@ namespace clang {
constexpr unsigned PointerAuthKeyNone = -1;
+/// Constant discriminator for std::type_info vtable pointers: 0xB1EA/45546
+/// The value is ptrauth_string_discriminator("_ZTVSt9type_info"), i.e.,
+/// the vtable type discriminator for classes derived from std::type_info.
+constexpr uint16_t StdTypeInfoVTablePointerConstantDiscrimination = 0xB1EA;
+
class PointerAuthSchema {
public:
enum class Kind : unsigned {
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 9c6cebd77ff0a..70dab1b16094d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4249,6 +4249,8 @@ defm ptrauth_vtable_pointer_address_discrimination :
OptInCC1FFlag<"ptrauth-vtable-pointer-address-discrimination", "Enable address discrimination of vtable pointers">;
defm ptrauth_vtable_pointer_type_discrimination :
OptInCC1FFlag<"ptrauth-vtable-pointer-type-discrimination", "Enable type discrimination of vtable pointers">;
+defm ptrauth_type_info_vtable_pointer_discrimination :
+ OptInCC1FFlag<"ptrauth-type-info-vtable-pointer-discrimination", "Enable type and address discrimination of vtable pointer of std::type_info">;
defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of function pointers in init/fini arrays">;
defm ptrauth_function_pointer_type_discrimination : OptInCC1FFlag<"ptrauth-function-pointer-type-discrimination",
"Enable type discrimination on C function pointers">;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index bf57addff1c6d..424fe53990c38 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1488,8 +1488,15 @@ void CompilerInvocation::setDefaultPointerAuthOptions(
Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,
LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type
: Discrimination::None);
- Opts.CXXTypeInfoVTablePointer =
- PointerAuthSchema(Key::ASDA, false, Discrimination::None);
+
+ if (LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
+ Opts.CXXTypeInfoVTablePointer =
+ PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
+ StdTypeInfoVTablePointerConstantDiscrimination);
+ else
+ Opts.CXXTypeInfoVTablePointer =
+ PointerAuthSchema(Key::ASDA, false, Discrimination::None);
+
Opts.CXXVTTVTablePointers =
PointerAuthSchema(Key::ASDA, false, Discrimination::None);
Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers =
@@ -3411,6 +3418,9 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination);
if (Opts.PointerAuthVTPtrTypeDiscrimination)
GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
+ if (Opts.PointerAuthTypeInfoVTPtrDiscrimination)
+ GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination);
+
if (Opts.PointerAuthInitFini)
GenerateArg(Consumer, OPT_fptrauth_init_fini);
if (Opts.PointerAuthFunctionTypeDiscrimination)
@@ -3427,6 +3437,9 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);
Opts.PointerAuthVTPtrTypeDiscrimination =
Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
+ Opts.PointerAuthTypeInfoVTPtrDiscrimination =
+ Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination);
+
Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini);
Opts.PointerAuthFunctionTypeDiscrimination =
Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination);
diff --git a/clang/test/CodeGenCXX/ptrauth-type-info-vtable.cpp b/clang/test/CodeGenCXX/ptrauth-type-info-vtable.cpp
new file mode 100644
index 0000000000000..d5f69e0485140
--- /dev/null
+++ b/clang/test/CodeGenCXX/ptrauth-type-info-vtable.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -DENABLE_TID=0 -I%S -std=c++11 -triple=arm64e-apple-darwin \
+// RUN: -fptrauth-calls -fptrauth-intrinsics \
+// RUN: -fptrauth-vtable-pointer-type-discrimination \
+// RUN: -fptrauth-vtable-pointer-address-discrimination \
+// RUN: %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,NODISC
+
+// RUN: %clang_cc1 -DENABLE_TID=1 -I%S -std=c++11 -triple=arm64e-apple-darwin \
+// RUN: -fptrauth-calls -fptrauth-intrinsics \
+// RUN: -fptrauth-vtable-pointer-type-discrimination \
+// RUN: -fptrauth-vtable-pointer-address-discrimination \
+// RUN: -fptrauth-type-info-vtable-pointer-discrimination \
+// RUN: %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,DISC
+
+// copied from typeinfo
+namespace std {
+
+#if __has_cpp_attribute(clang::ptrauth_vtable_pointer)
+# if __has_feature(ptrauth_type_info_vtable_pointer_discrimination)
+# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \
+ [[clang::ptrauth_vtable_pointer(process_independent, address_discrimination, type_discrimination)]]
+# else
+# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \
+ [[clang::ptrauth_vtable_pointer(process_independent, no_address_discrimination, no_extra_discrimination)]]
+# endif
+#else
+# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH
+#endif
+
+ class _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info
+ {
+ type_info& operator=(const type_info&);
+ type_info(const type_info&);
+
+ protected:
+ explicit type_info(const char* __n);
+
+ public:
+ virtual ~type_info();
+
+ virtual void test_method();
+ };
+} // namespace std
+
+static_assert(__has_feature(ptrauth_type_info_vtable_pointer_discrimination) == ENABLE_TID, "incorrect feature state");
+
+// CHECK: @disc_std_type_info = global i32 [[STDTYPEINFO_DISC:45546]]
+extern "C" int disc_std_type_info = __builtin_ptrauth_string_discriminator("_ZTVSt9type_info");
+
+// CHECK: @_ZTV10TestStruct = unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTI10TestStruct, ptr ptrauth (ptr @_ZN10TestStructD1Ev, i32 0, i64 52216, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV10TestStruct, i32 0, i32 0, i32 2)), ptr ptrauth (ptr @_ZN10TestStructD0Ev, i32 0, i64 39671, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV10TestStruct, i32 0, i32 0, i32 3))] }, align 8
+// CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr]
+// CHECK: @_ZTS10TestStruct = constant [13 x i8] c"10TestStruct\00", align 1
+
+// NODISC: @_ZTI10TestStruct = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr @_ZTS10TestStruct }, align 8
+
+// DISC: @_ZTI10TestStruct = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2, i64 [[STDTYPEINFO_DISC]]), ptr @_ZTS10TestStruct }, align 8
+
+struct TestStruct {
+ virtual ~TestStruct();
+ int a;
+};
+
+TestStruct::~TestStruct(){}
+
+extern "C" void test_vtable(std::type_info* t) {
+ t->test_method();
+}
+// NODISC: define void @test_vtable(ptr noundef %t)
+// NODISC: [[T_ADDR:%.*]] = alloca ptr, align 8
+// NODISC: store ptr %t, ptr [[T_ADDR]], align 8
+// NODISC: [[T:%.*]] = load ptr, ptr [[T_ADDR]], align 8
+// NODISC: [[VPTR:%.*]] = load ptr, ptr [[T]], align 8
+// NODISC: [[CAST_VPTR:%.*]] = ptrtoint ptr [[VPTR]] to i64
+// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[CAST_VPTR]], i32 2, i64 0)
+
+// DISC: define void @test_vtable(ptr noundef %t)
+// DISC: [[T_ADDR:%.*]] = alloca ptr, align 8
+// DISC: store ptr %t, ptr [[T_ADDR]], align 8
+// DISC: [[T:%.*]] = load ptr, ptr [[T_ADDR]], align 8
+// DISC: [[VPTR:%.*]] = load ptr, ptr [[T]], align 8
+// DISC: [[ADDR:%.*]] = ptrtoint ptr [[T]] to i64
+// DISC: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[ADDR]], i64 [[STDTYPEINFO_DISC]])
+// DISC: [[VPTRI:%.*]] = ptrtoint ptr [[VPTR]] to i64
+// DISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VPTRI]], i32 2, i64 [[DISCRIMINATOR]])
+
+extern "C" const void *ensure_typeinfo() {
+ return new TestStruct;
+}
|
…lvm#99726) We want to be able to support full type and address discrimination of type_info on targets that don't have existing ABI compatibility constraints. This patch does not enable such behavior on any platform, it just adds the necessary machinery. In clang we add a new commandline argument to control the type_info vtable ABI: -fptrauth-type-info-vtable-pointer-discrimination and a feature flag to allow source level detection of the ABI: __has_feature(ptrauth_type_info_vtable_pointer_discrimination) Co-authored-by: Oliver Hunt <oliver@apple.com>
Implement tests for the following PAuth-related features: - driver, preprocessor and ELF codegen tests for type_info vtable pointer discrimination llvm#99726; - driver, preprocessor, and ELF codegen (emitting function attributes) + sema (emitting errors) tests for indirect gotos signing llvm#97647; - ELF codegen tests for ubsan type checks + auth llvm#99590; - ELF codegen tests for constant global init with polymorphic MI llvm#99741; - ELF codegen tests for C++ member function pointers auth llvm#99576.
…100206) Implement tests for the following PAuth-related features: - driver, preprocessor and ELF codegen tests for type_info vtable pointer discrimination #99726; - driver, preprocessor, and ELF codegen (emitting function attributes) + sema (emitting errors) tests for indirect gotos signing #97647; - ELF codegen tests for ubsan type checks + auth #99590; - ELF codegen tests for constant global init with polymorphic MI #99741; - ELF codegen tests for C++ member function pointers auth #99576.
…99726) Summary: We want to be able to support full type and address discrimination of type_info on targets that don't have existing ABI compatibility constraints. This patch does not enable such behavior on any platform, it just adds the necessary machinery. In clang we add a new commandline argument to control the type_info vtable ABI: -fptrauth-type-info-vtable-pointer-discrimination and a feature flag to allow source level detection of the ABI: __has_feature(ptrauth_type_info_vtable_pointer_discrimination) Co-authored-by: Oliver Hunt <oliver@apple.com> Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251050
…100206) Summary: Implement tests for the following PAuth-related features: - driver, preprocessor and ELF codegen tests for type_info vtable pointer discrimination #99726; - driver, preprocessor, and ELF codegen (emitting function attributes) + sema (emitting errors) tests for indirect gotos signing #97647; - ELF codegen tests for ubsan type checks + auth #99590; - ELF codegen tests for constant global init with polymorphic MI #99741; - ELF codegen tests for C++ member function pointers auth #99576. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250599
…lvm#100206) Implement tests for the following PAuth-related features: - driver, preprocessor and ELF codegen tests for type_info vtable pointer discrimination llvm#99726; - driver, preprocessor, and ELF codegen (emitting function attributes) + sema (emitting errors) tests for indirect gotos signing llvm#97647; - ELF codegen tests for ubsan type checks + auth llvm#99590; - ELF codegen tests for constant global init with polymorphic MI llvm#99741; - ELF codegen tests for C++ member function pointers auth llvm#99576. (cherry picked from commit 70c6e79)
…lvm#100206) Implement tests for the following PAuth-related features: - driver, preprocessor and ELF codegen tests for type_info vtable pointer discrimination llvm#99726; - driver, preprocessor, and ELF codegen (emitting function attributes) + sema (emitting errors) tests for indirect gotos signing llvm#97647; - ELF codegen tests for ubsan type checks + auth llvm#99590; - ELF codegen tests for constant global init with polymorphic MI llvm#99741; - ELF codegen tests for C++ member function pointers auth llvm#99576. (cherry picked from commit 70c6e79)
@ahmedbougacha It looks like there is some missing codegen logic. Particularly, in
Here, I was able to fix that locally by just using a dummy Do you have some logic for this locally that you've not upstreamed yet? If yes, could you please open a PR adding that? If no, I'm happy to submit a PR with a fix described above by myself. Also tagging @asl |
|
||
// NODISC: @_ZTI10TestStruct = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr @_ZTS10TestStruct }, align 8 | ||
|
||
// DISC: @_ZTI10TestStruct = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2, i64 [[STDTYPEINFO_DISC]]), ptr @_ZTS10TestStruct }, align 8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ahmedbougacha Here, we have
ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2, i64 [[STDTYPEINFO_DISC]])
This has constant discriminator, but does not have address discrimination, while it should be enabled with -fptrauth-type-info-vtable-pointer-discrimination
. The correct output should be smth like (if we use a placeholder value ptr inttoptr (i64 1 to ptr)
as storage address)
ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2, i64 [[STDTYPEINFO_DISC]], ptr inttoptr (i64 1 to ptr))
The root cause is described in my previous comment #99726.
Submitted an issue #101716 describing incorrect behavior in terms of address discrimination (see also comments above) |
In llvm#99726, `-fptrauth-type-info-vtable-pointer-discrimination` was introduced, which is intended to enable type and address discrimination for type_info vtable pointers. However, some codegen logic for actually enabling address discrimination was missing. This patch addresses the issue. Fixes llvm#101716
In llvm#99726, `-fptrauth-type-info-vtable-pointer-discrimination` was introduced, which is intended to enable type and address discrimination for type_info vtable pointers. However, some codegen logic for actually enabling address discrimination was missing. This patch addresses the issue. Fixes llvm#101716
In #99726, `-fptrauth-type-info-vtable-pointer-discrimination` was introduced, which is intended to enable type and address discrimination for type_info vtable pointers. However, some codegen logic for actually enabling address discrimination was missing. This patch addresses the issue. Fixes #101716
…102199) In llvm#99726, `-fptrauth-type-info-vtable-pointer-discrimination` was introduced, which is intended to enable type and address discrimination for type_info vtable pointers. However, some codegen logic for actually enabling address discrimination was missing. This patch addresses the issue. Fixes llvm#101716
…102199) In llvm#99726, `-fptrauth-type-info-vtable-pointer-discrimination` was introduced, which is intended to enable type and address discrimination for type_info vtable pointers. However, some codegen logic for actually enabling address discrimination was missing. This patch addresses the issue. Fixes llvm#101716
We want to be able to support full type and address discrimination of type_info on targets that don't have existing ABI compatibility constraints.
This patch does not enable such behavior on any platform, it just adds the necessary machinery.
In clang we add a new commandline argument to control the type_info vtable ABI:
and a feature flag to allow source level detection of the ABI:
Co-authored-by: Oliver Hunt oliver@apple.com