[RFC PATCH 00/21] KCFI support

Sami Tolvanen
2022-04-29T20:38:22Z

KCFI is a proposed forward-edge control-flow integrity scheme for
Clang, which is more suitable for kernel use than the existing CFI
scheme used by CONFIG_CFI_CLANG. KCFI doesn't require LTO, doesn't
alter function references to point to a jump table, and won't break
function address equality. The latest LLVM patches are here:

https://reviews.llvm.org/D119296
https://reviews.llvm.org/D124211

This RFC series replaces the current arm64 CFI implementation with
KCFI and adds support for x86_64.

The proposed compiler patches add a built-in function that allows
CFI checks to be disabled for specific indirect calls. This is
necessary to prevent unnecessary checks from being emitted for
static_call trampoline calls that are later patched into direct
calls. However, as the call expression must be passed as an argument
to the built-in, this requires changing the static_call macro API to
include the call arguments. Patch 14 changes the macros to accept
arguments and patch 15 disables checks for the generated calls.

KCFI also requires assembly functions that are indirectly called
from C code to be annotated with type identifiers. As type
information is only available in C, the compiler emits expected
type identifiers into the symbol table, so they can be referenced
from assembly without having to hardcode type hashes. Patch 7 adds
helper macros for annotating functions, and patches 8 and 18 add
annotations.

In case of a type mismatch, KCFI always traps. To support error
handling, the compiler generates a .kcfi_traps section that contains
the locations of each trap. Patches 9 and 21 add arch-specific error
handlers. In addition, to support x86_64, objtool must be able to
identify KCFI type identifiers that are emitted before function
entries. The compiler generates an additional .kcfi_types section,
which points to each emitted type identifier. Patch 16 adds objtool
support.

To test this series, you'll need to compile your own Clang toolchain
with the patches linked above. You can also find the complete source
tree here:

https://github.com/samitolvanen/llvm-project/commits/kcfi-rfc

This series is also available in GitHub:

https://github.com/samitolvanen/linux/commits/kcfi-rfc

Sami Tolvanen (21):
efi/libstub: Filter out CC_FLAGS_CFI
arm64/vdso: Filter out CC_FLAGS_CFI
kallsyms: Ignore __kcfi_typeid_
cfi: Remove CONFIG_CFI_CLANG_SHADOW
cfi: Drop __CFI_ADDRESSABLE
cfi: Switch to -fsanitize=kcfi
cfi: Add type helper macros
arm64/crypto: Add types to indirect called assembly functions
arm64: Add CFI error handling
treewide: Drop function_nocfi
treewide: Drop WARN_ON_FUNCTION_MISMATCH
treewide: Drop __cficanonical
cfi: Add the cfi_unchecked macro
treewide: static_call: Pass call arguments to the macro
static_call: Use cfi_unchecked
objtool: Add support for CONFIG_CFI_CLANG
x86/tools/relocs: Ignore __kcfi_typeid_ relocations
x86: Add types to indirect called assembly functions
x86/purgatory: Disable CFI
x86/vdso: Disable CFI
x86: Add support for CONFIG_CFI_CLANG

