Skip to content

Commit 8e11ea8

Browse files
committed
[PAC] Function pointer type discrimination tests
And update to the main pauthtest document: * list new tests * remove the need for patching `libc` as the changes to it already went in. Unfortunately `cc-rs` is held back by `compiler/rustc_llvm/Cargo.toml` which pins to an old version: `cc = "=1.2.16"`
1 parent c926f3d commit 8e11ea8

22 files changed

Lines changed: 2753 additions & 24 deletions

src/doc/rustc/src/platform-support/aarch64-unknown-linux-pauthtest.md

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -109,29 +109,18 @@ Clang-based toolchain. In this case, no wrapper script is required,
109109

110110
Introduction of `aarch64-unknown-linux-pauthtest` target needs to be propagated
111111
to various crates/repos, so that they can correctly recognise and handle it.
112-
Specifically:
112+
At the time of writing this document the following requires patching:
113113
* `cc-rs`: https://github.com/jchlanda/cc-rs/tree/jakub/cc-v1.2.28-pauthtest
114-
* `libc`: https://github.com/jchlanda/libc/tree/jakub/0.2.183-pauthtest
115114
* `backtrace`: https://github.com/jchlanda/backtrace-rs/tree/jakub/backtrace-v0.3.76-pauthtest
116115

117-
The patched versions of `cc-rs` and `libc` will have to be registered through
118-
`[patch.crates-io]` section of `Cargo.toml` files both in:
119-
`<rust_root>/src/bootstrap/` and `<rust_root>/library/`. Check out `cc-rs` and
120-
`libc` to `<rust_root>/patches` and update config files. See attached diff for
121-
details:
116+
The patched versions of `cc-rs` will have to be registered through
117+
`[patch.crates-io]` section of `Cargo.toml` file in:
118+
`<rust_root>/src/bootstrap/`. Check out `cc-rs` to `<rust_root>/patches` and
119+
update config file. See attached diff for details:
122120

123121
<details>
124122

125123
```diff
126-
diff --git a/library/Cargo.toml b/library/Cargo.toml
127-
index e30e6240942..fb5a12f0065 100644
128-
--- a/library/Cargo.toml
129-
+++ b/library/Cargo.toml
130-
@@ -59,3 +59,4 @@ rustflags = ["-Cpanic=abort"]
131-
rustc-std-workspace-core = { path = 'rustc-std-workspace-core' }
132-
rustc-std-workspace-alloc = { path = 'rustc-std-workspace-alloc' }
133-
rustc-std-workspace-std = { path = 'rustc-std-workspace-std' }
134-
+libc = { path = '<rust_root>/patches/libc' }
135124
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
136125
index e1725db60cf..46763cdf9a4 100644
137126
--- a/src/bootstrap/Cargo.toml
@@ -147,7 +136,7 @@ index e1725db60cf..46763cdf9a4 100644
147136

148137
</details>
149138

150-
In contrast to `cc-rs` and `libc`, which are external crates resolved from
139+
In contrast to `cc-rs`, which is an external crate resolved from
151140
[crates.io](https://crates.io/) and can be overridden using `[patch.crates-io]`,
152141
`backtrace` is included in the Rust repository as a git submodule under
153142
`<rust_root>/library/backtrace`. At the time of writing, the necessary change
@@ -464,6 +453,19 @@ The following categories are supported (all present in tree):
464453
* pauth-extern-weak-global.rs
465454
* pauth-init-fini.rs
466455
* pauth-attr-special-funcs.rs
456+
* pauth-fn-ptr-type-discrimination-deeply-nested.rs
457+
* pauth-fn-ptr-type-discrimination-encoder.rs
458+
* pauth-fn-ptr-type-discrimination-fn-ptr-return-type.rs
459+
* pauth-fn-ptr-type-discrimination-option-callback.rs
460+
* pauth-fn-ptr-type-discrimination-option-return.rs
461+
* pauth-fn-ptr-type-discrimination-option.rs
462+
* pauth-fn-ptr-type-discrimination-recursive-statics.rs
463+
* pauth-fn-ptr-type-discrimination-running-test.rs
464+
* pauth-fn-ptr-type-discrimination-rust-array.rs
465+
* pauth-fn-ptr-type-discrimination-simd.rs
466+
* pauth-fn-ptr-type-discrimination-struct-members.rs
467+
* pauth-fn-ptr-type-discrimination-struct-name.rs
468+
* pauth-drop-terminator (implemented in run-make)
467469
* End-to-end execution tests
468470
* Rust-driven quicksort (pauth-quicksort-rust-driver)
469471
* C-driven quicksort (pauth-quicksort-c-driver)
@@ -472,7 +474,6 @@ The following categories are supported (all present in tree):
472474
* pauth-static-link-warning
473475
* enable_pointer_authentication_validation.rs
474476
* invalid_target_pointer_authentication.rs
475-
* type_discrimination_not_supported_pointer_authentication.rs
476477
* incompatible_pauth.rs
477478
* Unit tests for siphash function:
478479
* compiler/rustc_middle/src/ptrauth/llvm_siphash/tests.rs
@@ -495,13 +496,25 @@ x.py test --target aarch64-unknown-linux-pauthtest --force-rerun assembly-llvm \
495496
tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs \
496497
tests/codegen-llvm/pauth/pauth-extern-weak-global.rs \
497498
tests/codegen-llvm/pauth/pauth-init-fini.rs \
499+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-deeply-nested.rs \
500+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-encoder.rs \
501+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-fn-ptr-return-type.rs \
502+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-option-callback.rs \
503+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-option-return.rs \
504+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-option.rs \
505+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-recursive-statics.rs \
506+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-running-test.rs \
507+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-rust-array.rs \
508+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-simd.rs \
509+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-struct-members.rs \
510+
tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-struct-name.rs \
498511
tests/run-make/pauth-quicksort-rust-driver \
499512
tests/run-make/pauth-quicksort-c-driver \
500513
tests/run-make/pauth-static-link-warning \
514+
tests/run-make/pauth-drop-terminator \
501515
tests/ui/statics/crt-static-pauthtest.rs \
502516
tests/ui/pointer_authentication/enable_pointer_authentication_validation.rs \
503517
tests/ui/pointer_authentication/invalid_target_pointer_authentication.rs \
504-
tests/ui/pointer_authentication/type_discrimination_not_supported_pointer_authentication.rs \
505518
tests/ui/target_modifiers/incompatible_pauth.rs
506519
```
507520

tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88

99
use std::panic;
1010

11-
// CHECK: define {{.*}} @__rust_try{{.*}} [[ATTR_TRY:#[0-9]+]]
11+
// Make sure that `rust_eh_personality` is not signed.
12+
// CHECK: define internal i32 @{{.*}}lang_start{{.*}}pauth_attr_special_funcs(ptr %{{.*}}) unnamed_addr #[[#]] personality ptr @rust_eh_personality
13+
14+
// CHECK: define {{.*}} @__rust_try{{.*}} [[ATTR_TRY:#[0-9]+]] personality ptr @rust_eh_personality {
1215
// CHECK: define {{.*}} @main{{.*}} [[ATTR_MAIN:#[0-9]+]]
1316

1417
// CHECK: attributes [[ATTR_TRY]] = { {{.*}}"aarch64-jump-table-hardening"

tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
// ignore-tidy-file-linelength
12
//@ add-minicore
2-
// ignore-tidy-linelength
33
//@ only-pauthtest
44
//@ revisions: O0_PAUTH O3_PAUTH
55

tests/codegen-llvm/pauth/pauth-extern-weak-global.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ignore-tidy-linelength
1+
// ignore-tidy-file-linelength
22
//@ only-pauthtest
33
//@ revisions: O0_PAUTH O3_PAUTH O0_NO_PAUTH O3_NO_PAUTH
44
//@ add-minicore
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// ignore-tidy-file-linelength
2+
//@ add-minicore
3+
//@ only-pauthtest
4+
// Run it at O0, so that the compiler doesn't optimise the calls away.
5+
//@ revisions: DISC NO_DISC
6+
7+
//@ [DISC] needs-llvm-components: aarch64
8+
//@ [DISC] compile-flags: --target=aarch64-unknown-linux-pauthtest --crate-type=lib -Zpointer-authentication=+function-pointer-type-discrimination -C opt-level=0
9+
//@ [NO_DISC] needs-llvm-components: aarch64
10+
//@ [NO_DISC] compile-flags: --target=aarch64-unknown-linux-pauthtest --crate-type=lib -Zpointer-authentication=-function-pointer-type-discrimination -C opt-level=0
11+
12+
// Test generation of function-pointer type discriminators. The discriminator values were obtained
13+
// from Clang by compiling equivalent C code (included). Both compilers must generate identical
14+
// values.
15+
//
16+
// Make sure that the compiler can see through chains of nested structs, both when used as globals,
17+
// arguments and returns.
18+
//
19+
// Equivalent C:
20+
//
21+
// #include <stdio.h>
22+
//
23+
// typedef int (*L0)(int);
24+
// typedef int (*L1)(L0);
25+
// typedef int (*L2)(L1);
26+
// typedef int (*L3)(L2);
27+
// typedef int (*L4)(L3);
28+
// typedef L0 (*DeepRet)(void);
29+
//
30+
// int callback_i32(int x) { return x + 1; }
31+
//
32+
// int dummy_l1(L0 cb) { return cb(5); }
33+
// int dummy_l2(L1 cb) { return cb(callback_i32); }
34+
// int dummy_l3(L2 cb) { return cb(dummy_l1); }
35+
// int dummy_l4(L3 cb) { return cb(dummy_l2); }
36+
//
37+
// L0 returned_fn(void) { return callback_i32; }
38+
//
39+
// DeepRet f_deep(L4 cb) {
40+
// cb(dummy_l3);
41+
// return returned_fn;
42+
// }
43+
//
44+
// DeepRet (*T_DEEP)(L4) = f_deep;
45+
//
46+
// int main(void) {
47+
// DeepRet ret_fn;
48+
// L0 inner_fn;
49+
// int result;
50+
//
51+
// ret_fn = T_DEEP(dummy_l4);
52+
// inner_fn = ret_fn();
53+
// result = inner_fn(42);
54+
//
55+
// printf("result = %d\n", result);
56+
//
57+
// return 0;
58+
// }
59+
60+
#![feature(no_core, lang_items)]
61+
#![no_std]
62+
#![no_core]
63+
#![crate_type = "lib"]
64+
extern crate minicore;
65+
use minicore::hint::black_box;
66+
67+
// Nested fn ptr chain.
68+
type L0 = extern "C" fn(i32) -> i32;
69+
type L1 = extern "C" fn(L0) -> i32;
70+
type L2 = extern "C" fn(L1) -> i32;
71+
type L3 = extern "C" fn(L2) -> i32;
72+
type L4 = extern "C" fn(L3) -> i32;
73+
// Function returning fn ptr.
74+
type DeepRet = extern "C" fn() -> L0;
75+
76+
#[used]
77+
// DISC: @{{.*}}T_DEEP = constant ptr ptrauth (ptr @{{.*}}f_deep, i32 0, i64 1059), align 8
78+
// NO_DISC: @{{.*}}T_DEEP = constant ptr ptrauth (ptr @{{.*}}f_deep, i32 0), align 8
79+
static T_DEEP: unsafe extern "C" fn(L4) -> DeepRet = f_deep;
80+
81+
// Leaf callback.
82+
// CHECK-LABEL: callback_i32
83+
pub extern "C" fn callback_i32(x: i32) -> i32 {
84+
x
85+
}
86+
87+
// Dummy chain impl.
88+
// CHECK-LABEL: dummy_l1
89+
// CHECK: (ptr [[CB:%.*]])
90+
pub extern "C" fn dummy_l1(cb: L0) -> i32 {
91+
// DISC: call i32 [[CB]](i32 5) {{.*}} [ "ptrauth"(i32 0, i64 2981) ]
92+
// NO_DISC: call i32 [[CB]](i32 5) {{.*}} [ "ptrauth"(i32 0, i64 0) ]
93+
cb(5)
94+
}
95+
// CHECK-LABEL: dummy_l2
96+
// CHECK: (ptr [[CB:%.*]])
97+
pub extern "C" fn dummy_l2(cb: L1) -> i32 {
98+
// DISC: call i32 [[CB]](ptr ptrauth (ptr @{{.*}}callback_i32, i32 0, i64 2981)) {{.*}} [ "ptrauth"(i32 0, i64 12410) ]
99+
// NO_DISC: call i32 [[CB]](ptr ptrauth (ptr @{{.*}}callback_i32, i32 0)) {{.*}} [ "ptrauth"(i32 0, i64 0) ]
100+
cb(callback_i32)
101+
}
102+
// CHECK-LABEL: dummy_l3
103+
// CHECK: (ptr [[CB:%.*]])
104+
pub extern "C" fn dummy_l3(cb: L2) -> i32 {
105+
// DISC: call i32 [[CB]](ptr ptrauth (ptr @{{.*}}dummy_l1, i32 0, i64 12410)) {{.*}} [ "ptrauth"(i32 0, i64 12410) ]
106+
// NO_DISC: call i32 [[CB]](ptr ptrauth (ptr @{{.*}}dummy_l1, i32 0)) {{.*}} [ "ptrauth"(i32 0, i64 0) ]
107+
cb(dummy_l1)
108+
}
109+
// CHECK-LABEL: dummy_l4
110+
// CHECK: (ptr [[CB:%.*]])
111+
pub extern "C" fn dummy_l4(cb: L3) -> i32 {
112+
// DISC: call i32 [[CB]](ptr ptrauth (ptr @{{.*}}dummy_l2, i32 0, i64 12410)) {{.*}} [ "ptrauth"(i32 0, i64 12410) ]
113+
// NO_DISC: call i32 [[CB]](ptr ptrauth (ptr @{{.*}}dummy_l2, i32 0)) {{.*}} [ "ptrauth"(i32 0, i64 0) ]
114+
cb(dummy_l2)
115+
}
116+
// Return fn impl.
117+
// CHECK-LABEL: returned_fn
118+
pub extern "C" fn returned_fn() -> L0 {
119+
// DISC: ret ptr ptrauth (ptr @{{.*}}callback_i32, i32 0, i64 2981)
120+
// NO_DISC: ret ptr ptrauth (ptr @{{.*}}callback_i32, i32 0)
121+
return callback_i32;
122+
}
123+
// Entry point to the chain, takes L4 and returns function returning fn ptr.
124+
// CHECK-LABEL: f_deep
125+
// CHECK: (ptr [[CB:%.*]])
126+
pub extern "C" fn f_deep(cb: L4) -> DeepRet {
127+
// DISC: call i32 [[CB]](ptr ptrauth (ptr @{{.*}}dummy_l3, i32 0, i64 12410)) {{.*}} [ "ptrauth"(i32 0, i64 12410) ]
128+
// NO_DISC: call i32 [[CB]](ptr ptrauth (ptr @{{.*}}dummy_l3, i32 0)) {{.*}} [ "ptrauth"(i32 0, i64 0) ]
129+
cb(dummy_l3);
130+
// DISC: ret ptr ptrauth (ptr @{{.*}}returned_fn, i32 0, i64 34128)
131+
// NO_DISC: ret ptr ptrauth (ptr @{{.*}}returned_fn, i32 0)
132+
return returned_fn;
133+
}
134+
135+
// CHECK-LABEL: main
136+
pub fn main() {
137+
unsafe {
138+
// DISC: [[RET_FN:%.*]] = call ptr ptrauth (ptr @{{.*}}f_deep, i32 0, i64 1059)(ptr ptrauth (ptr @{{.*}}dummy_l4, i32 0, i64 12410)) {{.*}} [ "ptrauth"(i32 0, i64 1059) ]
139+
// NO_DISC: [[RET_FN:%.*]] = call ptr ptrauth (ptr @{{.*}}f_deep, i32 0)(ptr ptrauth (ptr @{{.*}}dummy_l4, i32 0)) {{.*}} [ "ptrauth"(i32 0, i64 0) ]
140+
let ret_fn: DeepRet = T_DEEP(dummy_l4);
141+
// DISC: [[INNER_FN:%.*]] = call ptr [[RET_FN]]() {{.*}} [ "ptrauth"(i32 0, i64 34128) ]
142+
// NO_DISC: [[INNER_FN:%.*]] = call ptr [[RET_FN]]() {{.*}} [ "ptrauth"(i32 0, i64 0) ]
143+
let inner_fn: L0 = ret_fn();
144+
// DISC: call i32 [[INNER_FN]](i32 42) {{.*}} [ "ptrauth"(i32 0, i64 2981) ]
145+
// NO_DISC: call i32 [[INNER_FN]](i32 42) {{.*}} [ "ptrauth"(i32 0, i64 0) ]
146+
let result = inner_fn(42);
147+
148+
black_box(result);
149+
}
150+
}

0 commit comments

Comments
 (0)