Skip to content

Commit 134603e

Browse files
kovdan01ahmedbougachaatrosinenko
committed
[PAC] Sign LR with B key for non-leaf functions with "ptrauth-returns" attr
For pauthtest ABI and arm64e, there is a bunch of ptrauth-* options, including ptrauth-returns. Use "ptrauth-returns" function attribute to indicate need for LR signing with B key for non-leaf function to avoid using "sign-return-address" and "sign-return-address-key" which were originally designed for pac-ret. Co-authored-by: Ahmed Bougacha <[email protected]> Co-authored-by: Anatoly Trosinenko <[email protected]>
1 parent 3f6eb13 commit 134603e

File tree

7 files changed

+416
-5
lines changed

7 files changed

+416
-5
lines changed

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8340,7 +8340,8 @@ AArch64InstrInfo::getOutliningCandidateInfo(
83408340
NumBytesToCreateFrame += 8;
83418341

83428342
// PAuth is enabled - set extra tail call cost, if any.
8343-
auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod();
8343+
auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
8344+
*RepeatedSequenceLocs[0].getMF());
83448345
NumBytesToCheckLRInTCEpilogue =
83458346
AArch64PAuth::getCheckerSizeInBytes(LRCheckMethod);
83468347
// Checking the authenticated LR value may significantly impact
@@ -8701,6 +8702,10 @@ void AArch64InstrInfo::mergeOutliningCandidateAttributes(
87018702
// behaviour of one of them
87028703
const auto &CFn = Candidates.front().getMF()->getFunction();
87038704

8705+
if (CFn.hasFnAttribute("ptrauth-returns"))
8706+
F.addFnAttr(CFn.getFnAttribute("ptrauth-returns"));
8707+
if (CFn.hasFnAttribute("ptrauth-auth-traps"))
8708+
F.addFnAttr(CFn.getFnAttribute("ptrauth-auth-traps"));
87048709
// Since all candidates belong to the same module, just copy the
87058710
// function-level attributes of an arbitrary function.
87068711
if (CFn.hasFnAttribute("sign-return-address"))

llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ void AArch64FunctionInfo::initializeBaseYamlFields(
3838
}
3939

4040
static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
41+
if (F.hasFnAttribute("ptrauth-returns"))
42+
return {true, false}; // non-leaf
4143
// The function should be signed in the following situations:
4244
// - sign-return-address=all
4345
// - sign-return-address=non-leaf and the functions spills the LR
@@ -56,6 +58,8 @@ static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
5658
}
5759

