@@ -127,6 +127,10 @@ const unsigned char * const x86_nops[ASM_NOP_MAX+1] =
127
127
#endif
128
128
};
129
129
130
+ #ifdef CONFIG_FINEIBT
131
+ static bool cfi_paranoid __ro_after_init ;
132
+ #endif
133
+
130
134
#ifdef CONFIG_MITIGATION_ITS
131
135
132
136
static struct module * its_mod ;
@@ -137,8 +141,25 @@ static unsigned int its_offset;
137
141
static void * its_init_thunk (void * thunk , int reg )
138
142
{
139
143
u8 * bytes = thunk ;
144
+ int offset = 0 ;
140
145
int i = 0 ;
141
146
147
+ #ifdef CONFIG_FINEIBT
148
+ if (cfi_paranoid ) {
149
+ /*
150
+ * When ITS uses indirect branch thunk the fineibt_paranoid
151
+ * caller sequence doesn't fit in the caller site. So put the
152
+ * remaining part of the sequence (<ea> + JNE) into the ITS
153
+ * thunk.
154
+ */
155
+ bytes [i ++ ] = 0xea ; /* invalid instruction */
156
+ bytes [i ++ ] = 0x75 ; /* JNE */
157
+ bytes [i ++ ] = 0xfd ;
158
+
159
+ offset = 1 ;
160
+ }
161
+ #endif
162
+
142
163
if (reg >= 8 ) {
143
164
bytes [i ++ ] = 0x41 ; /* REX.B prefix */
144
165
reg -= 8 ;
@@ -147,7 +168,7 @@ static void *its_init_thunk(void *thunk, int reg)
147
168
bytes [i ++ ] = 0xe0 + reg ; /* jmp *reg */
148
169
bytes [i ++ ] = 0xcc ;
149
170
150
- return thunk ;
171
+ return thunk + offset ;
151
172
}
152
173
153
174
void its_init_mod (struct module * mod )
@@ -217,6 +238,17 @@ static void *its_allocate_thunk(int reg)
217
238
int size = 3 + (reg / 8 );
218
239
void * thunk ;
219
240
241
+ #ifdef CONFIG_FINEIBT
242
+ /*
243
+ * The ITS thunk contains an indirect jump and an int3 instruction so
244
+ * its size is 3 or 4 bytes depending on the register used. If CFI
245
+ * paranoid is used then 3 extra bytes are added in the ITS thunk to
246
+ * complete the fineibt_paranoid caller sequence.
247
+ */
248
+ if (cfi_paranoid )
249
+ size += 3 ;
250
+ #endif
251
+
220
252
if (!its_page || (its_offset + size - 1 ) >= PAGE_SIZE ) {
221
253
its_page = its_alloc ();
222
254
if (!its_page ) {
@@ -240,6 +272,18 @@ static void *its_allocate_thunk(int reg)
240
272
return its_init_thunk (thunk , reg );
241
273
}
242
274
275
+ u8 * its_static_thunk (int reg )
276
+ {
277
+ u8 * thunk = __x86_indirect_its_thunk_array [reg ];
278
+
279
+ #ifdef CONFIG_FINEIBT
280
+ /* Paranoid thunk starts 2 bytes before */
281
+ if (cfi_paranoid )
282
+ return thunk - 2 ;
283
+ #endif
284
+ return thunk ;
285
+ }
286
+
243
287
#endif
244
288
245
289
/*
@@ -775,8 +819,17 @@ static bool cpu_wants_indirect_its_thunk_at(unsigned long addr, int reg)
775
819
/* Lower-half of the cacheline? */
776
820
return !(addr & 0x20 );
777
821
}
822
+ #else /* CONFIG_MITIGATION_ITS */
823
+
824
+ #ifdef CONFIG_FINEIBT
825
+ static bool cpu_wants_indirect_its_thunk_at (unsigned long addr , int reg )
826
+ {
827
+ return false;
828
+ }
778
829
#endif
779
830
831
+ #endif /* CONFIG_MITIGATION_ITS */
832
+
780
833
/*
781
834
* Rewrite the compiler generated retpoline thunk calls.
782
835
*
@@ -893,6 +946,7 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end)
893
946
int len , ret ;
894
947
u8 bytes [16 ];
895
948
u8 op1 , op2 ;
949
+ u8 * dest ;
896
950
897
951
ret = insn_decode_kernel (& insn , addr );
898
952
if (WARN_ON_ONCE (ret < 0 ))
@@ -909,6 +963,12 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end)
909
963
910
964
case CALL_INSN_OPCODE :
911
965
case JMP32_INSN_OPCODE :
966
+ /* Check for cfi_paranoid + ITS */
967
+ dest = addr + insn .length + insn .immediate .value ;
968
+ if (dest [-1 ] == 0xea && (dest [0 ] & 0xf0 ) == 0x70 ) {
969
+ WARN_ON_ONCE (cfi_mode != CFI_FINEIBT );
970
+ continue ;
971
+ }
912
972
break ;
913
973
914
974
case 0x0f : /* escape */
@@ -1198,8 +1258,6 @@ int cfi_get_func_arity(void *func)
1198
1258
static bool cfi_rand __ro_after_init = true;
1199
1259
static u32 cfi_seed __ro_after_init ;
1200
1260
1201
- static bool cfi_paranoid __ro_after_init = false;
1202
-
1203
1261
/*
1204
1262
* Re-hash the CFI hash with a boot-time seed while making sure the result is
1205
1263
* not a valid ENDBR instruction.
@@ -1612,6 +1670,19 @@ static int cfi_rand_callers(s32 *start, s32 *end)
1612
1670
return 0 ;
1613
1671
}
1614
1672
1673
+ static int emit_paranoid_trampoline (void * addr , struct insn * insn , int reg , u8 * bytes )
1674
+ {
1675
+ u8 * thunk = (void * )__x86_indirect_its_thunk_array [reg ] - 2 ;
1676
+
1677
+ #ifdef CONFIG_MITIGATION_ITS
1678
+ u8 * tmp = its_allocate_thunk (reg );
1679
+ if (tmp )
1680
+ thunk = tmp ;
1681
+ #endif
1682
+
1683
+ return __emit_trampoline (addr , insn , bytes , thunk , thunk );
1684
+ }
1685
+
1615
1686
static int cfi_rewrite_callers (s32 * start , s32 * end )
1616
1687
{
1617
1688
s32 * s ;
@@ -1653,9 +1724,14 @@ static int cfi_rewrite_callers(s32 *start, s32 *end)
1653
1724
memcpy (bytes , fineibt_paranoid_start , fineibt_paranoid_size );
1654
1725
memcpy (bytes + fineibt_caller_hash , & hash , 4 );
1655
1726
1656
- ret = emit_indirect (op , 11 , bytes + fineibt_paranoid_ind );
1657
- if (WARN_ON_ONCE (ret != 3 ))
1658
- continue ;
1727
+ if (cpu_wants_indirect_its_thunk_at ((unsigned long )addr + fineibt_paranoid_ind , 11 )) {
1728
+ emit_paranoid_trampoline (addr + fineibt_caller_size ,
1729
+ & insn , 11 , bytes + fineibt_caller_size );
1730
+ } else {
1731
+ ret = emit_indirect (op , 11 , bytes + fineibt_paranoid_ind );
1732
+ if (WARN_ON_ONCE (ret != 3 ))
1733
+ continue ;
1734
+ }
1659
1735
1660
1736
text_poke_early (addr , bytes , fineibt_paranoid_size );
1661
1737
}
@@ -1882,29 +1958,66 @@ static bool decode_fineibt_bhi(struct pt_regs *regs, unsigned long *target, u32
1882
1958
return false;
1883
1959
}
1884
1960
1961
+ static bool is_paranoid_thunk (unsigned long addr )
1962
+ {
1963
+ u32 thunk ;
1964
+
1965
+ __get_kernel_nofault (& thunk , (u32 * )addr , u32 , Efault );
1966
+ return (thunk & 0x00FFFFFF ) == 0xfd75ea ;
1967
+
1968
+ Efault :
1969
+ return false;
1970
+ }
1971
+
1885
1972
/*
1886
1973
* regs->ip points to a LOCK Jcc.d8 instruction from the fineibt_paranoid_start[]
1887
- * sequence.
1974
+ * sequence, or to an invalid instruction (0xea) + Jcc.d8 for cfi_paranoid + ITS
1975
+ * thunk.
1888
1976
*/
1889
1977
static bool decode_fineibt_paranoid (struct pt_regs * regs , unsigned long * target , u32 * type )
1890
1978
{
1891
1979
unsigned long addr = regs -> ip - fineibt_paranoid_ud ;
1892
- u32 hash ;
1893
1980
1894
- if (!cfi_paranoid || ! is_cfi_trap ( addr + fineibt_caller_size - LEN_UD2 ) )
1981
+ if (!cfi_paranoid )
1895
1982
return false;
1896
1983
1897
- __get_kernel_nofault (& hash , addr + fineibt_caller_hash , u32 , Efault );
1898
- * target = regs -> r11 + fineibt_preamble_size ;
1899
- * type = regs -> r10 ;
1984
+ if (is_cfi_trap (addr + fineibt_caller_size - LEN_UD2 )) {
1985
+ * target = regs -> r11 + fineibt_preamble_size ;
1986
+ * type = regs -> r10 ;
1987
+
1988
+ /*
1989
+ * Since the trapping instruction is the exact, but LOCK prefixed,
1990
+ * Jcc.d8 that got us here, the normal fixup will work.
1991
+ */
1992
+ return true;
1993
+ }
1900
1994
1901
1995
/*
1902
- * Since the trapping instruction is the exact, but LOCK prefixed,
1903
- * Jcc.d8 that got us here, the normal fixup will work.
1996
+ * The cfi_paranoid + ITS thunk combination results in:
1997
+ *
1998
+ * 0: 41 ba 78 56 34 12 mov $0x12345678, %r10d
1999
+ * 6: 45 3b 53 f7 cmp -0x9(%r11), %r10d
2000
+ * a: 4d 8d 5b f0 lea -0x10(%r11), %r11
2001
+ * e: 2e e8 XX XX XX XX cs call __x86_indirect_paranoid_thunk_r11
2002
+ *
2003
+ * Where the paranoid_thunk looks like:
2004
+ *
2005
+ * 1d: <ea> (bad)
2006
+ * __x86_indirect_paranoid_thunk_r11:
2007
+ * 1e: 75 fd jne 1d
2008
+ * __x86_indirect_its_thunk_r11:
2009
+ * 20: 41 ff eb jmp *%r11
2010
+ * 23: cc int3
2011
+ *
1904
2012
*/
1905
- return true;
2013
+ if (is_paranoid_thunk (regs -> ip )) {
2014
+ * target = regs -> r11 + fineibt_preamble_size ;
2015
+ * type = regs -> r10 ;
2016
+
2017
+ regs -> ip = * target ;
2018
+ return true;
2019
+ }
1906
2020
1907
- Efault :
1908
2021
return false;
1909
2022
}
1910
2023
0 commit comments