Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d457935

Browse files
committed
arm64e: Don't authenticate a ptrauth-qualified pointer before it's
passed to @llvm.ptrauth.strip, @llvm.ptrauth.auth, or @llvm.ptrauth.resign rdar://problem/60393465
1 parent 2d1a67c commit d457935

File tree

2 files changed

+90
-2
lines changed

2 files changed

+90
-2
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

+26-2
Original file line numberDiff line numberDiff line change
@@ -3642,8 +3642,32 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
36423642
case Builtin::BI__builtin_ptrauth_strip: {
36433643
// Emit the arguments.
36443644
SmallVector<llvm::Value*, 5> args;
3645-
for (auto argExpr : E->arguments())
3646-
args.push_back(EmitScalarExpr(argExpr));
3645+
CallExpr::const_arg_iterator arg = E->arg_begin(), argEnd = E->arg_end();
3646+
3647+
// Don't authenticate a ptrauth-qualified pointer before it's passed to
3648+
// ptrauth_strip, ptrauth_auth, or ptrauth_resign.
3649+
switch (BuiltinID) {
3650+
default:
3651+
break;
3652+
case Builtin::BI__builtin_ptrauth_auth:
3653+
case Builtin::BI__builtin_ptrauth_auth_and_resign:
3654+
case Builtin::BI__builtin_ptrauth_strip:
3655+
if (auto *cast = dyn_cast<CastExpr>(*arg))
3656+
if (cast->getCastKind() == CK_LValueToRValue) {
3657+
const Expr *subExpr = cast->getSubExpr();
3658+
if (subExpr->getType().getPointerAuth()) {
3659+
LValue lv = EmitLValue(subExpr);
3660+
lv.getQuals().removePtrAuth();
3661+
args.push_back(
3662+
EmitLoadOfLValue(lv, subExpr->getExprLoc()).getScalarVal());
3663+
++arg;
3664+
}
3665+
}
3666+
break;
3667+
}
3668+
3669+
for (; arg != argEnd; ++arg)
3670+
args.push_back(EmitScalarExpr(*arg));
36473671

36483672
// Cast the value to intptr_t, saving its original type.
36493673
llvm::Type *origValueType = args[0]->getType();

clang/test/CodeGen/ptrauth-intrinsics.c

+64
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ void test_auth() {
1717
fnptr = __builtin_ptrauth_auth(fnptr, 0, ptr_discriminator);
1818
}
1919

20+
// CHECK-LABEL: define void @test_auth_ptrauth_qual(
21+
void test_auth_ptrauth_qual(int *a) {
22+
// CHECK: alloca i32*, align 8
23+
// CHECK: %[[VALUE:.*]] = alloca i32*, align 8
24+
25+
// CHECK: %[[V5:.*]] = phi i32* [ null, %{{.*}} ], [ {{.*}} ]
26+
// CHECK: store i32* %[[V5]], i32** %[[VALUE]], align 8
27+
// CHECK: %[[V6:.*]] = load i32*, i32** %[[VALUE]], align 8
28+
// CHECK: %[[V7:.*]] = ptrtoint i32* %[[V6]] to i64
29+
// CHECK: %[[V8:.*]] = call i64 @llvm.ptrauth.auth.i64(i64 %[[V7]], i32 1, i64 100)
30+
// CHECK: %[[V9:.*]] = inttoptr i64 %[[V8]] to i32*
31+
// CHECK: store i32* %[[V9]], i32** %{{.*}}, align 8
32+
int *__ptrauth(1, 0, 100) value = a;
33+
int *p = __builtin_ptrauth_auth(value, 1, 100);
34+
}
35+
2036
// CHECK-LABEL: define void @test_auth_peephole()
2137
void test_auth_peephole() {
2238
// CHECK: [[PTR:%.*]] = load void ()*, void ()** @fnptr,
@@ -37,6 +53,38 @@ void test_strip() {
3753
fnptr = __builtin_ptrauth_strip(fnptr, 0);
3854
}
3955

56+
// CHECK-LABEL: define void @test_strip_ptrauth_qual0(
57+
void test_strip_ptrauth_qual0(int *a) {
58+
// CHECK: alloca i32*, align 8
59+
// CHECK: %[[VALUE:.*]] = alloca i32*, align 8
60+
61+
// CHECK: %[[V5:.*]] = phi i32* [ null, %{{.*}} ], [ {{.*}} ]
62+
// CHECK: store i32* %[[V5]], i32** %[[VALUE]], align 8
63+
// CHECK: %[[V6:.*]] = load i32*, i32** %[[VALUE]], align 8
64+
// CHECK: %[[V7:.*]] = ptrtoint i32* %[[V6]] to i64
65+
// CHECK: %[[V8:.*]] = call i64 @llvm.ptrauth.strip.i64(i64 %[[V7]], i32 1)
66+
// CHECK: %[[V9:.*]] = inttoptr i64 %[[V8]] to i32*
67+
// CHECK: store i32* %[[V9]], i32** %{{.*}}, align 8
68+
int *__ptrauth(1, 0, 100) value = a;
69+
int *p = __builtin_ptrauth_strip(value, 1);
70+
}
71+
72+
// CHECK-LABEL: define void @test_strip_ptrauth_qual1(
73+
void test_strip_ptrauth_qual1(int *a) {
74+
// CHECK: alloca i32*, align 8
75+
// CHECK: %[[VALUE:.*]] = alloca i32*, align 8
76+
77+
// CHECK: %[[V5:.*]] = phi i32* [ null, %{{.*}} ], [ {{.*}} ]
78+
// CHECK: store i32* %[[V5]], i32** %[[VALUE]], align 8
79+
// CHECK: %[[V6:.*]] = load i32*, i32** %[[VALUE]], align 8
80+
// CHECK: %[[V7:.*]] = ptrtoint i32* %[[V6]] to i64
81+
// CHECK: %[[V8:.*]] = call i64 @llvm.ptrauth.strip.i64(i64 %[[V7]], i32 1)
82+
// CHECK: %[[V9:.*]] = inttoptr i64 %[[V8]] to i32*
83+
// CHECK: store i32* %[[V9]], i32** %{{.*}}, align 8
84+
int *__ptrauth(1, 0, 100) value = a;
85+
int *p = __builtin_ptrauth_strip(*((int **)&value), 1);
86+
}
87+
4088
// CHECK-LABEL: define void @test_sign_unauthenticated()
4189
void test_sign_unauthenticated() {
4290
// CHECK: [[PTR:%.*]] = load void ()*, void ()** @fnptr,
@@ -61,6 +109,22 @@ void test_auth_and_resign() {
61109
fnptr = __builtin_ptrauth_auth_and_resign(fnptr, 0, ptr_discriminator, 3, 15);
62110
}
63111

112+
// CHECK-LABEL:define void @test_auth_and_resign_ptrauth_qual(
113+
void test_auth_and_resign_ptrauth_qual(int *a) {
114+
// CHECK: alloca i32*, align 8
115+
// CHECK: %[[VALUE:.*]] = alloca i32*, align 8
116+
117+
// CHECK: %[[V5:.*]] = phi i32* [ null, %{{.*}} ], [ {{.*}} ]
118+
// CHECK: store i32* %[[V5]], i32** %[[VALUE]], align 8
119+
// CHECK: %[[V6:.*]] = load i32*, i32** %[[VALUE]], align 8
120+
// CHECK: %[[V7:.*]] = ptrtoint i32* %[[V6]] to i64
121+
// CHECK: %[[V8:.*]] = call i64 @llvm.ptrauth.resign.i64(i64 %[[V7]], i32 1, i64 100, i32 1, i64 200)
122+
// CHECK: %[[V9:.*]] = inttoptr i64 %[[V8]] to i32*
123+
// CHECK: store i32* %[[V9]], i32** %{{.*}}, align 8
124+
int *__ptrauth(1, 0, 100) value = a;
125+
int *p = __builtin_ptrauth_auth_and_resign(value, 1, 100, 1, 200);
126+
}
127+
64128
// CHECK-LABEL: define void @test_blend_discriminator()
65129
void test_blend_discriminator() {
66130
// CHECK: [[PTR:%.*]] = load void ()*, void ()** @fnptr,

0 commit comments

Comments
 (0)