extern void *const __initdata_cf_clobber_start[];
extern void *const __initdata_cf_clobber_end[];
+/*
+ * In CET-IBT enabled builds, clobber endbr64 instructions after altcall has
+ * finished optimising all indirect branches to direct ones.
+ */
+static void __init seal_endbr64(void)
+{
+ void *const *val;
+ unsigned int clobbered = 0;
+
+ if ( !cpu_has_xen_ibt )
+ return;
+
+ /*
+ * This is some minor structure (ab)use. We walk the entire contents
+ * of .init.{ro,}data.cf_clobber as if it were an array of pointers.
+ *
+ * If the pointer points into .text, and at an endbr64 instruction,
+ * nop out the endbr64. This causes the pointer to no longer be a
+ * legal indirect branch target under CET-IBT. This is a
+ * defence-in-depth measure, to reduce the options available to an
+ * adversary who has managed to hijack a function pointer.
+ */
+ for ( val = __initdata_cf_clobber_start;
+ val < __initdata_cf_clobber_end;
+ val++ )
+ {
+ void *ptr = *val;
+
+ if ( !is_kernel_text(ptr) || !is_endbr64(ptr) )
+ continue;
+
+ place_endbr64_poison(ptr);
+ clobbered++;
+ }
+
+ printk("altcall: Optimised away %u endbr64 instructions\n", clobbered);
+}
+
/*
* Replace instructions with better alternatives for this CPU type.
* This runs before SMP is initialized to avoid SMP problems with
* Clobber endbr64 instructions now that altcall has finished optimising
* all indirect branches to direct ones.
*/
- if ( force && cpu_has_xen_ibt && system_state < SYS_STATE_active )
- {
- void *const *val;
- unsigned int clobbered = 0;
-
- /*
- * This is some minor structure (ab)use. We walk the entire contents
- * of .init.{ro,}data.cf_clobber as if it were an array of pointers.
- *
- * If the pointer points into .text, and at an endbr64 instruction,
- * nop out the endbr64. This causes the pointer to no longer be a
- * legal indirect branch target under CET-IBT. This is a
- * defence-in-depth measure, to reduce the options available to an
- * adversary who has managed to hijack a function pointer.
- */
- for ( val = __initdata_cf_clobber_start;
- val < __initdata_cf_clobber_end;
- val++ )
- {
- void *ptr = *val;
-
- if ( !is_kernel_text(ptr) || !is_endbr64(ptr) )
- continue;
-
- place_endbr64_poison(ptr);
- clobbered++;
- }
-
- printk("altcall: Optimised away %u endbr64 instructions\n", clobbered);
- }
+ if ( force && system_state < SYS_STATE_active )
+ seal_endbr64();
return 0;
}