/* 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, %r10d74* jz foo75* ud276* nop77* foo:78* osp nop3 # was endbr6479* ... code here ...80* ret81*82* direct caller:83* call foo / call foo+484*85* indirect caller:86* lea foo(%rip), %r1187* ...88* movl $0x12345678, %r10d89* subl $16, %r1190* nop491* call *%r1192*93*/94enum cfi_mode {95CFI_AUTO, /* FineIBT if hardware has IBT, otherwise kCFI */96CFI_OFF, /* Taditional / IBT depending on .config */97CFI_KCFI, /* Optionally CALL_PADDING, IBT, RETPOLINE */98CFI_FINEIBT, /* see arch/x86/kernel/alternative.c */99};100101extern enum cfi_mode cfi_mode;102103#ifdef CONFIG_FINEIBT_BHI104extern bool cfi_bhi;105#else106#define cfi_bhi (0)107#endif108109typedef u8 bhi_thunk[32];110extern bhi_thunk __bhi_args[];111extern bhi_thunk __bhi_args_end[];112113struct pt_regs;114115#ifdef CONFIG_CFI_CLANG116enum bug_trap_type handle_cfi_failure(struct pt_regs *regs);117#define __bpfcall118119static inline int cfi_get_offset(void)120{121switch (cfi_mode) {122case CFI_FINEIBT:123return 16;124case CFI_KCFI:125if (IS_ENABLED(CONFIG_CALL_PADDING))126return 16;127return 5;128default:129return 0;130}131}132#define cfi_get_offset cfi_get_offset133134extern u32 cfi_get_func_hash(void *func);135#define cfi_get_func_hash cfi_get_func_hash136137extern int cfi_get_func_arity(void *func);138139#ifdef CONFIG_FINEIBT140extern bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type);141#else142static inline bool143decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type)144{145return false;146}147148#endif149150#else151static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)152{153return BUG_TRAP_TYPE_NONE;154}155static inline int cfi_get_func_arity(void *func)156{157return 0;158}159#endif /* CONFIG_CFI_CLANG */160161#if HAS_KERNEL_IBT == 1162#define CFI_NOSEAL(x) asm(IBT_NOSEAL(__stringify(x)))163#endif164165#endif /* _ASM_X86_CFI_H */166167168