Skip to content

Commit 327760c

Browse files
committed
Generate begin_access [signed] when handling a field function pointer with __ptrauth qualifier
1 parent bc52efd commit 327760c

File tree

4 files changed

+70
-1
lines changed

4 files changed

+70
-1
lines changed

lib/SILGen/SILGenLValue.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,8 +853,17 @@ namespace {
853853
// TODO: if the base is +1, break apart its cleanup.
854854
auto Res = SGF.B.createStructElementAddr(loc, base.getValue(),
855855
Field, SubstFieldType);
856-
return ManagedValue::forLValue(Res);
856+
857+
if (!Field->getPointerAuthQualifier() ||
858+
!SGF.getOptions().EnableImportPtrauthFieldFunctionPointers) {
859+
return ManagedValue::forLValue(Res);
860+
}
861+
auto beginAccess =
862+
enterAccessScope(SGF, loc, base, Res, getTypeData(), getAccessKind(),
863+
SILAccessEnforcement::Signed, takeActorIsolation());
864+
return ManagedValue::forLValue(beginAccess);
857865
}
866+
858867
void dump(raw_ostream &OS, unsigned indent) const override {
859868
OS.indent(indent) << "StructElementComponent("
860869
<< Field->getName() << ")\n";

test/SILGen/Inputs/module.map

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module PointerAuth {
2+
header "ptrauth_field_fptr_import.h"
3+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef TEST_C_FUNCTION
2+
#define TEST_C_FUNCTION
3+
4+
struct SecureStruct {
5+
int (*__ptrauth(2, 0, 88)(secure_func_ptr1))();
6+
int (*__ptrauth(3, 0, 66)(secure_func_ptr2))();
7+
};
8+
9+
struct SecureStruct *ptr_to_secure_struct;
10+
#endif
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// RUN: %swift-frontend %s -enable-import-ptrauth-field-function-pointers -emit-silgen -target arm64e-apple-ios13.0 -I %S/Inputs/ 2>&1 | %FileCheck %s
2+
3+
import PointerAuth
4+
5+
// CHECK-LABEL: sil hidden [ossa] @$s25ptrauth_field_fptr_import05test_B8_fn_reads5Int32VyF :
6+
// CHECK: [[GLOB:%.*]] = global_addr @ptr_to_secure_struct : $*Optional<UnsafeMutablePointer<SecureStruct>>
7+
// CHECK: [[A1:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*Optional<UnsafeMutablePointer<SecureStruct>>
8+
// CHECK: [[LD1:%.*]] = load [trivial] [[A1]] : $*Optional<UnsafeMutablePointer<SecureStruct>>
9+
// CHECK: end_access [[A1]] : $*Optional<UnsafeMutablePointer<SecureStruct>>
10+
// CHECK: switch_enum [[LD1]] : $Optional<UnsafeMutablePointer<SecureStruct>>, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1
11+
// CHECK: bb2([[BBARG1:%.*]] : $UnsafeMutablePointer<SecureStruct>):
12+
// CHECK: [[F1:%.*]] = function_ref @$sSp7pointeexvlu : $@convention(method) <τ_0_0> (UnsafeMutablePointer<τ_0_0>) -> UnsafePointer<τ_0_0>
13+
// CHECK: [[PTR1:%.*]] = apply [[F1]]<SecureStruct>([[BBARG1]]) : $@convention(method) <τ_0_0> (UnsafeMutablePointer<τ_0_0>) -> UnsafePointer<τ_0_0>
14+
// CHECK: [[RAW1:%.*]] = struct_extract [[PTR1]] : $UnsafePointer<SecureStruct>, #UnsafePointer._rawValue
15+
// CHECK: [[ADDR1:%.*]] = pointer_to_address [[RAW1]] : $Builtin.RawPointer to [strict] $*SecureStruct
16+
// CHECK: [[A2:%.*]] = begin_access [read] [unsafe] [[ADDR1]] : $*SecureStruct
17+
// CHECK: [[ELEM1:%.*]] = struct_element_addr [[A2]] : $*SecureStruct, #SecureStruct.secure_func_ptr1
18+
// CHECK: [[ASIGNED:%.*]] = begin_access [read] [signed] [[ELEM1]] : $*Optional<@convention(c) () -> Int32>
19+
// CHECK: [[FPLOAD:%.*]] = load [trivial] [[ASIGNED]] : $*Optional<@convention(c) () -> Int32>
20+
// CHECK: end_access [[ASIGNED]] : $*Optional<@convention(c) () -> Int32>
21+
// CHECK: end_access [[A2]] : $*SecureStruct
22+
// CHECK: switch_enum [[FPLOAD]] : $Optional<@convention(c) () -> Int32>, case #Optional.some!enumelt: bb4, case #Optional.none!enumelt: bb3
23+
// CHECK-LABEL: } // end sil function '$s25ptrauth_field_fptr_import05test_B8_fn_reads5Int32VyF'
24+
func test_field_fn_read() -> Int32 {
25+
let fn = ptr_to_secure_struct!.pointee.secure_func_ptr1!
26+
return fn()
27+
}
28+
29+
// CHECK-LABEL: sil hidden [ossa] @$s25ptrauth_field_fptr_import05test_B12_fn_ptr_swapyyF :
30+
// CHECK:bb8([[UMP:%.*]] : $UnsafeMutablePointer<SecureStruct>):
31+
// CHECK: [[F1:%.*]] = function_ref @$sSp7pointeexvau : $@convention(method) <τ_0_0> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
32+
// CHECK: [[P:%.*]] = apply [[F1]]<SecureStruct>([[UMP]]) : $@convention(method) <τ_0_0> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
33+
// CHECK: [[EX1:%.*]] = struct_extract [[P]] : $UnsafeMutablePointer<SecureStruct>, #UnsafeMutablePointer._rawValue
34+
// CHECK: [[ADDR:%.*]] = pointer_to_address [[EX1]] : $Builtin.RawPointer to [strict] $*SecureStruct
35+
// CHECK: [[A1:%.*]] = begin_access [modify] [unsafe] [[ADDR]] : $*SecureStruct
36+
// CHECK: [[ELEM1:%.*]] = struct_element_addr [[A1]] : $*SecureStruct, #SecureStruct.secure_func_ptr2
37+
// CHECK: [[A2:%.*]] = begin_access [modify] [signed] [[ELEM1]] : $*Optional<@convention(c) () -> Int32>
38+
// CHECK: assign {{.*}} to [[A2]] : $*Optional<@convention(c) () -> Int32>
39+
// CHECK: end_access [[A2]] : $*Optional<@convention(c) () -> Int32>
40+
// CHECK: end_access [[A1]] : $*SecureStruct
41+
// CHECK-LABEL: } // end sil function '$s25ptrauth_field_fptr_import05test_B12_fn_ptr_swapyyF'
42+
func test_field_fn_ptr_swap() {
43+
let t = ptr_to_secure_struct!.pointee.secure_func_ptr1
44+
ptr_to_secure_struct!.pointee.secure_func_ptr1 = ptr_to_secure_struct!.pointee.secure_func_ptr2
45+
ptr_to_secure_struct!.pointee.secure_func_ptr2 = t
46+
}
47+

0 commit comments

Comments
 (0)