]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
lkdtm: Fix CFI_BACKWARD on RISC-V
authorSami Tolvanen <samitolvanen@google.com>
Wed, 27 Sep 2023 22:48:04 +0000 (22:48 +0000)
committerPalmer Dabbelt <palmer@rivosinc.com>
Fri, 27 Oct 2023 21:43:10 +0000 (14:43 -0700)
On RISC-V, the return address is before the current frame pointer,
unlike on most other architectures. Use the correct offset on RISC-V
to fix the CFI_BACKWARD test.

Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Acked-by: Kees Cook <keescook@chromium.org>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Link: https://lore.kernel.org/r/20230927224757.1154247-14-samitolvanen@google.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
drivers/misc/lkdtm/cfi.c

index fc28714ae3a610e44c361e8c608a70148fe02f91..6a33889d0902af7430d0d51451148787e8cbacf0 100644 (file)
@@ -68,12 +68,20 @@ static void lkdtm_CFI_FORWARD_PROTO(void)
 #define no_pac_addr(addr)      \
        ((__force __typeof__(addr))((uintptr_t)(addr) | PAGE_OFFSET))
 
+#ifdef CONFIG_RISCV
+/* https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#frame-pointer-convention */
+#define FRAME_RA_OFFSET                (-1)
+#else
+#define FRAME_RA_OFFSET                1
+#endif
+
 /* The ultimate ROP gadget. */
 static noinline __no_ret_protection
 void set_return_addr_unchecked(unsigned long *expected, unsigned long *addr)
 {
        /* Use of volatile is to make sure final write isn't seen as a dead store. */
-       unsigned long * volatile *ret_addr = (unsigned long **)__builtin_frame_address(0) + 1;
+       unsigned long * volatile *ret_addr =
+               (unsigned long **)__builtin_frame_address(0) + FRAME_RA_OFFSET;
 
        /* Make sure we've found the right place on the stack before writing it. */
        if (no_pac_addr(*ret_addr) == expected)
@@ -88,7 +96,8 @@ static noinline
 void set_return_addr(unsigned long *expected, unsigned long *addr)
 {
        /* Use of volatile is to make sure final write isn't seen as a dead store. */
-       unsigned long * volatile *ret_addr = (unsigned long **)__builtin_frame_address(0) + 1;
+       unsigned long * volatile *ret_addr =
+               (unsigned long **)__builtin_frame_address(0) + FRAME_RA_OFFSET;
 
        /* Make sure we've found the right place on the stack before writing it. */
        if (no_pac_addr(*ret_addr) == expected)