Skip to content
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

Normalize ptrauth handling in sanitizer runtime #100483

Merged
merged 2 commits into from
Jul 25, 2024

Conversation

asl
Copy link
Collaborator

@asl asl commented Jul 24, 2024

  1. Include ptrauth.h if ptrauth_intrinsics language feature is specified (per ptrauth spec, this is what enables ptrauh.h usage and functions like ptrauth_strip)
  2. For PAC-RET fallback implement two changes:
    1. Switch to macro, so we can ignore key argument
    2. Ensure the unsigned value is erased from LR, so the possibility of gadget reuse is reduced.

Fixes #100467

 1. Include ptrauth.h if ptrauth_intrinsics language feature is specified
    (per ptrauth spec, this is what enables ptrauh.h usage)
 2. For PAC-RET fallback implement two changes:
   - Switch to macro, so we can ignore key argument
   - Ensure the unsigned value is erased from LR, so the
     possibility of gadget reuse is reduced.

Fixes #100467
@asl
Copy link
Collaborator Author

asl commented Jul 24, 2024

@sylvestre will you please double check if this fixes the issue you're seeing?

@llvmbot
Copy link
Member

llvmbot commented Jul 24, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Anton Korobeynikov (asl)

Changes
  1. Include ptrauth.h if ptrauth_intrinsics language feature is specified (per ptrauth spec, this is what enables ptrauh.h usage)
  2. For PAC-RET fallback implement two changes:
  • Switch to macro, so we can ignore key argument
  • Ensure the unsigned value is erased from LR, so the possibility of gadget reuse is reduced.

Fixes #100467


Full diff: https://github.com/llvm/llvm-project/pull/100483.diff

1 Files Affected:

  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_ptrauth.h (+18-16)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_ptrauth.h b/compiler-rt/lib/sanitizer_common/sanitizer_ptrauth.h
index 5200354694851..d228dd33cf938 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_ptrauth.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_ptrauth.h
@@ -9,24 +9,26 @@
 #ifndef SANITIZER_PTRAUTH_H
 #define SANITIZER_PTRAUTH_H
 
-#if __has_feature(ptrauth_calls)
+#if __has_feature(ptrauth_intrinsics)
 #include <ptrauth.h>
 #elif defined(__ARM_FEATURE_PAC_DEFAULT) && !defined(__APPLE__)
-inline unsigned long ptrauth_strip(void* __value, unsigned int __key) {
-  // On the stack the link register is protected with Pointer
-  // Authentication Code when compiled with -mbranch-protection.
-  // Let's stripping the PAC unconditionally because xpaclri is in
-  // the NOP space so will do nothing when it is not enabled or not available.
-  unsigned long ret;
-  asm volatile(
-      "mov x30, %1\n\t"
-      "hint #7\n\t"  // xpaclri
-      "mov %0, x30\n\t"
-      : "=r"(ret)
-      : "r"(__value)
-      : "x30");
-  return ret;
-}
+// On the stack the link register is protected with Pointer
+// Authentication Code when compiled with -mbranch-protection.
+// Let's stripping the PAC unconditionally because xpaclri is in
+// the NOP space so will do nothing when it is not enabled or not available.
+#define ptrauth_strip(__value, __key)     \
+  ({                                      \
+      unsigned long ret;                  \
+      asm volatile(                       \
+        "mov x30, %1\n\t"                 \
+        "hint #7\n\t"                     \
+        "mov %0, x30\n\t"                 \
+        "mov x30, xzr\n\t"                \
+        : "=r"(ret)                       \
+        : "r"(__value)                    \
+        : "x30");                         \
+      ret;                                \
+  })
 #define ptrauth_auth_data(__value, __old_key, __old_data) __value
 #define ptrauth_string_discriminator(__string) ((int)0)
 #else

Copy link

github-actions bot commented Jul 24, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@kovdan01 kovdan01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@asl asl force-pushed the users/asl/compiler-rt-pauth-includes branch from 60e4dd8 to 1661d58 Compare July 25, 2024 00:10
@asl asl force-pushed the users/asl/compiler-rt-pauth-includes branch from 1661d58 to 778a0e3 Compare July 25, 2024 00:16
@asl asl merged commit cc4f989 into main Jul 25, 2024
6 checks passed
@asl asl deleted the users/asl/compiler-rt-pauth-includes branch July 25, 2024 18:57
@asl
Copy link
Collaborator Author

