0001
0002 #ifndef _ASM_X86_IBT_H
0003 #define _ASM_X86_IBT_H
0004
0005 #include <linux/types.h>
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #if defined(CONFIG_X86_KERNEL_IBT) && !defined(__DISABLE_EXPORTS)
0021
0022 #define HAS_KERNEL_IBT 1
0023
0024 #ifndef __ASSEMBLY__
0025
0026 #ifdef CONFIG_X86_64
0027 #define ASM_ENDBR "endbr64\n\t"
0028 #else
0029 #define ASM_ENDBR "endbr32\n\t"
0030 #endif
0031
0032 #define __noendbr __attribute__((nocf_check))
0033
0034
0035
0036
0037
0038
0039 #define IBT_NOSEAL(fname) \
0040 ".pushsection .discard.ibt_endbr_noseal\n\t" \
0041 _ASM_PTR fname "\n\t" \
0042 ".popsection\n\t"
0043
0044 static inline __attribute_const__ u32 gen_endbr(void)
0045 {
0046 u32 endbr;
0047
0048
0049
0050
0051
0052 asm ( "mov $~0xfa1e0ff3, %[endbr]\n\t"
0053 "not %[endbr]\n\t"
0054 : [endbr] "=&r" (endbr) );
0055
0056 return endbr;
0057 }
0058
0059 static inline __attribute_const__ u32 gen_endbr_poison(void)
0060 {
0061
0062
0063
0064
0065 return 0x001f0f66;
0066 }
0067
0068 static inline bool is_endbr(u32 val)
0069 {
0070 if (val == gen_endbr_poison())
0071 return true;
0072
0073 val &= ~0x01000000U;
0074 return val == gen_endbr();
0075 }
0076
0077 extern __noendbr u64 ibt_save(void);
0078 extern __noendbr void ibt_restore(u64 save);
0079
0080 #else
0081
0082 #ifdef CONFIG_X86_64
0083 #define ENDBR endbr64
0084 #else
0085 #define ENDBR endbr32
0086 #endif
0087
0088 #endif
0089
0090 #else
0091
0092 #define HAS_KERNEL_IBT 0
0093
0094 #ifndef __ASSEMBLY__
0095
0096 #define ASM_ENDBR
0097 #define IBT_NOSEAL(name)
0098
0099 #define __noendbr
0100
0101 static inline bool is_endbr(u32 val) { return false; }
0102
0103 static inline u64 ibt_save(void) { return 0; }
0104 static inline void ibt_restore(u64 save) { }
0105
0106 #else
0107
0108 #define ENDBR
0109
0110 #endif
0111
0112 #endif
0113
0114 #define ENDBR_INSN_SIZE (4*HAS_KERNEL_IBT)
0115
0116 #endif