On Wed, Aug 26, 2026 at 1:59 AM Kees Cook <[email protected]> wrote:
>
> Implement x86_64-specific KCFI backend:
>
> - Implies -mindirect-branch-register since KCFI needs call target in
>   a register for typeid hash loading.
>
> - Function preamble generation with type IDs positioned at -(4+prefix_nops)
>   offset from function entry point.
>
> - Function-aligned KCFI preambles using calculated alignment padding NOPs:
>   aligned(prefix_nops + 5, $func_align) to maintain ability to call the
>   __cfi_ preamble directly in the case of Linux's FineIBT alternative
>   CFI sequences (live patched into place).
>
> - Type-id hash avoids generating ENDBR instruction in type IDs
>   (0xfa1e0ff3/0xfb1e0ff3 are incremented by 1 to prevent execution).
>
> - On-demand scratch register allocation strategy (r11 as needed), with
>   the clobbers added when KCFI is used.
>
> - Incompatible with -ffixed-r10 or -ffixed-r11.
>
> - Uses the .kcfi_traps section for debugger/runtime metadata.
>
> - Introduces -fsanitize-kcfi-arity to enable function arg count to be
>   represented in the kcfi hash preamble for FineIBT.
>
> Assembly Code Pattern layout required by Linux kernel:
>   movl $inverse_type_id, %r10d   ; Load expected type (0 - hash)
>   addl offset(%target), %r10d    ; Add stored type ID from preamble
>   je .Lkcfi_call                 ; Branch if types match (sum == 0)
>   .Lkcfi_trap: ud2               ; Undefined instruction trap on mismatch
>   .Lkcfi_call: call/jmp *%target ; Execute validated indirect transfer
>
> Build and run tested on x86_64 Linux kernel with various CPU errata
> handling alternatives, with and without FineIBT patching.
>
> gcc/ChangeLog:
>
>         * common.opt (fsanitize-kcfi-arity): New option.
>         * config/i386/i386.h: KCFI enables TARGET_INDIRECT_BRANCH_REGISTER.
>         * config/i386/i386-protos.h: Update ix86_output_call_insn.
>         * config/i386/i386-expand.cc (ix86_expand_call): Expand indirect
>         calls into KCFI RTL.
>         * config/i386/i386.cc (ix86_kcfi_mask_type_id): New function.
>         (ix86_output_call_insn): Emit KCFI assembly.
>         * config/i386/i386.md: Add KCFI RTL substitution patterns.
>         * doc/invoke.texi: Document x86 nuances.
>         * opts.cc (common_handle_option): Reset flag_sanitize_kcfi_arity.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/kcfi/kcfi-adjacency.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-basics.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-call-sharing.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-complex-addressing.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-direct-call-shapes.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-move-preservation.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-no-sanitize-inline.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-no-sanitize.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-offset-validation.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-patchable-entry-only.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-patchable-large.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-patchable-medium.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-patchable-prefix-only.c: Add x86 patterns.
>         * gcc.dg/kcfi/kcfi-tail-calls.c: Add x86 tail-call patterns.
>         * gcc.dg/kcfi/kcfi-trap-section.c: Add x86 trap patterns.
>         * gcc.dg/kcfi/kcfi-trap-section-per-func.c: New test.
>         * gcc.dg/kcfi/kcfi-x86-32bit.c: New test.
>         * gcc.dg/kcfi/kcfi-x86-arity.c: New test.
>         * gcc.dg/kcfi/kcfi-x86-fixed-r10.c: New test.
>         * gcc.dg/kcfi/kcfi-x86-fixed-r11.c: New test.
>         * gcc.dg/kcfi/kcfi-x86-retpoline-r11.c: New test.
>
> Signed-off-by: Kees Cook <[email protected]>

[...]

> +/* Apply x86-64 specific masking to KCFI type ID.  TYPE_ID is the 32-bit
> +   KCFI type identifier to potentially mask.  Returns the type ID with
> +   x86-64 specific adjustments to avoid embedding ENDBR instruction
> +   sequences in the type identifier values.  */
> +
> +static uint32_t
> +ix86_kcfi_mask_type_id (uint32_t type_id)
> +{
> +  /* Avoid embedding ENDBR instructions in KCFI type IDs.
> +     ENDBR64: 0xfa1e0ff3, ENDBR32: 0xfb1e0ff3
> +     If the type ID matches either instruction encoding, increment by 1.  */
> +  if (type_id == 0xfa1e0ff3U || type_id == 0xfb1e0ff3U)

This should use the ix86_endbr_immediate_operand predicate. Exactly
one target dependent immediate (0xfa1... for TARGET_64BIT and 0xfb1
for TARGET_32BIT) should be avoided only with flag_cf_protection &
CF_BRANCH. All this is handled in the predicate.

Uros.

Reply via email to