asl commented Jul 25, 2024

/cherry-pick cc4f989

@asl asl added this to the LLVM 19.X Release milestone Jul 25, 2024
llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Jul 25, 2024
1. Include `ptrauth.h` if `ptrauth_intrinsics` language feature is specified (per ptrauth spec, this is what enables `ptrauh.h` usage and functions like `ptrauth_strip`)
 2. For PAC-RET fallback implement two changes:
    1. Switch to macro, so we can ignore key argument
    2. Ensure the unsigned value is erased from LR, so the possibility of gadget reuse is reduced.

Fixes llvm#100467

(cherry picked from commit cc4f989)
@llvmbot
Copy link
Member

llvmbot commented Jul 25, 2024

/pull-request #100634

@ZequanWu
Copy link
Contributor

With the fix, this is still broken due to invalid pointer conversion:

clang++: warning: argument unused during compilation: '--unwindlib=none' [-Wunused-command-line-argument]
/usr/local/google/home/ayzhao/src/chromium/src/third_party/llvm/compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cpp:210:12: error: incompatible integer to pointer conversion assigning to 'void *' from 'unsigned long'
  210 |   Vtable = ptrauth_strip(Vtable, ptrauth_key_cxx_vtable_pointer);
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/google/home/ayzhao/src/chromium/src/third_party/llvm/compiler-rt/lib/ubsan/../sanitizer_common/sanitizer_ptrauth.h:20:5: note: expanded from macro 'ptrauth_strip'
   20 |     ({                                  \
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   21 |       unsigned long ret;                \
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   22 |       asm volatile(                     \
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   23 |           "mov x30, %1\n\t"             \
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   24 |           "hint #7\n\t"                 \
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   25 |           "mov %0, x30\n\t"             \
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   26 |           "mov x30, xzr\n\t"            \
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   27 |           : "=r"(ret)                   \
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   28 |           : "r"(__value)                \
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   29 |           : "x30");                     \
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   30 |       ret;                              \
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   31 |     })
      |     ~~
1 error generated.

@asl
Copy link
Collaborator Author

asl commented Jul 25, 2024

@ZequanWu

With the fix, this is still broken due to invalid pointer conversion:

Oh. Thanks for noticing this! I believe we fixed this issue... But apparently, not final version of patch was submitted. So, to double check, the final version has void *ret variable, does it work for you?

Apparently, there are no buildbots that cover this configuration...

alanzhao1 added a commit to alanzhao1/llvm-project that referenced this pull request Jul 25, 2024
With llvm#100483, if the inline asm
version of `ptrauth_strip` is used instead of the builtin, the inline
asm implementation will return an unsigned long, causing an incompatible
pointer conversion issue.
@alanzhao1
Copy link
Contributor

@ZequanWu

With the fix, this is still broken due to invalid pointer conversion:

Oh. Thanks for noticing this! I believe we fixed this issue... But apparently, not final version of patch was submitted. So, to double check, the final version has void *ret variable, does it work for you?

Apparently, there are no buildbots that cover this configuration...

A quick search shows that the preference seems to be to cast the result of ptrauth_strip to the desired type where it's used. I created #100665

tru pushed a commit to llvmbot/llvm-project that referenced this pull request Jul 26, 2024
1. Include `ptrauth.h` if `ptrauth_intrinsics` language feature is specified (per ptrauth spec, this is what enables `ptrauh.h` usage and functions like `ptrauth_strip`)
 2. For PAC-RET fallback implement two changes:
    1. Switch to macro, so we can ignore key argument
    2. Ensure the unsigned value is erased from LR, so the possibility of gadget reuse is reduced.

Fixes llvm#100467

(cherry picked from commit cc4f989)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

fails to build with error: use of undeclared identifier 'ptrauth_key_cxx_vtable_pointer'
6 participants