Skip to content

Commit

Permalink
Merge tag 'kcfi-v6.1-rc1' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/kees/linux

Pull kcfi updates from Kees Cook:
 "This replaces the prior support for Clang's standard Control Flow
  Integrity (CFI) instrumentation, which has required a lot of special
  conditions (e.g. LTO) and work-arounds.

  The new implementation ("Kernel CFI") is specific to C, directly
  designed for the Linux kernel, and takes advantage of architectural
  features like x86's IBT. This series retains arm64 support and adds
  x86 support.

  GCC support is expected in the future[1], and additional "generic"
  architectural support is expected soon[2].

  Summary:

   - treewide: Remove old CFI support details

   - arm64: Replace Clang CFI support with Clang KCFI support

   - x86: Introduce Clang KCFI support"

Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107048 [1]
Link: https://github.com/samitolvanen/llvm-project/commits/kcfi_generic [2]

* tag 'kcfi-v6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (22 commits)
  x86: Add support for CONFIG_CFI_CLANG
  x86/purgatory: Disable CFI
  x86: Add types to indirectly called assembly functions
  x86/tools/relocs: Ignore __kcfi_typeid_ relocations
  kallsyms: Drop CONFIG_CFI_CLANG workarounds
  objtool: Disable CFI warnings
  objtool: Preserve special st_shndx indexes in elf_update_symbol
  treewide: Drop __cficanonical
  treewide: Drop WARN_ON_FUNCTION_MISMATCH
  treewide: Drop function_nocfi
  init: Drop __nocfi from __init
  arm64: Drop unneeded __nocfi attributes
  arm64: Add CFI error handling
  arm64: Add types to indirect called assembly functions
  psci: Fix the function type for psci_initcall_t
  lkdtm: Emit an indirect call for CFI tests
  cfi: Add type helper macros
  cfi: Switch to -fsanitize=kcfi
  cfi: Drop __CFI_ADDRESSABLE
  cfi: Remove CONFIG_CFI_CLANG_SHADOW
  ...
  • Loading branch information
torvalds committed Oct 4, 2022
2 parents 12ed00b + 3c516f8 commit 865dad2
Show file tree
Hide file tree
Showing 53 changed files with 425 additions and 553 deletions.
13 changes: 1 addition & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1001,18 +1001,7 @@ export CC_FLAGS_LTO
endif

ifdef CONFIG_CFI_CLANG
CC_FLAGS_CFI := -fsanitize=cfi \
-fsanitize-cfi-cross-dso \
-fno-sanitize-cfi-canonical-jump-tables \
-fno-sanitize-trap=cfi \
-fno-sanitize-blacklist

ifdef CONFIG_CFI_PERMISSIVE
CC_FLAGS_CFI += -fsanitize-recover=cfi
endif

# If LTO flags are filtered out, we must also filter out CFI.
CC_FLAGS_LTO += $(CC_FLAGS_CFI)
CC_FLAGS_CFI := -fsanitize=kcfi
KBUILD_CFLAGS += $(CC_FLAGS_CFI)
export CC_FLAGS_CFI
endif
Expand Down
18 changes: 5 additions & 13 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -744,11 +744,13 @@ config ARCH_SUPPORTS_CFI_CLANG
An architecture should select this option if it can support Clang's
Control-Flow Integrity (CFI) checking.

config ARCH_USES_CFI_TRAPS
bool

config CFI_CLANG
bool "Use Clang's Control Flow Integrity (CFI)"
depends on LTO_CLANG && ARCH_SUPPORTS_CFI_CLANG
depends on CLANG_VERSION >= 140000
select KALLSYMS
depends on ARCH_SUPPORTS_CFI_CLANG
depends on $(cc-option,-fsanitize=kcfi)
help
This option enables Clang’s forward-edge Control Flow Integrity
(CFI) checking, where the compiler injects a runtime check to each
Expand All @@ -760,16 +762,6 @@ config CFI_CLANG

https://clang.llvm.org/docs/ControlFlowIntegrity.html

config CFI_CLANG_SHADOW
bool "Use CFI shadow to speed up cross-module checks"
default y
depends on CFI_CLANG && MODULES
help
If you select this option, the kernel builds a fast look-up table of
CFI check functions in loaded modules to reduce performance overhead.

If unsure, say Y.

config CFI_PERMISSIVE
bool "Use CFI in permissive mode"
depends on CFI_CLANG
Expand Down
5 changes: 3 additions & 2 deletions arch/arm64/crypto/ghash-ce-core.S
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#include <linux/linkage.h>
#include <linux/cfi_types.h>
#include <asm/assembler.h>

SHASH .req v0
Expand Down Expand Up @@ -350,11 +351,11 @@ CPU_LE( rev64 T1.16b, T1.16b )
* void pmull_ghash_update(int blocks, u64 dg[], const char *src,
* struct ghash_key const *k, const char *head)
*/
SYM_FUNC_START(pmull_ghash_update_p64)
SYM_TYPED_FUNC_START(pmull_ghash_update_p64)
__pmull_ghash p64
SYM_FUNC_END(pmull_ghash_update_p64)

SYM_FUNC_START(pmull_ghash_update_p8)
SYM_TYPED_FUNC_START(pmull_ghash_update_p8)
__pmull_ghash p8
SYM_FUNC_END(pmull_ghash_update_p8)

Expand Down
3 changes: 2 additions & 1 deletion arch/arm64/crypto/sm3-ce-core.S
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#include <linux/linkage.h>
#include <linux/cfi_types.h>
#include <asm/assembler.h>

.irp b, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
Expand Down Expand Up @@ -73,7 +74,7 @@
* int blocks)
*/
.text
SYM_FUNC_START(sm3_ce_transform)
SYM_TYPED_FUNC_START(sm3_ce_transform)
/* load state */
ld1 {v8.4s-v9.4s}, [x0]
rev64 v8.4s, v8.4s
Expand Down
6 changes: 6 additions & 0 deletions arch/arm64/include/asm/brk-imm.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* 0x401: for compile time BRK instruction
* 0x800: kernel-mode BUG() and WARN() traps
* 0x9xx: tag-based KASAN trap (allowed values 0x900 - 0x9ff)
* 0x8xxx: Control-Flow Integrity traps
*/
#define KPROBES_BRK_IMM 0x004
#define UPROBES_BRK_IMM 0x005
Expand All @@ -28,4 +29,9 @@
#define KASAN_BRK_IMM 0x900
#define KASAN_BRK_MASK 0x0ff

#define CFI_BRK_IMM_TARGET GENMASK(4, 0)
#define CFI_BRK_IMM_TYPE GENMASK(9, 5)
#define CFI_BRK_IMM_BASE 0x8000
#define CFI_BRK_IMM_MASK (CFI_BRK_IMM_TARGET | CFI_BRK_IMM_TYPE)

#endif
2 changes: 1 addition & 1 deletion arch/arm64/include/asm/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
#define ARCH_SUPPORTS_FTRACE_OPS 1
#else
#define MCOUNT_ADDR ((unsigned long)function_nocfi(_mcount))
#define MCOUNT_ADDR ((unsigned long)_mcount)
#endif

/* The BL at the callsite's adjusted rec->ip */
Expand Down
4 changes: 4 additions & 0 deletions arch/arm64/include/asm/linkage.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@
SYM_START(name, SYM_L_WEAK, SYM_A_NONE) \
bti c ;

#define SYM_TYPED_FUNC_START(name) \
SYM_TYPED_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) \
bti c ;

#endif
4 changes: 2 additions & 2 deletions arch/arm64/include/asm/mmu_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ static inline void cpu_install_ttbr0(phys_addr_t ttbr0, unsigned long t0sz)
* Atomically replaces the active TTBR1_EL1 PGD with a new VA-compatible PGD,
* avoiding the possibility of conflicting TLB entries being allocated.
*/
static inline void __nocfi cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap)
static inline void cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap)
{
typedef void (ttbr_replace_func)(phys_addr_t);
extern ttbr_replace_func idmap_cpu_replace_ttbr1;
Expand All @@ -168,7 +168,7 @@ static inline void __nocfi cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap)
ttbr1 |= TTBR_CNP_BIT;
}

replace_phys = (void *)__pa_symbol(function_nocfi(idmap_cpu_replace_ttbr1));
replace_phys = (void *)__pa_symbol(idmap_cpu_replace_ttbr1);

__cpu_install_idmap(idmap);
replace_phys(ttbr1);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/acpi_parking_protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ static int acpi_parking_protocol_cpu_boot(unsigned int cpu)
* that read this address need to convert this address to the
* Boot-Loader's endianness before jumping.
*/
writeq_relaxed(__pa_symbol(function_nocfi(secondary_entry)),
writeq_relaxed(__pa_symbol(secondary_entry),
&mailbox->entry_point);
writel_relaxed(cpu_entry->gic_cpu_id, &mailbox->cpu_id);

Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/alternative.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ static void clean_dcache_range_nopatch(u64 start, u64 end)
} while (cur += d_size, cur < end);
}

