-
Notifications
You must be signed in to change notification settings - Fork 0
Discussion: atrosinenko/pauth-blend-removal #1
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
base: main
Are you sure you want to change the base?
Conversation
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.
Could you please explain why do we need this change?
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.
Sorry, this was merely a note to myself, I will file an issue / implement a fix and drop this change.
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.
Could you please explain why the behavior has changed?
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.
IIRC this test file uses an old form of "clang.arc.attachedcall"() operand bundle - this is probably unintentional. This test turned out to be affected by a change to the logic of auto-upgrading operand bundles.
| return Error::success(); | ||
| } | ||
|
|
||
| if (VTy.getMachineValueType() == MVT::Untyped) |
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.
Could you please explain why do we need this condition and which particular test case triggers it?
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.
Hmm, this is a fix for a rather obscure bug in TableGen that prevented me from defining ptrauth_bundle SDNode. I probably have to send this fix beforehand - maybe this is not even a bug, but an intended behavior - I would have to fix my SDNode definitions then.
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.
(link added to the description)
| ; CHECK-NEXT: call void %arg2() [ "ptrauth"(i64 42, i64 120) ] | ||
| call void %arg2() [ "ptrauth"(i64 42, i64 120) ] | ||
| ; CHECK-NOT: call void %ok() | ||
| call void %ok() [ "ptrauth"(i32 42, i64 120) ] ; OK |
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.
The first operand here and on the line below is i32 - is this considered OK? BTW, on the line 31 we have a similar situation with i32, but it's treated as an error there. Should we do the same here?
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.
"ptrauth"(i32, i64) is a correct old-style form of ptrauth bundles (because it has exactly two operands), which is auto-upgraded when the *.ll file is being read.
| ; CHECK-NEXT: call void %arg.ptr() [ "ptrauth"(i64 42, i64 120, i32 123) ] | ||
| call void %arg.ptr() [ "ptrauth"(i64 42, i64 120, i32 123) ] | ||
|
|
||
| ; Note that for compatibility reasons the first operand (originally, "the key ID") |
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.
Nit: when we have a major test update, it might be worth using ;; prefix for comments which are actual comments and not FileCheck directives.
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.
(link added to the description)
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.
Are there any pre-existing discussion I could look up to not to introduce yet another almost correct code style? :)
clang/lib/CodeGen/ItaniumCXXABI.cpp
Outdated
| auto *NonVirtualDiscriminator = | ||
| Builder.getInt64(AuthInfo.getIntDiscriminator()); | ||
| assert(!AuthInfo.getAddrDiscriminator()); | ||
| // FIXME This does not involve call to @llvm.ptrauth.blend(), but such |
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.
Could you please explain what do you particularly mean by "such usage of constant modifier is unsafe"?
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.
I assume that choosing the discriminator conditionally may be susceptible to unintentional spilling of intermediate values to the stack.
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.
(link added to the description)
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.
I investigated this a bit more and updated the FIXME. ItaniumCXXABI::EmitLoadOfMemberFunctionPointer returns a CGCallee result carrying both the (potentially signed) pointer to a function together with the schema to authenticate at the call site. Furthermore, EmitLoadOfMemberFunctionPointer is a virtual function. It is thus hardly possible to safely emit two separate authentications with hardcoded integer constants, as it would make things even worse by exposing a completely unprotected function pointer instead of the discriminator value. A better option would probably be re-signing the pointer to the same non-zero discriminator on the "FnVirtual" code path, but this requires further investigation not to introduce some other vulnerability.
| callee, args, allBundles, name); | ||
| call->setCallingConv(getRuntimeCC()); | ||
|
|
||
| // FIXME Attach "convergencectrl" bundle right away instead of re-creating |
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.
Could you please refer me to the tests which trigger this convergence-related condition?
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.
I tried adding an assertion that the result of cast<llvm::CallInst>(addConvergenceControlToken(call)) equals to call (which should fail on the condition mentioned in this FIXME), here is the list of tests:
Clang :: CodeGenHLSL/GlobalDestructors.hlsl
Clang :: CodeGenHLSL/builtins/GroupMemoryBarrierWithGroupSync.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveCountBits.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveMax.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveMin.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveSum.hlsl
Clang :: CodeGenHLSL/builtins/WaveReadLaneAt.hlsl
Clang :: CodeGenHLSL/builtins/wave_get_lane_count.hlsl
Clang :: CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl
Clang :: CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl
Clang :: CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl
Clang :: CodeGenHLSL/builtins/wave_is_first_lane.hlsl
Clang :: CodeGenHLSL/convergence/global_array.hlsl
Clang :: CodeGenHLSL/resources/RWBuffer-constructor-opt.hlsl
Clang :: CodeGenHLSL/resources/RWBuffer-imageformat.hlsl
Clang :: CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
Clang :: CodeGenHLSL/resources/StructuredBuffers-elementtype.hlsl
Clang :: CodeGenHLSL/resources/StructuredBuffers-subscripts.hlsl
Clang :: CodeGenHLSL/resources/TypedBuffers-elementtype.hlsl
Clang :: CodeGenHLSL/resources/TypedBuffers-subscript.hlsl
Clang :: CodeGenHLSL/resources/default_cbuffer.hlsl
Clang :: CodeGenHLSL/resources/res-array-global-multi-dim.hlsl
Clang :: CodeGenHLSL/resources/res-array-global-unbounded.hlsl
Clang :: CodeGenHLSL/resources/res-array-global.hlsl
Clang :: CodeGenHLSL/vk-features/vk.spec-constant.hlsl
Clang :: CodeGenHLSL/vk-input-builtin.hlsl
Clang :: CodeGenHLSL/vk_binding_attr.hlsl
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.
Do we expect existing tests like clang/test/Sema/ptrauth-intrinsics-macro.c now become failing with the same Standalone blend builtin is not supported error?
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.
Hmm, I thought I have updated all the tests as needed... I do expect that some code that was previously supported may be rejected now, but the in-tree tests are not expected to fail.
| @@ -0,0 +1,13 @@ | |||
| // RUN: %clang_cc1 -triple arm64-apple-ios -S -verify -fptrauth-intrinsics %s -fexperimental-new-constant-interpreter | |||
|
|
|||
| typedef __UINTPTR_TYPE__ uintptr_t; | |||
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.
Nit: why do we need this typedef?
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.
This typedef introduces a familiar platform-independent type name without the need to #include any headers.
clang/test/Sema/ptrauth-blend.c
Outdated
| @@ -0,0 +1,13 @@ | |||
| // RUN: %clang_cc1 -triple arm64-apple-ios -S -verify -fptrauth-intrinsics %s -fexperimental-new-constant-interpreter | |||
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.
Could you please explain which purpose does -fexperimental-new-constant-interpreter serve? I suppose that the error message should not be dependent on such flags and we should get the same result w/o the flag, shouldn't we?
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.
I'm not very familiar with state-of-the-art frontend testing, so this option was probably copied from a similar test file :)
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.
Dropped this option in 2c20897.
| const DataLayout &DL) const { | ||
| // If the keys are different, there's no chance for this to be compatible. | ||
| if (getKey() != Key) | ||
| // FIXME: Generalize ptrauth constants to arbitrary schemas instead of |
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.
It looks like that it's crucial to resolve this FIXME before presenting these changes for public discussion, isn't it?
If supporting arbitrary BundleOperands array is too challenging for some reason, I suppose we should at least not assume that we have always use the exact same meaning of int/address discriminators. So as for me, it might be OK to limit BundleOperands.size() (while leaving FIXME to support arbitrary size in future), but it does not look OK to treat specific operands as specific discriminator values with their AArch64-specific meaning.
Please let me know your thoughts on this.
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.
(link added to the description)
|
|
||
| ConstantPtrAuth *ConstantPtrAuth::get(Constant *Ptr, ConstantInt *Key, | ||
| ConstantInt *Disc, Constant *AddrDisc) { | ||
| // FIXME Should we simply enforce i64 instead? |
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.
Probably enforcing i64 is a good idea since it would make aarch64-specific ptrauth constants
BTW, is there a reason why ConstantPtrAuth is AArch64-specific or can we make it "generic" with arbitrary amount of i64 parameters as well? When we need to access that in AArch64-specific manner in code, we might just use some kind of wrapper which would ensure that we have expected amount of parameters in the constant and they fit expected width.
But I might be missing smth - would be glad if you could explain how you see the situation.
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.
I would rather make ConstantPtrAuth target-independent as well, but this requires further investigation. One of my concerns is whether binary encoding of IR constants is generic enough to transparently switch from a fixed structure of fields to generic tuples of i64.
(link added to the description)
atrosinenko
left a comment
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.
| callee, args, allBundles, name); | ||
| call->setCallingConv(getRuntimeCC()); | ||
|
|
||
| // FIXME Attach "convergencectrl" bundle right away instead of re-creating |
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.
I tried adding an assertion that the result of cast<llvm::CallInst>(addConvergenceControlToken(call)) equals to call (which should fail on the condition mentioned in this FIXME), here is the list of tests:
Clang :: CodeGenHLSL/GlobalDestructors.hlsl
Clang :: CodeGenHLSL/builtins/GroupMemoryBarrierWithGroupSync.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveCountBits.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveMax.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveMin.hlsl
Clang :: CodeGenHLSL/builtins/WaveActiveSum.hlsl
Clang :: CodeGenHLSL/builtins/WaveReadLaneAt.hlsl
Clang :: CodeGenHLSL/builtins/wave_get_lane_count.hlsl
Clang :: CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl
Clang :: CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl
Clang :: CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl
Clang :: CodeGenHLSL/builtins/wave_is_first_lane.hlsl
Clang :: CodeGenHLSL/convergence/global_array.hlsl
Clang :: CodeGenHLSL/resources/RWBuffer-constructor-opt.hlsl
Clang :: CodeGenHLSL/resources/RWBuffer-imageformat.hlsl
Clang :: CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
Clang :: CodeGenHLSL/resources/StructuredBuffers-elementtype.hlsl
Clang :: CodeGenHLSL/resources/StructuredBuffers-subscripts.hlsl
Clang :: CodeGenHLSL/resources/TypedBuffers-elementtype.hlsl
Clang :: CodeGenHLSL/resources/TypedBuffers-subscript.hlsl
Clang :: CodeGenHLSL/resources/default_cbuffer.hlsl
Clang :: CodeGenHLSL/resources/res-array-global-multi-dim.hlsl
Clang :: CodeGenHLSL/resources/res-array-global-unbounded.hlsl
Clang :: CodeGenHLSL/resources/res-array-global.hlsl
Clang :: CodeGenHLSL/vk-features/vk.spec-constant.hlsl
Clang :: CodeGenHLSL/vk-input-builtin.hlsl
Clang :: CodeGenHLSL/vk_binding_attr.hlsl
| unsigned IsIsaPointer : 1; | ||
| unsigned AuthenticatesNullValues : 1; | ||
| unsigned Key : 2; | ||
| unsigned IntDiscriminator : 16; |
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.
Fixed IntDiscriminator crossing the byte boundary in 2c20897
| } | ||
| } else { | ||
| VTable = cast<llvm::Instruction>(EmitPointerAuthAuth( | ||
| CGPointerAuthInfo(0, PointerAuthenticationMode::Strip, false, false, |
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.
(link added to the description)
| /// Given a pointer-authentication schema, return a concrete "other" | ||
| /// discriminator for it. | ||
| llvm::ConstantInt *CodeGenModule::getPointerAuthOtherDiscriminator( | ||
| unsigned CodeGenModule::getPointerAuthOtherDiscriminator( |
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.
(link added to the description)
clang/lib/CodeGen/ItaniumCXXABI.cpp
Outdated
| auto *NonVirtualDiscriminator = | ||
| Builder.getInt64(AuthInfo.getIntDiscriminator()); | ||
| assert(!AuthInfo.getAddrDiscriminator()); | ||
| // FIXME This does not involve call to @llvm.ptrauth.blend(), but such |
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.
(link added to the description)
| ; CHECK-NEXT: braaz x16 | ||
| define i32 @test_tailcall_ia_0(ptr %arg0) #0 { | ||
| %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 0, i64 0) ] | ||
| define i32 @test_tailcall_ia_0(i32 ()* %arg0) #0 { |
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.
Unintentionally rolled back the conversion to untyped pointers. Fixed in 2c20897.
|
|
||
| declare ptr @foo0(i32) | ||
| declare ptr @foo1() | ||
| declare i8* @foo0(i32) |
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.
Fixed in 2c20897.
| call void %ok() [ "ptrauth"(i32 42, i64 120) ] ; OK | ||
| call void %ok() [ "ptrauth"(i32 42, i64 %arg.64) ] ; OK | ||
| call void %ok() [ "ptrauth"(i64 %arg.64, i64 123) ] ; OK | ||
| call void %ok() [ "ptrauth"(i64 %arg.64, i64 123, i64 %arg.64, i64 42) ] ; OK |
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.
(link added to the description)
| ; CHECK-NEXT: call void %arg.ptr() [ "ptrauth"(i64 42, i64 120, i32 123) ] | ||
| call void %arg.ptr() [ "ptrauth"(i64 42, i64 120, i32 123) ] | ||
|
|
||
| ; Note that for compatibility reasons the first operand (originally, "the key ID") |
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.
(link added to the description)
| return Error::success(); | ||
| } | ||
|
|
||
| if (VTy.getMachineValueType() == MVT::Untyped) |
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.
(link added to the description)
5a97aa4 to
a2dc74c
Compare
|
@kovdan01 The above force-push reorganized the commit history without changing the file tree (i.e. output of |
* Three-operand bundle always implies blend (OK) * Two-operand bundle has three modes: - immediate integer only (OK) - raw value (OK) - result of llvm.ptrauth.blend (compatibility, will be removed later) At ISel time this means PtrAuthInfo-style structs are converted from Key+Discr to homogenous vectors of `Register`s or `SDValue`s with the second operation mode added at the instruction legalization site.
Always use three-operand bundles for simplicity (except for ptrauth.strip). Change operand order from (key, addr, int) to (key, int, addr) to reflect operand order of ptrauth constants. More cleanup.
a2dc74c to
f84201d
Compare
|
Rebased onto current mainline. This branch turned out to conflict with a recently merged deactivation symbols implementation: llvm@6227eb9. By the way, that commit seems to implement |
260894f to
31f049f
Compare
Here is a list of open questions, in case corresponding comments disappear as a result of rebase:
PointerAuthenticationMode::SignAndStripis not used at all..."CodeGenModule::getPointerAuthOtherDiscriminatorshould returnunsignedoruint16_t(the same question applies to its callees).ConstantPtrAuthto an arbitrary tuple ofi64parameters.ptrauthbundles are rejected by the backend