Skip to content

Commit 2bd926b

Browse files
xairytorvalds
authored andcommitted
kasan: add CONFIG_KASAN_GENERIC and CONFIG_KASAN_SW_TAGS
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: Andrey Konovalov <andreyknvl@google.com> Reviewed-by: Andrey Ryabinin <aryabinin@virtuozzo.com> Reviewed-by: Dmitry 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent b938fcf commit 2bd926b

File tree

11 files changed

+214
-66
lines changed

11 files changed

+214
-66
lines changed

include/linux/compiler-clang.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616
/* all clang versions usable with the kernel support KASAN ABI version 5 */
1717
#define KASAN_ABI_VERSION 5
1818

19+
#if __has_feature(address_sanitizer) || __has_feature(hwaddress_sanitizer)
1920
/* emulate gcc's __SANITIZE_ADDRESS__ flag */
20-
#if __has_feature(address_sanitizer)
2121
#define __SANITIZE_ADDRESS__
22+
#define __no_sanitize_address \
23+
__attribute__((no_sanitize("address", "hwaddress")))
24+
#else
25+
#define __no_sanitize_address
2226
#endif
2327

2428
/*

include/linux/compiler-gcc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@
143143
#define KASAN_ABI_VERSION 3
144144
#endif
145145

146+
#if __has_attribute(__no_sanitize_address__)
147+
#define __no_sanitize_address __attribute__((no_sanitize_address))
148+
#else
149+
#define __no_sanitize_address
150+
#endif
151+
146152
#if GCC_VERSION >= 50100
147153
#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
148154
#endif

include/linux/compiler_attributes.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -199,19 +199,6 @@
199199
*/
200200
#define __noreturn __attribute__((__noreturn__))
201201

202-
/*
203-
* Optional: only supported since gcc >= 4.8
204-
* Optional: not supported by icc
205-
*
206-
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-no_005fsanitize_005faddress-function-attribute
207-
* clang: https://clang.llvm.org/docs/AttributeReference.html#no-sanitize-address-no-address-safety-analysis
208-
*/
209-
#if __has_attribute(__no_sanitize_address__)
210-
# define __no_sanitize_address __attribute__((__no_sanitize_address__))
211-
#else
212-
# define __no_sanitize_address
213-
#endif
214-
215202
/*
216203
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute
217204
* clang: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute

include/linux/kasan.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ void kasan_free_pages(struct page *page, unsigned int order);
4545

4646
void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
4747
slab_flags_t *flags);
48-
void kasan_cache_shrink(struct kmem_cache *cache);
49-
void kasan_cache_shutdown(struct kmem_cache *cache);
5048

5149
void kasan_poison_slab(struct page *page);
5250
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) {}
9795
static inline void kasan_cache_create(struct kmem_cache *cache,
9896
unsigned int *size,
9997
slab_flags_t *flags) {}
100-
static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
101-
static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
10298

10399
static inline void kasan_poison_slab(struct page *page) {}
104100
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; }
155151

156152
#endif /* CONFIG_KASAN */
157153

154+
#ifdef CONFIG_KASAN_GENERIC
155+
156+
void kasan_cache_shrink(struct kmem_cache *cache);
157+
void kasan_cache_shutdown(struct kmem_cache *cache);
158+
159+
#else /* CONFIG_KASAN_GENERIC */
160+
161+
static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
162+
static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
163+
164+
#endif /* CONFIG_KASAN_GENERIC */
165+
158166
#endif /* LINUX_KASAN_H */

lib/Kconfig.kasan

Lines changed: 76 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,92 @@
1+
# This config refers to the generic KASAN mode.
12
config HAVE_ARCH_KASAN
23
bool
34

4-
if HAVE_ARCH_KASAN
5+
config HAVE_ARCH_KASAN_SW_TAGS
6+
bool
7+
8+
config CC_HAS_KASAN_GENERIC
9+
def_bool $(cc-option, -fsanitize=kernel-address)
10+
11+
config CC_HAS_KASAN_SW_TAGS
12+
def_bool $(cc-option, -fsanitize=kernel-hwaddress)
513

