Skip to content

Commit 52f3913

Browse files
committed
[PAC][InstCombine] Replace auth+sign with resign
Prevent introducing signing oracles by increasing the chances that pointer resign pattern is detected and kept as a single operation until it is expanded in AsmPrinter. With separate auth and sign intrinsics, it is possible that intermediate authenticated pointer is spilled to stack and reloaded before it is signed again, thus making it possible for the attacker to trick the PAC* instruction into signing an arbitrary pointer.
1 parent a447142 commit 52f3913

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3048,6 +3048,29 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
30483048
Intrinsic::getOrInsertDeclaration(II->getModule(), NewIntrin);
30493049
return CallInst::Create(NewFn, CallArgs);
30503050
}
3051+
case Intrinsic::ptrauth_sign: {
3052+
// auth + sign can be replaced with resign, which prevents unsafe
3053+
// spills and reloads of intermediate authenticated value.
3054+
Value *Ptr = II->getArgOperand(0);
3055+
Value *SignKey = II->getArgOperand(1);
3056+
Value *SignDisc = II->getArgOperand(2);
3057+
3058+
const auto *CI = dyn_cast<CallBase>(Ptr);
3059+
if (!CI || CI->getIntrinsicID() != Intrinsic::ptrauth_auth)
3060+
break;
3061+
3062+
Value *BasePtr = CI->getOperand(0);
3063+
Value *AuthKey = CI->getArgOperand(1);
3064+
Value *AuthDisc = CI->getArgOperand(2);
3065+
3066+
// Not replacing auth+sign using the same schema with nop, as auth+sign
3067+
// pair traps on authentication failure.
3068+
3069+
Function *NewFn = Intrinsic::getOrInsertDeclaration(
3070+
II->getModule(), Intrinsic::ptrauth_resign);
3071+
return CallInst::Create(NewFn,
3072+
{BasePtr, AuthKey, AuthDisc, SignKey, SignDisc});
3073+
}
30513074
case Intrinsic::arm_neon_vtbl1:
30523075
case Intrinsic::aarch64_neon_tbl1:
30533076
if (Value *V = simplifyNeonTbl1(*II, Builder))

llvm/test/Transforms/InstCombine/ptrauth-intrinsics.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,7 @@ define i64 @test_ptrauth_resign_ptrauth_constant(ptr %p) {
163163
define i64 @test_ptrauth_auth_sign_same_schema(ptr %p) {
164164
; CHECK-LABEL: @test_ptrauth_auth_sign_same_schema(
165165
; CHECK-NEXT: [[P_INT:%.*]] = ptrtoint ptr [[P:%.*]] to i64
166-
; CHECK-NEXT: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P_INT]], i32 1, i64 1234)
167-
; CHECK-NEXT: [[RESIGNED:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[AUTHED]], i32 1, i64 1234)
166+
; CHECK-NEXT: [[RESIGNED:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[P_INT]], i32 1, i64 1234, i32 1, i64 1234)
168167
; CHECK-NEXT: ret i64 [[RESIGNED]]
169168
;
170169
%p.int = ptrtoint ptr %p to i64
@@ -176,8 +175,7 @@ define i64 @test_ptrauth_auth_sign_same_schema(ptr %p) {
176175
define i64 @test_ptrauth_auth_sign_opaque_disc_same_schema(ptr %p, i64 %disc) {
177176
; CHECK-LABEL: @test_ptrauth_auth_sign_opaque_disc_same_schema(
178177
; CHECK-NEXT: [[P_INT:%.*]] = ptrtoint ptr [[P:%.*]] to i64
179-
; CHECK-NEXT: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P_INT]], i32 1, i64 [[DISC:%.*]])
180-
; CHECK-NEXT: [[RESIGNED:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[AUTHED]], i32 1, i64 [[DISC]])
178+
; CHECK-NEXT: [[RESIGNED:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[P_INT]], i32 1, i64 [[DISC:%.*]], i32 1, i64 [[DISC]])
181179
; CHECK-NEXT: ret i64 [[RESIGNED]]
182180
;
183181
%p.int = ptrtoint ptr %p to i64
@@ -189,8 +187,7 @@ define i64 @test_ptrauth_auth_sign_opaque_disc_same_schema(ptr %p, i64 %disc) {
189187
define i64 @test_ptrauth_auth_sign_different_disc(ptr %p, i64 %disc) {
190188
; CHECK-LABEL: @test_ptrauth_auth_sign_different_disc(
191189
; CHECK-NEXT: [[P_INT:%.*]] = ptrtoint ptr [[P:%.*]] to i64
192-
; CHECK-NEXT: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P_INT]], i32 1, i64 [[DISC:%.*]])
193-
; CHECK-NEXT: [[RESIGNED:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[AUTHED]], i32 1, i64 1234)
190+
; CHECK-NEXT: [[RESIGNED:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[P_INT]], i32 1, i64 [[DISC:%.*]], i32 1, i64 1234)
194191
; CHECK-NEXT: ret i64 [[RESIGNED]]
195192
;
196193
%p.int = ptrtoint ptr %p to i64
@@ -202,8 +199,7 @@ define i64 @test_ptrauth_auth_sign_different_disc(ptr %p, i64 %disc) {
202199
define i64 @test_ptrauth_auth_sign_different_key(ptr %p) {
203200
; CHECK-LABEL: @test_ptrauth_auth_sign_different_key(
204201
; CHECK-NEXT: [[P_INT:%.*]] = ptrtoint ptr [[P:%.*]] to i64
205-
; CHECK-NEXT: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[P_INT]], i32 0, i64 1234)
206-
; CHECK-NEXT: [[RESIGNED:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[AUTHED]], i32 1, i64 1234)
202+
; CHECK-NEXT: [[RESIGNED:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[P_INT]], i32 0, i64 1234, i32 1, i64 1234)
207203
; CHECK-NEXT: ret i64 [[RESIGNED]]
208204
;
209205
%p.int = ptrtoint ptr %p to i64

0 commit comments

Comments
 (0)