-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[llvm-exegesis][AArch64] Check for PAC keys before disabling them #138643
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-tools-llvm-exegesis Author: Abhilash Majumder (abhilash1910) Changes[llvm-exegesis][AArch64] Check for PAC keys before disabling them. Tries to resolve aarch64 error arising from accessible PAC keys from PR: Disable pauth and ldgm as unsupported instructions fixed. The suspected reason is in some systems, the pac keys are present and need to be checked before setting them. This is followup to merge the changes with following changes to attempt to fixup the arch64 failure. Changes: Apply checks to verify if PAC is enabled in some systems and disabling them . @lakshayk-nv please help to verify and review. Full diff: https://github.com/llvm/llvm-project/pull/138643.diff 1 Files Affected:
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index a1eb5a46f21fc..d1da6f41461a7 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -207,16 +207,26 @@ class ExegesisAArch64Target : public ExegesisTarget {
if (isPointerAuth(Opcode)) {
#if defined(__aarch64__) && defined(__linux__)
+
+ // Fix for some systems where PAC/PAG keys are present but is
+ // explicitly getting disabled
+ unsigned long pac_keys = 0;
+ if (prctl(PR_PAC_GET_ENABLED_KEYS, &pac_keys, 0, 0, 0) < 0) {
+ return "Failed to get PAC key status";
+ }
+
// Disable all PAC keys. Note that while we expect the measurements to
// be the same with PAC keys disabled, they could potentially be lower
// since authentication checks are bypassed.
- if (prctl(PR_PAC_SET_ENABLED_KEYS,
- PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY |
- PR_PAC_APDBKEY, // all keys
- 0, // disable all
- 0, 0) < 0) {
- return "Failed to disable PAC keys";
- }
+ if (pac_keys != 0) {
+ if (prctl(PR_PAC_SET_ENABLED_KEYS,
+ PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY |
+ PR_PAC_APDBKEY, // all keys
+ 0, // disable all
+ 0, 0) < 0) {
+ return "Failed to disable PAC keys";
+ }
+ }
#else
return "Unsupported opcode: isPointerAuth";
#endif
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please run clang-format
over the patch to fix the code formatting.
@@ -207,16 +207,26 @@ class ExegesisAArch64Target : public ExegesisTarget { | |||
|
|||
if (isPointerAuth(Opcode)) { | |||
#if defined(__aarch64__) && defined(__linux__) | |||
|
|||
// Fix for some systems where PAC/PAG keys are present but is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment could probably be more descriptive and instead of just stating that it is a fix, state the case that it is handling and what would happen if we do not handle that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, please help to review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't really describe the why that I am asking about. This being "better" or "safer" doesn't really mean anything to someone who doesn't already understand the pointer authentication flow.
// For systems without PAC, this is a No-op but with PAC, it is | ||
// safer to check the existing key state and then disable/enable them. | ||
// Hence the guard placed for switching. | ||
unsigned long pac_keys = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@asl this is a linux pac question so I'm not sure if this is correct behavior and will leave it to you
I am curious though - this seems like a PAC behavior choice based on compile time process configuration rather than specified target info? Is this expected behavior (I don't understand how ptrauth works on linux)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Tagging @atrosinenko
Essentially we expect two things:
- If full pauth ABI is enabled, it is done in platform-specific manner. E.g. via ABI field in target quadruple for common platforms, or some other way for downstream
- PAC-RET is expected to work regardless of settings since it is an ABI-neutral change.
My expectation is that PAC instructions in hint space should be handled gracefully regardless of PAC state. But maybe I am missing some context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If my understanding is correct, the problem is that llvm-exegesis may fail with an error like "AUTIA: Failed to disable PAC keys", depending on the CPU features. It looks like I have managed to reproduce this issue in QEMU (in full-system emulation mode), the results are below.
As far as I see, PAuth-related prctl
s are not documented in man pages well, but thankfully the kernel sources are quite readable on themselves:
prctl
entry point is in kernel/sys.c, and here are relevant operations- the requests are ultimately processed in arch/arm64/kernel/pointer_auth.c
- according to the Caveats section of
man prctl
, as well as toman PR_PAC_RESET_KEYS
, it is probably better to passprctl
arguments aslong
Each configuration was tested by running
strace -f -e prctl \
/path/to/llvm-project/build-aarch64/bin/llvm-exegesis \
-mtriple=aarch64-linux-gnu \
-mcpu=neoverse-v2 \
-mode=latency \
--opcode-name=AUTIA \
--use-dummy-perf-counters
On the main branch (commit cd6c4b6), with emulated CPU set to neoverse-v1,pauth-impdef=on
(Neoverse-V2 is not supported in QEMU 9.2.1, but Neoverse-V1 seems to be enough to reproduce the issue. Similarly, pauth-impdef=on
should not affect the issue, but makes emulation faster) I got
prctl(PR_PAC_SET_ENABLED_KEYS, PR_PAC_APIAKEY|PR_PAC_APIBKEY|PR_PAC_APDAKEY|PR_PAC_APDBKEY, 0, 0, 0) = 0
---
mode: latency
key:
instructions:
- 'AUTIA X23 X23 X15'
config: ''
register_initial_values:
- 'X23=0x0'
- 'X15=0x0'
cpu_name: neoverse-v2
llvm_triple: aarch64-unknown-linux-gnu
min_instructions: 10000
measurements: []
error: ''
info: Repeating a single implicitly serial instruction
assembled_snippet: F70F1FF8170080D20F0080D2F711C1DAF711C1DAF711C1DAF711C1DAF70741F8C0035FD6
...
+++ exited with 0 +++
and setting CPU to cortex-a72
gives this output:
prctl(PR_PAC_SET_ENABLED_KEYS, PR_PAC_APIAKEY|PR_PAC_APIBKEY|PR_PAC_APDAKEY|PR_PAC_APDBKEY, 0, 0, 0) = -1 EINVAL (Invalid argument)
AUTIA: Failed to disable PAC keys
+++ exited with 0 +++
(by the way, return code is 0, which is a bit surprising...). This is probably because of if (!system_supports_address_auth()) return -EINVAL;
check in the kernel, assuming system_supports_address_auth()
means "FEAT_PAUTH was detected at run-time" (instead of "the kernel was compiled with PAuth support" or something like this).
This PR (commit 2a9af0f) produces an error like the following with both CPU models:
prctl(PR_PAC_GET_ENABLED_KEYS, 0x7ff2234598, 0, 0, 0) = -1 EINVAL (Invalid argument)
AUTIA: Failed to get PAC key status
+++ exited with 0 +++
Turned out, all arguments should be set to 0 and the bitmask is returned as the return value of prctl
.
I applied a quick fix:
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 7e6382693c3e..3d59955177cb 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -213,8 +213,8 @@ private:
// For systems without PAC, this is a No-op but with PAC, it is
// safer to check the existing key state and then disable/enable them.
// Hence the guard for switching.
- unsigned long PacKeys = 0;
- if (prctl(PR_PAC_GET_ENABLED_KEYS, &PacKeys, 0, 0, 0) < 0) {
+ unsigned long PacKeys = prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0);
+ if ((long)PacKeys < 0) {
return "Failed to get PAC key status";
}
With CPU set to neoverse-v1,pauth-impdef=on
the following output is produced:
prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0) = 0xf (PR_PAC_APIAKEY|PR_PAC_APIBKEY|PR_PAC_APDAKEY|PR_PAC_APDBKEY)
prctl(PR_PAC_SET_ENABLED_KEYS, PR_PAC_APIAKEY|PR_PAC_APIBKEY|PR_PAC_APDAKEY|PR_PAC_APDBKEY, 0, 0, 0) = 0
---
mode: latency
key:
instructions:
- 'AUTIA X23 X23 X0'
config: ''
register_initial_values:
- 'X23=0x0'
- 'X0=0x0'
cpu_name: neoverse-v2
llvm_triple: aarch64-unknown-linux-gnu
min_instructions: 10000
measurements: []
error: ''
info: Repeating a single implicitly serial instruction
assembled_snippet: F70F1FF8170080D2000080D21710C1DA1710C1DA1710C1DA1710C1DAF70741F8C0035FD6
...
+++ exited with 0 +++
but with cortex-a72
it fails with:
prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0) = -1 EINVAL (Invalid argument)
AUTIA: Failed to get PAC key status
+++ exited with 0 +++
Probably, EINVAL
is always returned when FEAT_PAUTH is not supported by the CPU.
if (prctl(PR_PAC_SET_ENABLED_KEYS, | ||
PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | | ||
PR_PAC_APDBKEY, // all keys | ||
0, // disable all | ||
0, 0) < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] It may be more readable to define a wrapper with the default argument values in C++, as in this example these three literal 0s have different meaning: the first one is a bitmask and the rest are "the argument is unused, pass 0 now, other values to de defined in the future"
static int prctl_wrapper(int op, long arg2 = 0, long arg3 = 0, long arg4 = 0, long arg5 = 0) {
return prctl(op, arg2, arg3, arg4, arg5);
}
[llvm-exegesis][AArch64] Check for PAC keys before disabling them.
Tries to resolve aarch64 error arising from accessible PAC keys from PR: Disable pauth and ldgm as unsupported instructions fixed. The suspected reason is in some systems, the pac keys are present and need to be checked before setting them.
This is followup to merge the changes with following changes to attempt to fixup the arch64 failure.
Changes:
Apply checks to verify if PAC is enabled in some systems and disabling them .
@lakshayk-nv please help to verify and review.
cc @sjoerdmeijer @davemgreen