/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _ASM_X86_CFI_H #define _ASM_X86_CFI_H /* * Clang Control Flow Integrity (CFI) support. * * Copyright (C) 2022 Google LLC */ #include <linux/bug.h> #include <asm/ibt.h> /* * An overview of the various calling conventions... * * Traditional: * * foo: * ... code here ... * ret * * direct caller: * call foo * * indirect caller: * lea foo(%rip), %r11 * ... * call *%r11 * * * IBT: * * foo: * endbr64 * ... code here ... * ret * * direct caller: * call foo / call foo+4 * * indirect caller: * lea foo(%rip), %r11 * ... * call *%r11 * * * kCFI: * * __cfi_foo: * movl $0x12345678, %eax * # 11 nops when CONFIG_CALL_PADDING * foo: * endbr64 # when IBT * ... code here ... * ret * * direct call: * call foo # / call foo+4 when IBT * * indirect call: * lea foo(%rip), %r11 * ... * movl $(-0x12345678), %r10d * addl -4(%r11), %r10d # -15 when CONFIG_CALL_PADDING * jz 1f * ud2 * 1:call *%r11 * * * FineIBT (builds as kCFI + CALL_PADDING + IBT + RETPOLINE and runtime patches into): * * __cfi_foo: * endbr64 * subl 0x12345678, %r10d * jz foo * ud2 * nop * foo: * osp nop3 # was endbr64 * ... code here ... * ret * * direct caller: * call foo / call foo+4 * * indirect caller: * lea foo(%rip), %r11 * ... * movl $0x12345678, %r10d * subl $16, %r11 * nop4 * call *%r11 * */ enum cfi_mode { … }; extern enum cfi_mode cfi_mode; struct pt_regs; #ifdef CONFIG_CFI_CLANG enum bug_trap_type handle_cfi_failure(struct pt_regs *regs); #define __bpfcall extern u32 cfi_bpf_hash; extern u32 cfi_bpf_subprog_hash; static inline int cfi_get_offset(void) { … } #define cfi_get_offset … extern u32 cfi_get_func_hash(void *func); #else static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs) { return BUG_TRAP_TYPE_NONE; } #define cfi_bpf_hash … #define cfi_bpf_subprog_hash … static inline u32 cfi_get_func_hash(void *func) { return 0; } #endif /* CONFIG_CFI_CLANG */ #if HAS_KERNEL_IBT == 1 #define CFI_NOSEAL(x) … #endif #endif /* _ASM_X86_CFI_H */