On Thu, Jun 18, 2026 at 02:09:50PM -0700, Kees Cook wrote:
> diff --git a/kernel/cfi.c b/kernel/cfi.c
> index 4dad04ead06c..8cb6a274c865 100644
> --- a/kernel/cfi.c
> +++ b/kernel/cfi.c
> @@ -8,12 +8,61 @@
> #include <linux/bpf.h>
> #include <linux/cfi_types.h>
> #include <linux/cfi.h>
> +#include <linux/rcupdate.h>
>
> bool cfi_warn __ro_after_init = IS_ENABLED(CONFIG_CFI_PERMISSIVE);
>
> +#if IS_ENABLED(CONFIG_CFI_KUNIT_TEST)
> +static bool (*cfi_kunit_failure_hook)(void);
> +
> +void cfi_kunit_set_failure_hook(bool (*hook)(void))
> +{
BUG_ON(cfi_kunit_failure_hook);
> + WRITE_ONCE(cfi_kunit_failure_hook, hook);
> +
> + /*
> + * On unregister, wait for any in-flight cfi_kunit_handled() caller to
> + * finish before the (possibly module-resident) hook can be freed.
> + */
> + if (!hook)
> + synchronize_rcu();
> +}
> +EXPORT_SYMBOL_GPL(cfi_kunit_set_failure_hook);
EXPORT_SYMBOL_FOR_MODULES(cfi_kunit_set_failure_hook, "cfi_kunit")
> +static bool cfi_kunit_handled(void)
> +{
> + bool (*hook)(void);
> + bool handled = false;
> +
> + /*
> + * Runs in CFI trap context (NMI-like on some arches); RCU is watching
> + * by this point, and the read-side section pairs with the
> + * synchronize_rcu() on unregister to keep the hook alive across the
> + * call.
> + */
> + rcu_read_lock();
> + hook = READ_ONCE(cfi_kunit_failure_hook);
> + if (hook)
> + handled = hook();
> + rcu_read_unlock();
> +
> + return handled;
> +}
> +#else
> +static inline bool cfi_kunit_handled(void) { return false; }
> +#endif
> +
> enum bug_trap_type report_cfi_failure(struct pt_regs *regs, unsigned long
> addr,
> unsigned long *target, u32 type)
> {
> + /*
> + * Let a registered KUnit test consume and count its own deliberate
> + * violations. If it claims the failure, suppress the report and tell
> + * the arch handler to skip the trap and resume the thread, regardless
> + * of CFI_PERMISSIVE.
> + */
> + if (cfi_kunit_handled())
> + return BUG_TRAP_TYPE_WARN;
Somewhat ironic to make an indirect call failure do an indirect call,
which can fail...
This is really rather horrible. Also, now all an attacker needs to do is
ensure cfi_kunit_handled() unconditionally returns true. IOW, no distro
must ever have this KUNIT crap enabled.