From e2e5113a530897d8aedc4ad1d65c5a99a926b9cc Mon Sep 17 00:00:00 2001 From: Stewart Smith Date: Tue, 13 May 2025 13:52:41 -0700 Subject: [PATCH] Fix my_context_[spawn|continue|yield] for aarch64 BTI Fixes SIGILL in MariaDB Server "main.non_blocking_api" test case on aarch64 processors supporting Branch Target Identification (BTI). Branch Target Identification is a new aarch64 feature that prevents jumping to arbitrary code locations that are not properly marked as branch targets. The "-mbranch-protection=standard" flag to GCC will enable code generation using BTI. This is backwards compatible as the added instructions are no-ops on older processors. One example of where both "-mbranch-protection=standard" is enabled and hardware supports it is with Amazon Linux 2023 and Graviton 4. The symptom is the following mtr main.non_blocking_api failure: mysqltest got signal 4 read_command_buf (0xaaaae6ae27a8): connect (con_nonblock,localhost,root,,test) conn->name (0xaaaae6b0c0b8): Attempting backtrace... stack_bottom = 0x0 thread_stack 0x3c000 /usr/bin/mariadb-test(my_print_stacktrace+0x48)[0xaaaab6934088] bits/stdio2.h:79(signal_handler)[0xaaaab68f41a0] addr2line: 'linux-vdso.so.1': No such file linux-vdso.so.1(__kernel_rt_sigreturn+0x0)[0xffffa22bc830] /usr/bin/mariadb-test(my_context_spawn+0x74)[0xaaaab6914d84] With GDB giving the information that SIGILL was on the perfectly legal 'mov' instruction: Program received signal SIGILL, Illegal instruction. 0x0000aaaaaab44d84 in my_context_spawn (c=0xaaaaab07ada8, f=0xfffff7fed240, d=0x0) at mariadb1011-10.11.11-1.amzn2023.0.1.aarch64/libmariadb/libmariadb/ma_context.c:674 674 __asm__ __volatile__ (gdb) x/i$pc => 0xaaaaaab44d84 : mov w0, #0x1 // #1 The call sequence to get to this point is as follows: Breakpoint 1, my_context_spawn (c=0xaaaaab07ada8, f=0xaaaaaab38024 , d=0xffffffffc648) at libmariadb/ma_context.c:661 661 register void *stack asm("x13") = c->stack_top; (gdb) c Continuing. Breakpoint 2, my_context_yield (c=0xaaaaab07ada8) at libmariadb/ma_context.c:843 843 register const uint64_t *save asm("x19") = &c->save[0]; Continuing from here leads to the SIGILL above. The branch that ends up causing the SIGILL is the "br x11" instruction in my_context_yield(). This is due to the branch being to a location that is not marked as a branch target. The fix is to ensure that these locations in the my_context aarch64 assembler are marked with "bti j" instructions so that the locations that will be 'br'ed to are valid to be 'br'ed to. Since older compilers don't know about the instruction, we need an ifdef to define a string that has the raw opcode in it. Fixes: d2285fb8304c82fd87de483845d1c12b06927479 --- libmariadb/ma_context.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libmariadb/ma_context.c b/libmariadb/ma_context.c index a80a7867..64bbdc76 100644 --- a/libmariadb/ma_context.c +++ b/libmariadb/ma_context.c @@ -637,6 +637,13 @@ my_context_destroy(struct my_context *c) #ifdef MY_CONTEXT_USE_AARCH64_GCC_ASM + +#if (defined(__clang__) && (__clang_major__ >= 9)) || \ + (defined(__GNUC__) && (__GNUC__ > 9 || (__GNUC__ == 9 && __GNUC_MINOR__ >= 1))) +#define BTI_J_STR "bti j" +#else +#define BTI_J_STR ".inst 0xd503241f" +#endif /* GCC-aarch64 (arm64) implementation of my_context. @@ -724,12 +731,14 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d) will do this for us if needed. */ "1:\n\t" + BTI_J_STR "\n\t" "ldr x10, [%[save], #88]\n\t" "mov sp, x10\n\t" "mov %w[ret], #0\n\t" "b 3f\n" /* Come here when operation was suspended. */ "2:\n\t" + BTI_J_STR "\n\t" "mov %w[ret], #1\n" "3:\n" : [ret] "=r" (ret), @@ -824,6 +833,7 @@ my_context_continue(struct my_context *c) my_context_spawn(), so we preserve the value correctly at this point. */ "1:\n\t" + BTI_J_STR "\n\t" /* x19 (aka %[save]) is preserved from my_context_spawn() in this case. */ "ldr x20, [%[save], #8]\n\t" "ldp x21, x22, [%[save], #16]\n\t" @@ -840,6 +850,7 @@ my_context_continue(struct my_context *c) "b 3f\n" /* Come here when operation is suspended. */ "2:\n\t" + BTI_J_STR "\n\t" "mov %w[ret], #1\n" "3:\n" : [ret] "=r" (ret) @@ -923,6 +934,7 @@ my_context_yield(struct my_context *c) "br x11\n" "1:\n" + BTI_J_STR "\n\t" : : [save] "r" (save) : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",