5860
static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) {
61+
if (F.hasFnAttribute("ptrauth-returns"))
62+
return true;
5963
if (!F.hasFnAttribute("sign-return-address-key")) {
6064
if (STI.getTargetTriple().isOSWindows())
6165
return true;

llvm/lib/Target/AArch64/AArch64PointerAuth.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ bool AArch64PointerAuth::checkAuthenticatedLR(
341341
AArch64PACKey::ID KeyId =
342342
MFnI->shouldSignWithBKey() ? AArch64PACKey::IB : AArch64PACKey::IA;
343343

344-
AuthCheckMethod Method = Subtarget->getAuthenticatedLRCheckMethod();
344+
AuthCheckMethod Method =
345+
Subtarget->getAuthenticatedLRCheckMethod(*TI->getMF());
345346

346347
if (Method == AuthCheckMethod::None)
347348
return false;

llvm/lib/Target/AArch64/AArch64Subtarget.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,8 +565,11 @@ bool AArch64Subtarget::useAA() const { return UseAA; }
565565
// exception on its own. Later, if the callee spills the signed LR value and
566566
// neither FEAT_PAuth2 nor FEAT_EPAC are implemented, the valid PAC replaces
567567
// the higher bits of LR thus hiding the authentication failure.
568-
AArch64PAuth::AuthCheckMethod
569-
AArch64Subtarget::getAuthenticatedLRCheckMethod() const {
568+
AArch64PAuth::AuthCheckMethod AArch64Subtarget::getAuthenticatedLRCheckMethod(
569+
const MachineFunction &MF) const {
570+
if (MF.getFunction().hasFnAttribute("ptrauth-returns") &&
571+
MF.getFunction().hasFnAttribute("ptrauth-auth-traps"))
572+
return AArch64PAuth::AuthCheckMethod::HighBitsNoTBI;
570573
if (AuthenticatedLRCheckMethod.getNumOccurrences())
571574
return AuthenticatedLRCheckMethod;
572575

llvm/lib/Target/AArch64/AArch64Subtarget.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,8 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
413413
}
414414

415415
/// Choose a method of checking LR before performing a tail call.
416-
AArch64PAuth::AuthCheckMethod getAuthenticatedLRCheckMethod() const;
416+
AArch64PAuth::AuthCheckMethod
417+
getAuthenticatedLRCheckMethod(const MachineFunction &MF) const;
417418

418419
/// Compute the integer discriminator for a given BlockAddress constant, if
419420
/// blockaddress signing is enabled, or std::nullopt otherwise.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
; RUN: llc -mtriple arm64e-apple-darwin -asm-verbose=false -disable-post-ra -o - %s | \
2+
; RUN: FileCheck %s --check-prefixes=CHECK,DARWIN
3+
; RUN: llc -mtriple aarch64-linux-gnu -mattr=+pauth -asm-verbose=false -disable-post-ra -o - %s | \
4+
; RUN: FileCheck %s --check-prefixes=CHECK,ELF
5+
6+
; CHECK-LABEL: test_tailcall:
7+
; CHECK-NEXT: pacibsp
8+
; DARWIN-NEXT: stp x29, x30, [sp, #-16]!
9+
; ELF-NEXT: str x30, [sp, #-16]!
10+
; DARWIN-NEXT: bl _bar
11+
; ELF-NEXT: bl bar
12+
; DARWIN-NEXT: ldp x29, x30, [sp], #16
13+
; ELF-NEXT: ldr x30, [sp], #16
14+
; CHECK-NEXT: autibsp
15+
; CHECK-NEXT: eor x16, x30, x30, lsl #1
16+
; DARWIN-NEXT: tbnz x16, #62, [[BAD:L.*]]
17+
; ELF-NEXT: tbnz x16, #62, [[BAD:.L.*]]
18+
; DARWIN-NEXT: b _bar
19+
; ELF-NEXT: b bar
20+
; CHECK-NEXT: [[BAD]]:
21+
; CHECK-NEXT: brk #0xc471
22+
define i32 @test_tailcall() #0 {
23+
call i32 @bar()
24+
%c = tail call i32 @bar()
25+
ret i32 %c
26+
}
27+
28+
; CHECK-LABEL: test_tailcall_noframe:
29+
; DARWIN-NEXT: b _bar
30+
; ELF-NEXT: b bar
31+
define i32 @test_tailcall_noframe() #0 {
32+
%c = tail call i32 @bar()
33+
ret i32 %c
34+
}
35+
36+
; CHECK-LABEL: test_tailcall_indirect:
37+
; CHECK: autibsp
38+
; CHECK: eor x16, x30, x30, lsl #1
39+
; DARWIN: tbnz x16, #62, [[BAD:L.*]]
40+
; ELF: tbnz x16, #62, [[BAD:.L.*]]
41+
; CHECK: br x0
42+
; CHECK: [[BAD]]:
43+
; CHECK: brk #0xc471
44+
define void @test_tailcall_indirect(ptr %fptr) #0 {
45+
call i32 @test_tailcall()
46+
tail call void %fptr()
47+
ret void
48+
}
49+
50+
; CHECK-LABEL: test_tailcall_indirect_in_x9:
51+
; CHECK: autibsp
52+
; CHECK: eor x16, x30, x30, lsl #1
53+
; DARWIN: tbnz x16, #62, [[BAD:L.*]]
54+
; ELF: tbnz x16, #62, [[BAD:.L.*]]
55+
; CHECK: br x9
56+
; CHECK: [[BAD]]:
57+
; CHECK: brk #0xc471
58+
define void @test_tailcall_indirect_in_x9(ptr sret(i64) %ret, [8 x i64] %in, ptr %fptr) #0 {
59+
%ptr = alloca i8, i32 16
60+
call i32 @test_tailcall()
61+
tail call void %fptr(ptr sret(i64) %ret, [8 x i64] %in)
62+
ret void
63+
}
64+
65+
; CHECK-LABEL: test_auth_tailcall_indirect:
66+
; CHECK: autibsp
67+
; CHECK: eor x16, x30, x30, lsl #1
68+
; DARWIN: tbnz x16, #62, [[BAD:L.*]]
69+
; ELF: tbnz x16, #62, [[BAD:.L.*]]
70+
; CHECK: mov x16, #42
71+
; CHECK: braa x0, x16
72+
; CHECK: [[BAD]]:
73+
; CHECK: brk #0xc471
74+
define void @test_auth_tailcall_indirect(ptr %fptr) #0 {
75+
call i32 @test_tailcall()
76+
tail call void %fptr() [ "ptrauth"(i32 0, i64 42) ]
77+
ret void
78+
}
79+
80+
; CHECK-LABEL: test_auth_tailcall_indirect_in_x9:
81+
; CHECK: autibsp
82+
; CHECK: eor x16, x30, x30, lsl #1
83+
; DARWIN: tbnz x16, #62, [[BAD:L.*]]
84+
; ELF: tbnz x16, #62, [[BAD:.L.*]]
85+
; CHECK: brabz x9
86+
; CHECK: [[BAD]]:
87+
; CHECK: brk #0xc471
88+
define void @test_auth_tailcall_indirect_in_x9(ptr sret(i64) %ret, [8 x i64] %in, ptr %fptr) #0 {
89+
%ptr = alloca i8, i32 16
90+
call i32 @test_tailcall()
91+
tail call void %fptr(ptr sret(i64) %ret, [8 x i64] %in) [ "ptrauth"(i32 1, i64 0) ]
92+
ret void
93+
}
94+
95+
; CHECK-LABEL: test_auth_tailcall_indirect_bti:
96+
; CHECK: autibsp
97+
; CHECK: eor x17, x30, x30, lsl #1
98+
; DARWIN: tbnz x17, #62, [[BAD:L.*]]
99+
; ELF: tbnz x17, #62, [[BAD:.L.*]]
100+
; CHECK: brabz x16
101+
; CHECK: [[BAD]]:
102+
; CHECK: brk #0xc471
103+
define void @test_auth_tailcall_indirect_bti(ptr sret(i64) %ret, [8 x i64] %in, ptr %fptr) #0 "branch-target-enforcement"="true" {
104+
%ptr = alloca i8, i32 16
105+
call i32 @test_tailcall()
106+
tail call void %fptr(ptr sret(i64) %ret, [8 x i64] %in) [ "ptrauth"(i32 1, i64 0) ]
107+
ret void
108+
}
109+
110+
declare i32 @bar()
111+
112+
attributes #0 = { nounwind "ptrauth-returns" "ptrauth-auth-traps" }

0 commit comments

Comments
 (0)