crasher: add pac and bti crashes.
Also add the missing `.size` directives to all the assembler functions
for slightly improved backtraces.
Test: crasher64 pac; crasher64 bti
Change-Id: I8e0c127cbff56c33637e6ca8f1d927b971951807
diff --git a/debuggerd/crasher/arm/crashglue.S b/debuggerd/crasher/arm/crashglue.S
index e4adf40..0def8ae 100644
--- a/debuggerd/crasher/arm/crashglue.S
+++ b/debuggerd/crasher/arm/crashglue.S
@@ -23,10 +23,11 @@
ldr lr, [lr]
b .
.cfi_endproc
+ .size crash1, .-crash1
-.globl crashnostack
-.type crashnostack, %function
-crashnostack:
+.globl crash_no_stack
+.type crash_no_stack, %function
+crash_no_stack:
.cfi_startproc
mov r1, sp
.cfi_def_cfa_register r1
@@ -35,3 +36,4 @@
ldr r0, [r0]
b .
.cfi_endproc
+ .size crash_no_stack, .-crash_no_stack
diff --git a/debuggerd/crasher/arm64/crashglue.S b/debuggerd/crasher/arm64/crashglue.S
index 97c824e..c56e19a 100644
--- a/debuggerd/crasher/arm64/crashglue.S
+++ b/debuggerd/crasher/arm64/crashglue.S
@@ -41,11 +41,12 @@
ldr x30, [x30]
b .
.cfi_endproc
+ .size crash1, .-crash1
-.globl crashnostack
-.type crashnostack, %function
-crashnostack:
+.globl crash_no_stack
+.type crash_no_stack, %function
+crash_no_stack:
.cfi_startproc
mov x1, sp
.cfi_def_cfa_register x1
@@ -54,3 +55,41 @@
ldr x0, [x0]
b .
.cfi_endproc
+ .size crash_no_stack, .-crash_no_stack
+
+
+.globl crash_bti
+.type crash_bti, %function
+crash_bti:
+ .cfi_startproc
+ adr x16, 1f
+ br x16
+1: // Deliberatly not a bti instruction so we crash here.
+ b .
+ .cfi_endproc
+ .size crash_bti, .-crash_bti
+
+
+.globl crash_pac
+.type crash_pac, %function
+crash_pac:
+ .cfi_startproc
+ paciasp
+ // Since sp is a pac input, this ensures a mismatch.
+ sub sp, sp, #16
+ autiasp
+ b .
+ .cfi_endproc
+ .size crash_pac, .-crash_pac
+
+// Set the PAC and BTI bits for this object file.
+.section .note.gnu.property, "a"
+.balign 8
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+.long 0xc0000000
+.long 4
+.long 0x3
+.long 0
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index 12ba502..3b52776 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -19,6 +19,7 @@
#include <assert.h>
#include <dirent.h>
#include <errno.h>
+#include <error.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
@@ -29,6 +30,9 @@
#include <sys/prctl.h>
#include <unistd.h>
+#include <android-base/file.h>
+#include <android-base/strings.h>
+
// We test both kinds of logging.
#include <android-base/logging.h>
#include <log/log.h>
@@ -59,8 +63,10 @@
// Avoid name mangling so that stacks are more readable.
extern "C" {
-void crash1(void);
-void crashnostack(void);
+void crash1();
+void crash_no_stack();
+void crash_bti();
+void crash_pac();
int do_action(const char* arg);
@@ -196,13 +202,6 @@
fprintf(stderr, " fdsan_file close a file descriptor that's owned by a FILE*\n");
fprintf(stderr, " fdsan_dir close a file descriptor that's owned by a DIR*\n");
fprintf(stderr, " seccomp fail a seccomp check\n");
-#if defined(__arm__)
- fprintf(stderr, " kuser_helper_version call kuser_helper_version\n");
- fprintf(stderr, " kuser_get_tls call kuser_get_tls\n");
- fprintf(stderr, " kuser_cmpxchg call kuser_cmpxchg\n");
- fprintf(stderr, " kuser_memory_barrier call kuser_memory_barrier\n");
- fprintf(stderr, " kuser_cmpxchg64 call kuser_cmpxchg64\n");
-#endif
fprintf(stderr, " xom read execute-only memory\n");
fprintf(stderr, "\n");
fprintf(stderr, " LOG_ALWAYS_FATAL call liblog LOG_ALWAYS_FATAL\n");
@@ -223,6 +222,20 @@
fprintf(stderr, "\n");
fprintf(stderr, " no_new_privs set PR_SET_NO_NEW_PRIVS and then abort\n");
fprintf(stderr, "\n");
+#if defined(__arm__)
+ fprintf(stderr, "Also, since this is an arm32 binary:\n");
+ fprintf(stderr, " kuser_helper_version call kuser_helper_version\n");
+ fprintf(stderr, " kuser_get_tls call kuser_get_tls\n");
+ fprintf(stderr, " kuser_cmpxchg call kuser_cmpxchg\n");
+ fprintf(stderr, " kuser_memory_barrier call kuser_memory_barrier\n");
+ fprintf(stderr, " kuser_cmpxchg64 call kuser_cmpxchg64\n");
+#endif
+#if defined(__aarch64__)
+ fprintf(stderr, "Also, since this is an arm64 binary:\n");
+ fprintf(stderr, " bti fail a branch target identification (BTI) check\n");
+ fprintf(stderr, " pac fail a pointer authentication (PAC) check\n");
+#endif
+ fprintf(stderr, "\n");
fprintf(stderr, "prefix any of the above with 'thread-' to run on a new thread\n");
fprintf(stderr, "prefix any of the above with 'exhaustfd-' to exhaust\n");
fprintf(stderr, "all available file descriptors before crashing.\n");
@@ -231,6 +244,21 @@
return EXIT_FAILURE;
}
+[[maybe_unused]] static void CheckCpuFeature(const std::string& name) {
+ std::string cpuinfo;
+ if (!android::base::ReadFileToString("/proc/cpuinfo", &cpuinfo)) {
+ error(1, errno, "couldn't read /proc/cpuinfo");
+ }
+ std::vector<std::string> lines = android::base::Split(cpuinfo, "\n");
+ for (std::string_view line : lines) {
+ if (!android::base::ConsumePrefix(&line, "Features\t:")) continue;
+ std::vector<std::string> features = android::base::Split(std::string(line), " ");
+ if (std::find(features.begin(), features.end(), name) == features.end()) {
+ error(1, 0, "/proc/cpuinfo does not report feature '%s'", name.c_str());
+ }
+ }
+}
+
noinline int do_action(const char* arg) {
// Prefixes.
if (!strncmp(arg, "wait-", strlen("wait-"))) {
@@ -256,7 +284,7 @@
} else if (!strcasecmp(arg, "stack-overflow")) {
overflow_stack(nullptr);
} else if (!strcasecmp(arg, "nostack")) {
- crashnostack();
+ crash_no_stack();
} else if (!strcasecmp(arg, "exit")) {
exit(1);
} else if (!strcasecmp(arg, "call-null")) {
@@ -350,6 +378,14 @@
} else if (!strcasecmp(arg, "kuser_cmpxchg64")) {
return __kuser_cmpxchg64(0, 0, 0);
#endif
+#if defined(__aarch64__)
+ } else if (!strcasecmp(arg, "bti")) {
+ CheckCpuFeature("bti");
+ crash_bti();
+ } else if (!strcasecmp(arg, "pac")) {
+ CheckCpuFeature("paca");
+ crash_pac();
+#endif
} else if (!strcasecmp(arg, "no_new_privs")) {
if (prctl(PR_SET_NO_NEW_PRIVS, 1) != 0) {
fprintf(stderr, "prctl(PR_SET_NO_NEW_PRIVS, 1) failed: %s\n", strerror(errno));
diff --git a/debuggerd/crasher/riscv64/crashglue.S b/debuggerd/crasher/riscv64/crashglue.S
index 42f59b3..f179e33 100644
--- a/debuggerd/crasher/riscv64/crashglue.S
+++ b/debuggerd/crasher/riscv64/crashglue.S
@@ -43,10 +43,11 @@
ld t2, 0(zero)
j .
.cfi_endproc
+ .size crash1, .-crash1
-.globl crashnostack
-crashnostack:
+.globl crash_no_stack
+crash_no_stack:
.cfi_startproc
mv t1, sp
.cfi_def_cfa_register t1
@@ -54,3 +55,4 @@
ld t2, 0(zero)
j .
.cfi_endproc
+ .size crash_no_stack, .-crash_no_stack
diff --git a/debuggerd/crasher/x86/crashglue.S b/debuggerd/crasher/x86/crashglue.S
index e8eb3a7..453035b 100644
--- a/debuggerd/crasher/x86/crashglue.S
+++ b/debuggerd/crasher/x86/crashglue.S
@@ -6,13 +6,15 @@
movl $0, %edx
jmp *%edx
+ .size crash1, .-crash1
-.globl crashnostack
-crashnostack:
+.globl crash_no_stack
+crash_no_stack:
.cfi_startproc
movl %esp, %eax
.cfi_def_cfa_register %eax
movl $0, %esp
movl (%esp), %ebx
.cfi_endproc
+ .size crash_no_stack, .-crash_no_stack
diff --git a/debuggerd/crasher/x86_64/crashglue.S b/debuggerd/crasher/x86_64/crashglue.S
index 8f67214..c3d39c4 100644
--- a/debuggerd/crasher/x86_64/crashglue.S
+++ b/debuggerd/crasher/x86_64/crashglue.S
@@ -6,13 +6,15 @@
movl $0, %edx
jmp *%rdx
+ .size crash1, .-crash1
-.globl crashnostack
-crashnostack:
+.globl crash_no_stack
+crash_no_stack:
.cfi_startproc
movq %rsp, %rax
.cfi_def_cfa_register %rax
movq $0, %rsp
movq (%rsp), %rbx
.cfi_endproc
+ .size crash_no_stack, .-crash_no_stack