lkdtm: Fix CFI_BACKWARD on RISC-V
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>
This commit is contained in:
committed by
Palmer Dabbelt
parent
c40fef858d
commit
245561ba6d
@@ -68,12 +68,20 @@ static void lkdtm_CFI_FORWARD_PROTO(void)
|
|||||||
#define no_pac_addr(addr) \
|
#define no_pac_addr(addr) \
|
||||||
((__force __typeof__(addr))((uintptr_t)(addr) | PAGE_OFFSET))
|
((__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. */
|
/* The ultimate ROP gadget. */
|
||||||
static noinline __no_ret_protection
|
static noinline __no_ret_protection
|
||||||
void set_return_addr_unchecked(unsigned long *expected, unsigned long *addr)
|
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. */
|
/* 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. */
|
/* Make sure we've found the right place on the stack before writing it. */
|
||||||
if (no_pac_addr(*ret_addr) == expected)
|
if (no_pac_addr(*ret_addr) == expected)
|
||||||
@@ -88,7 +96,8 @@ static noinline
|
|||||||
void set_return_addr(unsigned long *expected, unsigned long *addr)
|
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. */
|
/* 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. */
|
/* Make sure we've found the right place on the stack before writing it. */
|
||||||
if (no_pac_addr(*ret_addr) == expected)
|
if (no_pac_addr(*ret_addr) == expected)
|
||||||
|
|||||||
Reference in New Issue
Block a user