Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 895fc0a0 authored by Sami Tolvanen's avatar Sami Tolvanen Committed by Alistair Strachan
Browse files

ANDROID: add support for clang Control Flow Integrity (CFI)



This change adds the CONFIG_CFI_CLANG option, CFI error handling,
and a faster look-up table for cross module CFI checks.

Bug: 67506682
Change-Id: Ic009f0a629b552a0eb16e6d89808c7029e91447d
Signed-off-by: default avatarSami Tolvanen <samitolvanen@google.com>
parent a9fc9479
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -821,6 +821,32 @@ DISABLE_LTO := $(DISABLE_LTO_CLANG)
export LTO_CFLAGS DISABLE_LTO
endif

ifdef CONFIG_CFI_CLANG
cfi-clang-flags	+= -fsanitize=cfi $(call cc-option, -fsplit-lto-unit)
DISABLE_CFI_CLANG := -fno-sanitize=cfi
ifdef CONFIG_MODULES
cfi-clang-flags	+= -fsanitize-cfi-cross-dso
DISABLE_CFI_CLANG += -fno-sanitize-cfi-cross-dso
endif
ifdef CONFIG_CFI_PERMISSIVE
cfi-clang-flags	+= -fsanitize-recover=cfi -fno-sanitize-trap=cfi
endif

# also disable CFI when LTO is disabled
DISABLE_LTO_CLANG += $(DISABLE_CFI_CLANG)
# allow disabling only clang CFI where needed
export DISABLE_CFI_CLANG
endif

ifdef CONFIG_CFI
CFI_CFLAGS	:= $(cfi-clang-flags)
KBUILD_CFLAGS	+= $(CFI_CFLAGS)

DISABLE_CFI	:= $(DISABLE_CFI_CLANG)
DISABLE_LTO	+= $(DISABLE_CFI)
export CFI_CFLAGS DISABLE_CFI
endif

# arch Makefile may override CC so keep this after arch Makefile is included
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)

+28 −0
Original line number Diff line number Diff line
@@ -513,6 +513,34 @@ config LTO_CLANG

endchoice

config CFI
	bool

config CFI_PERMISSIVE
	bool "Use CFI in permissive mode"
	depends on CFI
	help
	  When selected, Control Flow Integrity (CFI) violations result in a
	  warning instead of a kernel panic. This option is useful for finding
	  CFI violations in drivers during development.

config CFI_CLANG
	bool "Use clang Control Flow Integrity (CFI) (EXPERIMENTAL)"
	depends on LTO_CLANG
	depends on KALLSYMS
	select CFI
	help
	  This option enables clang Control Flow Integrity (CFI), which adds
	  runtime checking for indirect function calls.

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

config HAVE_ARCH_WITHIN_STACK_FRAMES
	bool
	help
+3 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@
 */
#if defined(CONFIG_LD_DEAD_CODE_DATA_ELIMINATION) || defined(CONFIG_LTO_CLANG)
#define TEXT_MAIN .text .text.[0-9a-zA-Z_]*
#define TEXT_CFI_MAIN .text.[0-9a-zA-Z_]*.cfi
#define DATA_MAIN .data .data.[0-9a-zA-Z_]* .data..LPBX*
#define SDATA_MAIN .sdata .sdata.[0-9a-zA-Z_]*
#define RODATA_MAIN .rodata .rodata.[0-9a-zA-Z_]*
@@ -75,6 +76,7 @@
#define SBSS_MAIN .sbss .sbss.[0-9a-zA-Z_]*
#else
#define TEXT_MAIN .text
#define TEXT_CFI_MAIN .text.cfi
#define DATA_MAIN .data
#define SDATA_MAIN .sdata
#define RODATA_MAIN .rodata
@@ -491,6 +493,7 @@
#define TEXT_TEXT							\
		ALIGN_FUNCTION();					\
		*(.text.hot TEXT_MAIN .text.fixup .text.unlikely)	\
		*(TEXT_CFI_MAIN) 					\
		*(.text..refcount)					\
		*(.text..ftrace)					\
		*(.ref.text)						\

include/linux/cfi.h

0 → 100644
+38 −0
Original line number Diff line number Diff line
#ifndef _LINUX_CFI_H
#define _LINUX_CFI_H

#include <linux/stringify.h>

#ifdef CONFIG_CFI_CLANG
#ifdef CONFIG_MODULES

typedef void (*cfi_check_fn)(uint64_t, void *, void *);

/* Compiler-generated function in each module, and the kernel */
#define CFI_CHECK_FN		__cfi_check
#define CFI_CHECK_FN_NAME	__stringify(CFI_CHECK_FN)

extern void CFI_CHECK_FN(uint64_t, void *, void *);

#ifdef CONFIG_CFI_CLANG_SHADOW
extern void cfi_module_add(struct module *mod, unsigned long min_addr,
	unsigned long max_addr);

extern void cfi_module_remove(struct module *mod, unsigned long min_addr,
	unsigned long max_addr);
#else
static inline void cfi_module_add(struct module *mod, unsigned long min_addr,
	unsigned long max_addr)
{
}

static inline void cfi_module_remove(struct module *mod, unsigned long min_addr,
	unsigned long max_addr)
{
}
#endif /* CONFIG_CFI_CLANG_SHADOW */

#endif /* CONFIG_MODULES */
#endif /* CONFIG_CFI_CLANG */

#endif /* _LINUX_CFI_H */
+2 −0
Original line number Diff line number Diff line
@@ -49,4 +49,6 @@
#define __norecordmcount \
	__attribute__((__section__(".text..ftrace")))
#endif

#define __nocfi		__attribute__((no_sanitize("cfi")))
#endif
Loading