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
This commit is contained in:
parent
60dbdaa3fa
commit
1b13b14758
6 changed files with 105 additions and 22 deletions
|
@ -23,10 +23,11 @@ crash1:
|
|||
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 @@ crashnostack:
|
|||
ldr r0, [r0]
|
||||
b .
|
||||
.cfi_endproc
|
||||
.size crash_no_stack, .-crash_no_stack
|
||||
|
|
|
@ -41,11 +41,12 @@ crash1:
|
|||
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 @@ crashnostack:
|
|||
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
|
||||
|
|
|
@ -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 @@ typedef int (__kuser_cmpxchg64_t)(const int64_t*, const int64_t*, volatile int64
|
|||
// 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 @@ static int usage() {
|
|||
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 @@ static int usage() {
|
|||
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 @@ static int usage() {
|
|||
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 @@ noinline int do_action(const char* arg) {
|
|||
} 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")) {
|
||||
|
@ -349,6 +377,14 @@ noinline int do_action(const char* arg) {
|
|||
__kuser_dmb();
|
||||
} 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) {
|
||||
|
|
|
@ -43,10 +43,11 @@ crash1:
|
|||
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 @@ crashnostack:
|
|||
ld t2, 0(zero)
|
||||
j .
|
||||
.cfi_endproc
|
||||
.size crash_no_stack, .-crash_no_stack
|
||||
|
|
|
@ -6,13 +6,15 @@ crash1:
|
|||
|
||||
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
|
||||
|
|
|
@ -6,13 +6,15 @@ crash1:
|
|||
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue