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

Commit 8712cc72 authored by Andrey Konovalov's avatar Andrey Konovalov Committed by Alistair Delva
Browse files

BACKPORT: kasan: add CONFIG_KASAN_GENERIC and CONFIG_KASAN_SW_TAGS

The conflict during backport is caused by the
include/linux/compiler_attributes.h file not being present.

(Upstream commit 2bd926b439b4cb6b9ed240a9781cd01958b53d85).

This commit splits the current CONFIG_KASAN config option into two:
1. CONFIG_KASAN_GENERIC, that enables the generic KASAN mode (the one
   that exists now);
2. CONFIG_KASAN_SW_TAGS, that enables the software tag-based KASAN mode.

The name CONFIG_KASAN_SW_TAGS is chosen as in the future we will have
another hardware tag-based KASAN mode, that will rely on hardware memory
tagging support in arm64.

With CONFIG_KASAN_SW_TAGS enabled, compiler options are changed to
instrument kernel files with -fsantize=kernel-hwaddress (except the ones
for which KASAN_SANITIZE := n is set).

Both CONFIG_KASAN_GENERIC and CONFIG_KASAN_SW_TAGS support both
CONFIG_KASAN_INLINE and CONFIG_KASAN_OUTLINE instrumentation modes.

This commit also adds empty placeholder (for now) implementation of
tag-based KASAN specific hooks inserted by the compiler and adjusts
common hooks implementation.

While this commit adds the CONFIG_KASAN_SW_TAGS config option, this option
is not selectable, as it depends on HAVE_ARCH_KASAN_SW_TAGS, which we will
enable once all the infrastracture code has been added.

Link: http://lkml.kernel.org/r/b2550106eb8a68b10fefbabce820910b115aa853.1544099024.git.andreyknvl@google.com


Signed-off-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Reviewed-by: default avatarAndrey Ryabinin <aryabinin@virtuozzo.com>
Reviewed-by: default avatarDmitry Vyukov <dvyukov@google.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Change-Id: Id95c0c0b6857c6b30f2bea4597aea6c90273ef89
Signed-off-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Bug: 128674696
parent 3915eb8b
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -15,13 +15,18 @@
/* all clang versions usable with the kernel support KASAN ABI version 5 */
#define KASAN_ABI_VERSION 5

/* __no_sanitize_address has been already defined compiler-gcc.h */
#undef __no_sanitize_address

#if __has_feature(address_sanitizer) || __has_feature(hwaddress_sanitizer)
/* emulate gcc's __SANITIZE_ADDRESS__ flag */
#if __has_feature(address_sanitizer)
#define __SANITIZE_ADDRESS__
#define __no_sanitize_address \
		__attribute__((no_sanitize("address", "hwaddress")))
#else
#define __no_sanitize_address
#endif

#define __no_sanitize_address __attribute__((no_sanitize("address")))

/*
 * Not all versions of clang implement the the type-generic versions
 * of the builtin overflow checkers. Fortunately, clang implements
+6 −0
Original line number Diff line number Diff line
@@ -183,6 +183,12 @@
#define KASAN_ABI_VERSION 3
#endif

#if __has_attribute(__no_sanitize_address__)
#define __no_sanitize_address __attribute__((no_sanitize_address))
#else
#define __no_sanitize_address
#endif

#if GCC_VERSION >= 50100
/*
 * Mark structures as requiring designated initializers.
+12 −4
Original line number Diff line number Diff line
@@ -45,8 +45,6 @@ void kasan_free_pages(struct page *page, unsigned int order);

void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
			slab_flags_t *flags);
void kasan_cache_shrink(struct kmem_cache *cache);
void kasan_cache_shutdown(struct kmem_cache *cache);

void kasan_poison_slab(struct page *page);
void kasan_unpoison_object_data(struct kmem_cache *cache, void *object);
@@ -97,8 +95,6 @@ static inline void kasan_free_pages(struct page *page, unsigned int order) {}
static inline void kasan_cache_create(struct kmem_cache *cache,
				      unsigned int *size,
				      slab_flags_t *flags) {}
static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}

static inline void kasan_poison_slab(struct page *page) {}
static inline void kasan_unpoison_object_data(struct kmem_cache *cache,
@@ -155,4 +151,16 @@ static inline size_t kasan_metadata_size(struct kmem_cache *cache) { return 0; }

#endif /* CONFIG_KASAN */

#ifdef CONFIG_KASAN_GENERIC

void kasan_cache_shrink(struct kmem_cache *cache);
void kasan_cache_shutdown(struct kmem_cache *cache);

#else /* CONFIG_KASAN_GENERIC */

static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}

#endif /* CONFIG_KASAN_GENERIC */

#endif /* LINUX_KASAN_H */
+76 −22
Original line number Diff line number Diff line
# This config refers to the generic KASAN mode.
config HAVE_ARCH_KASAN
	bool

if HAVE_ARCH_KASAN
config HAVE_ARCH_KASAN_SW_TAGS
	bool

config CC_HAS_KASAN_GENERIC
	def_bool $(cc-option, -fsanitize=kernel-address)

config CC_HAS_KASAN_SW_TAGS
	def_bool $(cc-option, -fsanitize=kernel-hwaddress)

config KASAN
	bool "KASan: runtime memory debugger"
	bool "KASAN: runtime memory debugger"
	depends on (HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC) || \
		   (HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS)
	depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB)
	help
	  Enables KASAN (KernelAddressSANitizer) - runtime memory debugger,
	  designed to find out-of-bounds accesses and use-after-free bugs.
	  See Documentation/dev-tools/kasan.rst for details.

choice
	prompt "KASAN mode"
	depends on KASAN
	default KASAN_GENERIC
	help
	  KASAN has two modes: generic KASAN (similar to userspace ASan,
	  x86_64/arm64/xtensa, enabled with CONFIG_KASAN_GENERIC) and
	  software tag-based KASAN (a version based on software memory
	  tagging, arm64 only, similar to userspace HWASan, enabled with
	  CONFIG_KASAN_SW_TAGS).
	  Both generic and tag-based KASAN are strictly debugging features.

config KASAN_GENERIC
	bool "Generic mode"
	depends on HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC
	depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB)
	select SLUB_DEBUG if SLUB
	select CONSTRUCTORS
	select STACKDEPOT
	help
	  Enables kernel address sanitizer - runtime memory debugger,
	  designed to find out-of-bounds accesses and use-after-free bugs.
	  This is strictly a debugging feature and it requires a gcc version
	  of 4.9.2 or later. Detection of out of bounds accesses to stack or
	  global variables requires gcc 5.0 or later.
	  This feature consumes about 1/8 of available memory and brings about
	  ~x3 performance slowdown.
	  Enables generic KASAN mode.
	  Supported in both GCC and Clang. With GCC it requires version 4.9.2
	  or later for basic support and version 5.0 or later for detection of
	  out-of-bounds accesses for stack and global variables and for inline
	  instrumentation mode (CONFIG_KASAN_INLINE). With Clang it requires
	  version 3.7.0 or later and it doesn't support detection of
	  out-of-bounds accesses for global variables yet.
	  This mode consumes about 1/8th of available memory at kernel start
	  and introduces an overhead of ~x1.5 for the rest of the allocations.
	  The performance slowdown is ~x3.
	  For better error detection enable CONFIG_STACKTRACE.
	  Currently CONFIG_KASAN doesn't work with CONFIG_DEBUG_SLAB
	  Currently CONFIG_KASAN_GENERIC doesn't work with CONFIG_DEBUG_SLAB
	  (the resulting kernel does not boot).

config KASAN_SW_TAGS
	bool "Software tag-based mode"
	depends on HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS
	depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB)
	select SLUB_DEBUG if SLUB
	select CONSTRUCTORS
	select STACKDEPOT
	help
	  Enables software tag-based KASAN mode.
	  This mode requires Top Byte Ignore support by the CPU and therefore
	  is only supported for arm64.
	  This mode requires Clang version 7.0.0 or later.
	  This mode consumes about 1/16th of available memory at kernel start
	  and introduces an overhead of ~20% for the rest of the allocations.
	  This mode may potentially introduce problems relating to pointer
	  casting and comparison, as it embeds tags into the top byte of each
	  pointer.
	  For better error detection enable CONFIG_STACKTRACE.
	  Currently CONFIG_KASAN_SW_TAGS doesn't work with CONFIG_DEBUG_SLAB
	  (the resulting kernel does not boot).

endchoice

config KASAN_EXTRA
	bool "KAsan: extra checks"
	depends on KASAN && DEBUG_KERNEL && !COMPILE_TEST
	bool "KASAN: extra checks"
	depends on KASAN_GENERIC && DEBUG_KERNEL && !COMPILE_TEST
	help
	  This enables further checks in the kernel address sanitizer, for now
	  it only includes the address-use-after-scope check that can lead
	  to excessive kernel stack usage, frame size warnings and longer
	  This enables further checks in generic KASAN, for now it only
	  includes the address-use-after-scope check that can lead to
	  excessive kernel stack usage, frame size warnings and longer
	  compile time.
	  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 has more

	  See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715

choice
	prompt "Instrumentation type"
@@ -53,16 +109,14 @@ config KASAN_INLINE
	  memory accesses. This is faster than outline (in some workloads
	  it gives about x2 boost over outline instrumentation), but
	  make kernel's .text size much bigger.
	  This requires a gcc version of 5.0 or later.
	  For CONFIG_KASAN_GENERIC this requires GCC 5.0 or later.

endchoice

config TEST_KASAN
	tristate "Module for testing kasan for bug detection"
	tristate "Module for testing KASAN for bug detection"
	depends on m && KASAN
	help
	  This is a test module doing various nasty things like
	  out of bounds accesses, use after free. It is useful for testing
	  kernel debugging features like kernel address sanitizer.

endif
	  kernel debugging features like KASAN.
+5 −1
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
KASAN_SANITIZE := n
UBSAN_SANITIZE_common.o := n
UBSAN_SANITIZE_generic.o := n
UBSAN_SANITIZE_tags.o := n
KCOV_INSTRUMENT := n

CFLAGS_REMOVE_generic.o = -pg
@@ -10,5 +11,8 @@ CFLAGS_REMOVE_generic.o = -pg

CFLAGS_common.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
CFLAGS_generic.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
CFLAGS_tags.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)

obj-y := common.o generic.o report.o init.o quarantine.o
obj-$(CONFIG_KASAN) := common.o init.o report.o
obj-$(CONFIG_KASAN_GENERIC) += generic.o quarantine.o
obj-$(CONFIG_KASAN_SW_TAGS) += tags.o
Loading