Makefile | 13 +-
arch/Kconfig | 18 +-
arch/arm/include/asm/paravirt.h | 2 +-
arch/arm64/crypto/ghash-ce-core.S | 5 +-
arch/arm64/crypto/sm3-ce-core.S | 3 +-
arch/arm64/include/asm/brk-imm.h | 2 +
arch/arm64/include/asm/compiler.h | 16 -
arch/arm64/include/asm/ftrace.h | 2 +-
arch/arm64/include/asm/insn.h | 1 +
arch/arm64/include/asm/mmu_context.h | 2 +-
arch/arm64/include/asm/paravirt.h | 2 +-
arch/arm64/kernel/acpi_parking_protocol.c | 2 +-
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/ftrace.c | 2 +-
arch/arm64/kernel/machine_kexec.c | 2 +-
arch/arm64/kernel/psci.c | 2 +-
arch/arm64/kernel/smp_spin_table.c | 2 +-
arch/arm64/kernel/traps.c | 57 ++++
arch/arm64/kernel/vdso/Makefile | 3 +-
arch/x86/Kconfig | 1 +
arch/x86/crypto/aesni-intel_glue.c | 7 +-
arch/x86/crypto/blowfish-x86_64-asm_64.S | 5 +-
arch/x86/entry/vdso/Makefile | 3 +-
arch/x86/events/core.c | 40 +--
arch/x86/include/asm/kvm_host.h | 6 +-
arch/x86/include/asm/linkage.h | 7 +
arch/x86/include/asm/paravirt.h | 4 +-
arch/x86/kernel/traps.c | 39 ++-
arch/x86/kvm/cpuid.c | 2 +-
arch/x86/kvm/hyperv.c | 4 +-
arch/x86/kvm/irq.c | 2 +-
arch/x86/kvm/kvm_cache_regs.h | 10 +-
arch/x86/kvm/lapic.c | 32 +-
arch/x86/kvm/mmu.h | 4 +-
arch/x86/kvm/mmu/mmu.c | 8 +-
arch/x86/kvm/mmu/spte.c | 4 +-
arch/x86/kvm/pmu.c | 4 +-
arch/x86/kvm/trace.h | 4 +-
arch/x86/kvm/x86.c | 326 ++++++++++-----------
arch/x86/kvm/x86.h | 4 +-
arch/x86/kvm/xen.c | 4 +-
arch/x86/lib/memcpy_64.S | 3 +-
arch/x86/purgatory/Makefile | 4 +
arch/x86/tools/relocs.c | 1 +
drivers/cpufreq/amd-pstate.c | 8 +-
drivers/firmware/efi/libstub/Makefile | 2 +
drivers/firmware/psci/psci.c | 4 +-
drivers/misc/lkdtm/usercopy.c | 2 +-
include/asm-generic/bug.h | 16 -
include/asm-generic/vmlinux.lds.h | 38 +--
include/linux/cfi.h | 50 ++--
include/linux/cfi_types.h | 57 ++++
include/linux/compiler-clang.h | 10 +-
include/linux/compiler.h | 16 +-
include/linux/compiler_types.h | 4 +-
include/linux/entry-common.h | 2 +-
include/linux/init.h | 4 +-
include/linux/kernel.h | 2 +-
include/linux/module.h | 8 +-
include/linux/pci.h | 4 +-
include/linux/perf_event.h | 6 +-
include/linux/sched.h | 2 +-
include/linux/static_call.h | 18 +-
include/linux/static_call_types.h | 13 +-
include/linux/tracepoint.h | 2 +-
kernel/cfi.c | 340 ++++------------------
kernel/kthread.c | 3 +-
kernel/module.c | 49 +---
kernel/static_call_inline.c | 2 +-
kernel/trace/bpf_trace.c | 2 +-
kernel/workqueue.c | 2 +-
scripts/Makefile.build | 3 +-
scripts/kallsyms.c | 1 +
scripts/link-vmlinux.sh | 3 +
scripts/module.lds.S | 24 +-
security/keys/trusted-keys/trusted_core.c | 14 +-
tools/include/linux/static_call_types.h | 13 +-
tools/objtool/arch/x86/include/arch/elf.h | 2 +
tools/objtool/builtin-check.c | 3 +-
tools/objtool/check.c | 128 +++++++-
tools/objtool/elf.c | 13 +
tools/objtool/include/objtool/arch.h | 1 +
tools/objtool/include/objtool/builtin.h | 2 +-
tools/objtool/include/objtool/elf.h | 2 +
84 files changed, 748 insertions(+), 793 deletions(-)
create mode 100644 include/linux/cfi_types.h

--
2.36.0.464.gb9c8b46e94-goog