614
config KASAN
7-
bool "KASan: runtime memory debugger"
15+
bool "KASAN: runtime memory debugger"
16+
depends on (HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC) || \
17+
(HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS)
18+
depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB)
19+
help
20+
Enables KASAN (KernelAddressSANitizer) - runtime memory debugger,
21+
designed to find out-of-bounds accesses and use-after-free bugs.
22+
See Documentation/dev-tools/kasan.rst for details.
23+
24+
choice
25+
prompt "KASAN mode"
26+
depends on KASAN
27+
default KASAN_GENERIC
28+
help
29+
KASAN has two modes: generic KASAN (similar to userspace ASan,
30+
x86_64/arm64/xtensa, enabled with CONFIG_KASAN_GENERIC) and
31+
software tag-based KASAN (a version based on software memory
32+
tagging, arm64 only, similar to userspace HWASan, enabled with
33+
CONFIG_KASAN_SW_TAGS).
34+
Both generic and tag-based KASAN are strictly debugging features.
35+
36+
config KASAN_GENERIC
37+
bool "Generic mode"
38+
depends on HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC
839
depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB)
940
select SLUB_DEBUG if SLUB
1041
select CONSTRUCTORS
1142
select STACKDEPOT
1243
help
13-
Enables kernel address sanitizer - runtime memory debugger,
14-
designed to find out-of-bounds accesses and use-after-free bugs.
15-
This is strictly a debugging feature and it requires a gcc version
16-
of 4.9.2 or later. Detection of out of bounds accesses to stack or
17-
global variables requires gcc 5.0 or later.
18-
This feature consumes about 1/8 of available memory and brings about
19-
~x3 performance slowdown.
44+
Enables generic KASAN mode.
45+
Supported in both GCC and Clang. With GCC it requires version 4.9.2
46+
or later for basic support and version 5.0 or later for detection of
47+
out-of-bounds accesses for stack and global variables and for inline
48+
instrumentation mode (CONFIG_KASAN_INLINE). With Clang it requires
49+
version 3.7.0 or later and it doesn't support detection of
50+
out-of-bounds accesses for global variables yet.
51+
This mode consumes about 1/8th of available memory at kernel start
52+
and introduces an overhead of ~x1.5 for the rest of the allocations.
53+
The performance slowdown is ~x3.
2054
For better error detection enable CONFIG_STACKTRACE.
21-
Currently CONFIG_KASAN doesn't work with CONFIG_DEBUG_SLAB
55+
Currently CONFIG_KASAN_GENERIC doesn't work with CONFIG_DEBUG_SLAB
2256
(the resulting kernel does not boot).
2357

58+
config KASAN_SW_TAGS
59+
bool "Software tag-based mode"
60+
depends on HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS
61+
depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB)
62+
select SLUB_DEBUG if SLUB
63+
select CONSTRUCTORS
64+
select STACKDEPOT
65+
help
66+
Enables software tag-based KASAN mode.
67+
This mode requires Top Byte Ignore support by the CPU and therefore
68+
is only supported for arm64.
69+
This mode requires Clang version 7.0.0 or later.
70+
This mode consumes about 1/16th of available memory at kernel start
71+
and introduces an overhead of ~20% for the rest of the allocations.
72+
This mode may potentially introduce problems relating to pointer
73+
casting and comparison, as it embeds tags into the top byte of each
74+
pointer.
75+
For better error detection enable CONFIG_STACKTRACE.
76+
Currently CONFIG_KASAN_SW_TAGS doesn't work with CONFIG_DEBUG_SLAB
77+
(the resulting kernel does not boot).
78+
79+
endchoice
80+
2481
config KASAN_EXTRA
25-
bool "KAsan: extra checks"
26-
depends on KASAN && DEBUG_KERNEL && !COMPILE_TEST
82+
bool "KASAN: extra checks"
83+
depends on KASAN_GENERIC && DEBUG_KERNEL && !COMPILE_TEST
2784
help
28-
This enables further checks in the kernel address sanitizer, for now
29-
it only includes the address-use-after-scope check that can lead
30-
to excessive kernel stack usage, frame size warnings and longer
85+
This enables further checks in generic KASAN, for now it only
86+
includes the address-use-after-scope check that can lead to
87+
excessive kernel stack usage, frame size warnings and longer
3188
compile time.
32-
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 has more
33-
89+
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715
3490

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

58114
endchoice
59115

@@ -67,11 +123,9 @@ config KASAN_S390_4_LEVEL_PAGING
67123
4-level paging instead.
68124

69125
config TEST_KASAN
70-
tristate "Module for testing kasan for bug detection"
126+
tristate "Module for testing KASAN for bug detection"
71127
depends on m && KASAN
72128
help
73129
This is a test module doing various nasty things like
74130
out of bounds accesses, use after free. It is useful for testing
75-
kernel debugging features like kernel address sanitizer.
76-
77-
endif
131+
kernel debugging features like KASAN.

mm/kasan/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
KASAN_SANITIZE := n
33
UBSAN_SANITIZE_common.o := n
44
UBSAN_SANITIZE_generic.o := n
5+
UBSAN_SANITIZE_tags.o := n
56
KCOV_INSTRUMENT := n
67

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

1112
CFLAGS_common.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
1213
CFLAGS_generic.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
14+
CFLAGS_tags.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
1315

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

mm/kasan/generic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* This file contains core KASAN code.
2+
* This file contains core generic KASAN code.
33
*
44
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
55
* Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>

mm/kasan/kasan.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ void kasan_report(unsigned long addr, size_t size,
114114
bool is_write, unsigned long ip);
115115
void kasan_report_invalid_free(void *object, unsigned long ip);
116116

117-
#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB)
117+
#if defined(CONFIG_KASAN_GENERIC) && \
118+
(defined(CONFIG_SLAB) || defined(CONFIG_SLUB))
118119
void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache);
119120
void quarantine_reduce(void);
120121
void quarantine_remove_cache(struct kmem_cache *cache);

mm/kasan/tags.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* This file contains core tag-based KASAN code.
3+
*
4+
* Copyright (c) 2018 Google, Inc.
5+
* Author: Andrey Konovalov <andreyknvl@google.com>
6+
*
7+
* This program is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License version 2 as
9+
* published by the Free Software Foundation.
10+
*
11+
*/
12+
13+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14+
#define DISABLE_BRANCH_PROFILING
15+
16+
#include <linux/export.h>
17+
#include <linux/interrupt.h>
18+
#include <linux/init.h>
19+
#include <linux/kasan.h>
20+
#include <linux/kernel.h>
21+
#include <linux/kmemleak.h>
22+
#include <linux/linkage.h>
23+
#include <linux/memblock.h>
24+
#include <linux/memory.h>
25+
#include <linux/mm.h>
26+
#include <linux/module.h>
27+
#include <linux/printk.h>
28+
#include <linux/random.h>
29+
#include <linux/sched.h>
30+
#include <linux/sched/task_stack.h>
31+
#include <linux/slab.h>
32+
#include <linux/stacktrace.h>
33+
#include <linux/string.h>
34+
#include <linux/types.h>
35+
#include <linux/vmalloc.h>
36+
#include <linux/bug.h>
37+
38+
#include "kasan.h"
39+
#include "../slab.h"
40+
41+
void check_memory_region(unsigned long addr, size_t size, bool write,
42+
unsigned long ret_ip)
43+
{
44+
}
45+
46+
#define DEFINE_HWASAN_LOAD_STORE(size) \
47+
void __hwasan_load##size##_noabort(unsigned long addr) \
48+
{ \
49+
} \
50+
EXPORT_SYMBOL(__hwasan_load##size##_noabort); \
51+
void __hwasan_store##size##_noabort(unsigned long addr) \
52+
{ \
53+
} \
54+
EXPORT_SYMBOL(__hwasan_store##size##_noabort)
55+
56+
DEFINE_HWASAN_LOAD_STORE(1);
57+
DEFINE_HWASAN_LOAD_STORE(2);
58+
DEFINE_HWASAN_LOAD_STORE(4);
59+
DEFINE_HWASAN_LOAD_STORE(8);
60+
DEFINE_HWASAN_LOAD_STORE(16);
61+
62+
void __hwasan_loadN_noabort(unsigned long addr, unsigned long size)
63+
{
64+
}
65+
EXPORT_SYMBOL(__hwasan_loadN_noabort);
66+
67+
void __hwasan_storeN_noabort(unsigned long addr, unsigned long size)
68+
{
69+
}
70+
EXPORT_SYMBOL(__hwasan_storeN_noabort);
71+
72+
void __hwasan_tag_memory(unsigned long addr, u8 tag, unsigned long size)
73+
{
74+
}
75+
EXPORT_SYMBOL(__hwasan_tag_memory);

mm/slub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2992,7 +2992,7 @@ static __always_inline void slab_free(struct kmem_cache *s, struct page *page,
29922992
do_slab_free(s, page, head, tail, cnt, addr);
29932993
}
29942994

2995-
#ifdef CONFIG_KASAN
2995+
#ifdef CONFIG_KASAN_GENERIC
29962996
void ___cache_free(struct kmem_cache *cache, void *x, unsigned long addr)
29972997
{
29982998
do_slab_free(cache, virt_to_head_page(x), x, NULL, 1, addr);

0 commit comments

Comments
 (0)