/* SPDX-License-Identifier: GPL-2.0 */1#ifndef _ASM_X86_CFI_H2#define _ASM_X86_CFI_H34/*5* Clang Control Flow Integrity (CFI) support.6*7* Copyright (C) 2022 Google LLC8*/9#include <linux/bug.h>10#include <asm/ibt.h>1112/*13* An overview of the various calling conventions...14*15* Traditional:16*17* foo:18* ... code here ...19* ret20*21* direct caller:22* call foo23*24* indirect caller:25* lea foo(%rip), %r1126* ...27* call *%r1128*29*30* IBT:31*32* foo:33* endbr6434* ... code here ...35* ret36*37* direct caller:38* call foo / call foo+439*40* indirect caller:41* lea foo(%rip), %r1142* ...43* call *%r1144*45*46* kCFI:47*48* __cfi_foo:49* movl $0x12345678, %eax50* # 11 nops when CONFIG_CALL_PADDING51* foo:52* endbr64 # when IBT53* ... code here ...54* ret55*56* direct call:57* call foo # / call foo+4 when IBT58*59* indirect call:60* lea foo(%rip), %r1161* ...62* movl $(-0x12345678), %r10d63* addl -4(%r11), %r10d # -15 when CONFIG_CALL_PADDING64* jz 1f65* ud266* 1:call *%r1167*68*69* FineIBT (builds as kCFI + CALL_PADDING + IBT + RETPOLINE and runtime patches into):70*71* __cfi_foo:72* endbr6473* subl 0x12345678, %eax74* jne.32,pn foo+375* foo:76* nopl -42(%rax) # was endbr6477* ... code here ...78* ret79*80* direct caller:81* call foo / call foo+482*83* indirect caller:84* lea foo(%rip), %r1185* ...86* movl $0x12345678, %eax87* lea -0x10(%r11), %r1188* nop589* call *%r1190*91*/92enum cfi_mode {93CFI_AUTO, /* FineIBT if hardware has IBT, otherwise kCFI */94CFI_OFF, /* Taditional / IBT depending on .config */95CFI_KCFI, /* Optionally CALL_PADDING, IBT, RETPOLINE */96CFI_FINEIBT, /* see arch/x86/kernel/alternative.c */97};9899extern enum cfi_mode cfi_mode;100101#ifdef CONFIG_FINEIBT_BHI102extern bool cfi_bhi;103#else104#define cfi_bhi (0)105#endif106107typedef u8 bhi_thunk[32];108extern bhi_thunk __bhi_args[];109extern bhi_thunk __bhi_args_end[];110111struct pt_regs;112113#ifdef CONFIG_CFI114enum bug_trap_type handle_cfi_failure(struct pt_regs *regs);115#define __bpfcall116117static inline int cfi_get_offset(void)118{119switch (cfi_mode) {120case CFI_FINEIBT:121return 16;122case CFI_KCFI:123if (IS_ENABLED(CONFIG_CALL_PADDING))124return 16;125return 5;126default:127return 0;128}129}130#define cfi_get_offset cfi_get_offset131132extern u32 cfi_get_func_hash(void *func);133#define cfi_get_func_hash cfi_get_func_hash134135extern int cfi_get_func_arity(void *func);136137#ifdef CONFIG_FINEIBT138extern bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type);139#else140static inline bool141decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type)142{143return false;144}145146#endif147148#else149static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)150{151return BUG_TRAP_TYPE_NONE;152}153static inline int cfi_get_func_arity(void *func)154{155return 0;156}157#endif /* CONFIG_CFI */158159#if HAS_KERNEL_IBT == 1160#define CFI_NOSEAL(x) asm(IBT_NOSEAL(__stringify(x)))161#endif162163#endif /* _ASM_X86_CFI_H */164165166