| 1 | #include <asm/hwcap.h> |
| 2 | #include <stdbool.h> |
| 3 | #include <sys/auxv.h> |
| 4 | #include <sys/prctl.h> |
| 5 | |
| 6 | #ifndef HWCAP_GCS |
| 7 | #define HWCAP_GCS (1UL << 32) |
| 8 | #endif |
| 9 | |
| 10 | #define PR_GET_SHADOW_STACK_STATUS 74 |
| 11 | #define PR_SET_SHADOW_STACK_STATUS 75 |
| 12 | #define PR_LOCK_SHADOW_STACK_STATUS 76 |
| 13 | |
| 14 | #define PR_SHADOW_STACK_ENABLE (1UL << 0) |
| 15 | #define PR_SHADOW_STACK_WRITE (1UL << 1) |
| 16 | #define PR_SHADOW_STACK_PUSH (1UL << 2) |
| 17 | |
| 18 | #define PRCTL_SYSCALL_NO 167 |
| 19 | |
| 20 | // Once we enable GCS, we cannot return from the function that made the syscall |
| 21 | // to enable it. This is because the control stack is empty, there is no valid |
| 22 | // address for us to return to. So for the initial enable we must use inline asm |
| 23 | // instead of the libc's prctl wrapper function. |
| 24 | #define my_prctl(option, arg2, arg3, arg4, arg5) \ |
| 25 | ({ \ |
| 26 | register unsigned long x0 __asm__("x0") = option; \ |
| 27 | register unsigned long x1 __asm__("x1") = arg2; \ |
| 28 | register unsigned long x2 __asm__("x2") = arg3; \ |
| 29 | register unsigned long x3 __asm__("x3") = arg4; \ |
| 30 | register unsigned long x4 __asm__("x4") = arg5; \ |
| 31 | register unsigned long x8 __asm__("x8") = PRCTL_SYSCALL_NO; \ |
| 32 | __asm__ __volatile__("svc #0\n" \ |
| 33 | : "=r"(x0) \ |
| 34 | : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), \ |
| 35 | "r"(x8) \ |
| 36 | : "cc", "memory"); \ |
| 37 | }) |
| 38 | |
| 39 | unsigned long get_gcs_status() { |
| 40 | unsigned long mode = 0; |
| 41 | prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); |
| 42 | return mode; |
| 43 | } |
| 44 | |
| 45 | extern void _start(); |
| 46 | bool change_gcs_config(bool enable) { |
| 47 | // The test unlocks and disables all features (excluding the main enable bit) |
| 48 | // before calling this expression. Enable them again. |
| 49 | unsigned long new_status = |
| 50 | enable | PR_SHADOW_STACK_PUSH | PR_SHADOW_STACK_WRITE; |
| 51 | |
| 52 | if (enable) { |
| 53 | // We would not be able to return from prctl(). |
| 54 | my_prctl(PR_SET_SHADOW_STACK_STATUS, new_status, 0, 0, 0); |
| 55 | |
| 56 | // This is a stack, so we must push in reverse order to the pops we want to |
| 57 | // have later. So push the return of __lldb_expr (_start), then the return |
| 58 | // address of this function (__lldb_expr). |
| 59 | __asm__ __volatile__("sys #3, C7, C7, #0, %0\n" // gcspushm _start |
| 60 | "sys #3, C7, C7, #0, x30\n" // gcspushm x30 |
| 61 | : |
| 62 | : "r" (_start)); |
| 63 | } else { |
| 64 | if (prctl(PR_SET_SHADOW_STACK_STATUS, new_status, 0, 0, 0) != 0) |
| 65 | return false; |
| 66 | } |
| 67 | |
| 68 | // Turn back on all locks. |
| 69 | if (prctl(PR_LOCK_SHADOW_STACK_STATUS, ~(0UL), 0, 0, 0) != 0) |
| 70 | return false; |
| 71 | |
| 72 | return true; |
| 73 | } |
| 74 | |
| 75 | void gcs_signal() { |
| 76 | // If we enabled GCS manually, then we could just return from main to generate |
| 77 | // a signal. However, if the C library enabled it, then we'd just exit |
| 78 | // normally. Assume the latter, and try to return to some bogus address to |
| 79 | // generate the signal. |
| 80 | __asm__ __volatile__( |
| 81 | // Corrupt the link register. This could be many numbers but 16 is a |
| 82 | // nicely aligned value that is unlikely to result in a fault because the |
| 83 | // PC is misaligned, which would hide the GCS fault. |
| 84 | "add x30, x30, #10\n" |
| 85 | "ret\n" ); |
| 86 | } |
| 87 | |
| 88 | // These functions are used to observe gcspr_el0 changing as we enter them, and |
| 89 | // the fault we cause by changing its value. Also used to check expression |
| 90 | // eval can handle function calls. |
| 91 | int test_func2() { return 99; } |
| 92 | |
| 93 | int test_func() { return test_func2(); } |
| 94 | |
| 95 | int main() { |
| 96 | if (!(getauxval(AT_HWCAP) & HWCAP_GCS)) |
| 97 | return 1; |
| 98 | |
| 99 | unsigned long mode = get_gcs_status(); |
| 100 | if ((mode & 1) == 0) { |
| 101 | // If GCS wasn't already enabled by the C library, enable it. |
| 102 | my_prctl(PR_SET_SHADOW_STACK_STATUS, PR_SHADOW_STACK_ENABLE, 0, 0, 0); |
| 103 | // From this point on, we cannot return from main without faulting because |
| 104 | // the return address from main, and every function before that, is not on |
| 105 | // the guarded control stack. |
| 106 | } |
| 107 | |
| 108 | // By now we should have one memory region where the GCS is stored. |
| 109 | |
| 110 | // For register read/write tests. |
| 111 | volatile int i = test_func(); |
| 112 | |
| 113 | // If this was a register test, we would have disabled GCS during the |
| 114 | // test_func call. We cannot re-enable it from ptrace so skip this part in |
| 115 | // this case. |
| 116 | mode = get_gcs_status(); |
| 117 | if ((mode & 1) == 1) |
| 118 | gcs_signal(); // Set break point at this line. |
| 119 | |
| 120 | return 0; |
| 121 | } |
| 122 | |