static void __nocfi __apply_alternatives(struct alt_region *region, bool is_module,
static void __apply_alternatives(struct alt_region *region, bool is_module,
unsigned long *feature_mask)
{
struct alt_instr *alt;
Expand Down
5 changes: 3 additions & 2 deletions arch/arm64/kernel/cpu-reset.S
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

#include <linux/linkage.h>
#include <linux/cfi_types.h>
#include <asm/assembler.h>
#include <asm/sysreg.h>
#include <asm/virt.h>
Expand All @@ -28,7 +29,7 @@
* branch to what would be the reset vector. It must be executed with the
* flat identity mapping.
*/
SYM_CODE_START(cpu_soft_restart)
SYM_TYPED_FUNC_START(cpu_soft_restart)
mov_q x12, INIT_SCTLR_EL1_MMU_OFF
pre_disable_mmu_workaround
/*
Expand All @@ -47,6 +48,6 @@ SYM_CODE_START(cpu_soft_restart)
mov x1, x3 // arg1
mov x2, x4 // arg2
br x8
SYM_CODE_END(cpu_soft_restart)
SYM_FUNC_END(cpu_soft_restart)

.popsection
4 changes: 2 additions & 2 deletions arch/arm64/kernel/cpufeature.c
Original file line number Diff line number Diff line change
Expand Up @@ -1685,7 +1685,7 @@ static phys_addr_t kpti_ng_pgd_alloc(int shift)
return kpti_ng_temp_alloc;
}

static void __nocfi
static void
kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
{
typedef void (kpti_remap_fn)(int, int, phys_addr_t, unsigned long);
Expand Down Expand Up @@ -1713,7 +1713,7 @@ kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
if (arm64_use_ng_mappings)
return;

remap_fn = (void *)__pa_symbol(function_nocfi(idmap_kpti_install_ng_mappings));
remap_fn = (void *)__pa_symbol(idmap_kpti_install_ng_mappings);

if (!cpu) {
alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
unsigned long pc;
u32 new;

pc = (unsigned long)function_nocfi(ftrace_call);
pc = (unsigned long)ftrace_call;
new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func,
AARCH64_INSN_BRANCH_LINK);

Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ void machine_kexec(struct kimage *kimage)
typeof(cpu_soft_restart) *restart;

cpu_install_idmap();
restart = (void *)__pa_symbol(function_nocfi(cpu_soft_restart));
restart = (void *)__pa_symbol(cpu_soft_restart);
restart(is_hyp_nvhe(), kimage->start, kimage->arch.dtb_mem,
0, 0);
} else {
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/psci.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static int __init cpu_psci_cpu_prepare(unsigned int cpu)

static int cpu_psci_cpu_boot(unsigned int cpu)
{
phys_addr_t pa_secondary_entry = __pa_symbol(function_nocfi(secondary_entry));
phys_addr_t pa_secondary_entry = __pa_symbol(secondary_entry);
int err = psci_ops.cpu_on(cpu_logical_map(cpu), pa_secondary_entry);
if (err)
pr_err("failed to boot CPU%d (%d)\n", cpu, err);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/smp_spin_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static int smp_spin_table_cpu_init(unsigned int cpu)
static int smp_spin_table_cpu_prepare(unsigned int cpu)
{
__le64 __iomem *release_addr;
phys_addr_t pa_holding_pen = __pa_symbol(function_nocfi(secondary_holding_pen));
phys_addr_t pa_holding_pen = __pa_symbol(secondary_holding_pen);

if (!cpu_release_addr[cpu])
return -ENODEV;
Expand Down
47 changes: 44 additions & 3 deletions arch/arm64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/syscalls.h>
#include <linux/mm_types.h>
#include <linux/kasan.h>
#include <linux/cfi.h>

#include <asm/atomic.h>
#include <asm/bug.h>
Expand Down Expand Up @@ -991,6 +992,38 @@ static struct break_hook bug_break_hook = {
.imm = BUG_BRK_IMM,
};

#ifdef CONFIG_CFI_CLANG
static int cfi_handler(struct pt_regs *regs, unsigned long esr)
{
unsigned long target;
u32 type;

target = pt_regs_read_reg(regs, FIELD_GET(CFI_BRK_IMM_TARGET, esr));
type = (u32)pt_regs_read_reg(regs, FIELD_GET(CFI_BRK_IMM_TYPE, esr));

switch (report_cfi_failure(regs, regs->pc, &target, type)) {
case BUG_TRAP_TYPE_BUG:
die("Oops - CFI", regs, 0);
break;

case BUG_TRAP_TYPE_WARN:
break;

default:
return DBG_HOOK_ERROR;
}

arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
return DBG_HOOK_HANDLED;
}

static struct break_hook cfi_break_hook = {
.fn = cfi_handler,
.imm = CFI_BRK_IMM_BASE,
.mask = CFI_BRK_IMM_MASK,
};
#endif /* CONFIG_CFI_CLANG */

static int reserved_fault_handler(struct pt_regs *regs, unsigned long esr)
{
pr_err("%s generated an invalid instruction at %pS!\n",
Expand Down Expand Up @@ -1052,17 +1085,22 @@ static struct break_hook kasan_break_hook = {
};
#endif


#define esr_comment(esr) ((esr) & ESR_ELx_BRK64_ISS_COMMENT_MASK)

/*
* Initial handler for AArch64 BRK exceptions
* This handler only used until debug_traps_init().
*/
int __init early_brk64(unsigned long addr, unsigned long esr,
struct pt_regs *regs)
{
#ifdef CONFIG_CFI_CLANG
if ((esr_comment(esr) & ~CFI_BRK_IMM_MASK) == CFI_BRK_IMM_BASE)
return cfi_handler(regs, esr) != DBG_HOOK_HANDLED;
#endif
#ifdef CONFIG_KASAN_SW_TAGS
unsigned long comment = esr & ESR_ELx_BRK64_ISS_COMMENT_MASK;

if ((comment & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
if ((esr_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
return kasan_handler(regs, esr) != DBG_HOOK_HANDLED;
#endif
return bug_handler(regs, esr) != DBG_HOOK_HANDLED;
Expand All @@ -1071,6 +1109,9 @@ int __init early_brk64(unsigned long addr, unsigned long esr,
void __init trap_init(void)
{
register_kernel_break_hook(&bug_break_hook);
#ifdef CONFIG_CFI_CLANG
register_kernel_break_hook(&cfi_break_hook);
#endif
register_kernel_break_hook(&fault_break_hook);
#ifdef CONFIG_KASAN_SW_TAGS
register_kernel_break_hook(&kasan_break_hook);
Expand Down
3 changes: 2 additions & 1 deletion arch/arm64/kernel/vdso/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ ccflags-y += -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
# kernel with CONFIG_WERROR enabled.
CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) \
$(RANDSTRUCT_CFLAGS) $(GCC_PLUGINS_CFLAGS) \
$(CC_FLAGS_LTO) -Wmissing-prototypes -Wmissing-declarations
$(CC_FLAGS_LTO) $(CC_FLAGS_CFI) \
-Wmissing-prototypes -Wmissing-declarations
KASAN_SANITIZE := n
KCSAN_SANITIZE := n
UBSAN_SANITIZE := n
Expand Down
5 changes: 3 additions & 2 deletions arch/arm64/mm/proc.S
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/pgtable.h>
#include <linux/cfi_types.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
#include <asm/asm_pointer_auth.h>
Expand Down Expand Up @@ -185,7 +186,7 @@ SYM_FUNC_END(cpu_do_resume)
* This is the low-level counterpart to cpu_replace_ttbr1, and should not be
* called by anything else. It can only be executed from a TTBR0 mapping.
*/
SYM_FUNC_START(idmap_cpu_replace_ttbr1)
SYM_TYPED_FUNC_START(idmap_cpu_replace_ttbr1)
save_and_disable_daif flags=x2

__idmap_cpu_set_reserved_ttbr1 x1, x3
Expand Down Expand Up @@ -253,7 +254,7 @@ SYM_FUNC_END(idmap_cpu_replace_ttbr1)
SYM_DATA(__idmap_kpti_flag, .long 1)
.popsection

SYM_FUNC_START(idmap_kpti_install_ng_mappings)
SYM_TYPED_FUNC_START(idmap_kpti_install_ng_mappings)
cpu .req w0
temp_pte .req x0
num_cpus .req w1
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ config X86
select ARCH_SUPPORTS_PAGE_TABLE_CHECK if X86_64
select ARCH_SUPPORTS_NUMA_BALANCING if X86_64
select ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP if NR_CPUS <= 4096
select ARCH_SUPPORTS_CFI_CLANG if X86_64
select ARCH_USES_CFI_TRAPS if X86_64 && CFI_CLANG
select ARCH_SUPPORTS_LTO_CLANG
select ARCH_SUPPORTS_LTO_CLANG_THIN
select ARCH_USE_BUILTIN_BSWAP
Expand Down
5 changes: 3 additions & 2 deletions arch/x86/crypto/blowfish-x86_64-asm_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#include <linux/linkage.h>
#include <linux/cfi_types.h>

.file "blowfish-x86_64-asm.S"
.text
Expand Down Expand Up @@ -141,7 +142,7 @@ SYM_FUNC_START(__blowfish_enc_blk)
RET;
SYM_FUNC_END(__blowfish_enc_blk)

SYM_FUNC_START(blowfish_dec_blk)
SYM_TYPED_FUNC_START(blowfish_dec_blk)
/* input:
* %rdi: ctx
* %rsi: dst
Expand Down Expand Up @@ -332,7 +333,7 @@ SYM_FUNC_START(__blowfish_enc_blk_4way)
RET;
SYM_FUNC_END(__blowfish_enc_blk_4way)

SYM_FUNC_START(blowfish_dec_blk_4way)
SYM_TYPED_FUNC_START(blowfish_dec_blk_4way)
/* input:
* %rdi: ctx
* %rsi: dst
Expand Down
Loading

0 comments on commit 865dad2

Please sign in to comment.