kasan.h 7.46 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
2
3
4
5
#ifndef __MM_KASAN_KASAN_H
#define __MM_KASAN_KASAN_H

#include <linux/kasan.h>
6
#include <linux/stackdepot.h>
7
8
9
10

#define KASAN_SHADOW_SCALE_SIZE (1UL << KASAN_SHADOW_SCALE_SHIFT)
#define KASAN_SHADOW_MASK       (KASAN_SHADOW_SCALE_SIZE - 1)

11
12
13
14
#define KASAN_TAG_KERNEL	0xFF /* native kernel pointers tag */
#define KASAN_TAG_INVALID	0xFE /* inaccessible memory tag */
#define KASAN_TAG_MAX		0xFD /* maximum value for random tags */

15
#ifdef CONFIG_KASAN_GENERIC
16
17
18
19
#define KASAN_FREE_PAGE         0xFF  /* page was freed */
#define KASAN_PAGE_REDZONE      0xFE  /* redzone for kmalloc_large allocations */
#define KASAN_KMALLOC_REDZONE   0xFC  /* redzone inside slub object */
#define KASAN_KMALLOC_FREE      0xFB  /* object was freed (kmem_cache_free/kfree) */
20
21
22
23
24
25
26
#else
#define KASAN_FREE_PAGE         KASAN_TAG_INVALID
#define KASAN_PAGE_REDZONE      KASAN_TAG_INVALID
#define KASAN_KMALLOC_REDZONE   KASAN_TAG_INVALID
#define KASAN_KMALLOC_FREE      KASAN_TAG_INVALID
#endif

27
#define KASAN_GLOBAL_REDZONE    0xFA  /* redzone for global variable */
28
#define KASAN_VMALLOC_INVALID   0xF9  /* unallocated space in vmapped page */
29

30
31
32
33
34
35
36
37
38
/*
 * Stack redzone shadow values
 * (Those are compiler's ABI, don't change them)
 */
#define KASAN_STACK_LEFT        0xF1
#define KASAN_STACK_MID         0xF2
#define KASAN_STACK_RIGHT       0xF3
#define KASAN_STACK_PARTIAL     0xF4

39
40
41
42
43
44
45
46
/*
 * alloca redzone shadow values
 */
#define KASAN_ALLOCA_LEFT	0xCA
#define KASAN_ALLOCA_RIGHT	0xCB

#define KASAN_ALLOCA_REDZONE_SIZE	32

47
48
49
50
51
/*
 * Stack frame marker (compiler ABI).
 */
#define KASAN_CURRENT_STACK_FRAME_MAGIC 0x41B58AB3

52
53
54
55
/* Don't break randconfig/all*config builds */
#ifndef KASAN_ABI_VERSION
#define KASAN_ABI_VERSION 1
#endif
56

57
58
59
60
61
62
63
64
struct kasan_access_info {
	const void *access_addr;
	const void *first_bad_addr;
	size_t access_size;
	bool is_write;
	unsigned long ip;
};

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/* The layout of struct dictated by compiler */
struct kasan_source_location {
	const char *filename;
	int line_no;
	int column_no;
};

/* The layout of struct dictated by compiler */
struct kasan_global {
	const void *beg;		/* Address of the beginning of the global variable. */
	size_t size;			/* Size of the global variable. */
	size_t size_with_redzone;	/* Size of the variable + size of the red zone. 32 bytes aligned */
	const void *name;
	const void *module_name;	/* Name of the module where the global variable is declared. */
	unsigned long has_dynamic_init;	/* This needed for C++ */
#if KASAN_ABI_VERSION >= 4
	struct kasan_source_location *location;
#endif
83
84
85
#if KASAN_ABI_VERSION >= 5
	char *odr_indicator;
#endif
86
87
};

Alexander Potapenko's avatar
Alexander Potapenko committed
88
89
90
91
/**
 * Structures to keep alloc and free tracks *
 */

92
93
#define KASAN_STACK_DEPTH 64

Alexander Potapenko's avatar
Alexander Potapenko committed
94
struct kasan_track {
95
96
	u32 pid;
	depot_stack_handle_t stack;
Alexander Potapenko's avatar
Alexander Potapenko committed
97
98
};

99
100
101
102
103
104
#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
#define KASAN_NR_FREE_STACKS 5
#else
#define KASAN_NR_FREE_STACKS 1
#endif

Alexander Potapenko's avatar
Alexander Potapenko committed
105
struct kasan_alloc_meta {
106
	struct kasan_track alloc_track;
107
108
109
110
111
	struct kasan_track free_track[KASAN_NR_FREE_STACKS];
#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
	u8 free_pointer_tag[KASAN_NR_FREE_STACKS];
	u8 free_track_idx;
#endif
Alexander Potapenko's avatar
Alexander Potapenko committed
112
113
};

114
115
116
struct qlist_node {
	struct qlist_node *next;
};
Alexander Potapenko's avatar
Alexander Potapenko committed
117
struct kasan_free_meta {
118
119
120
121
	/* This field is used while the object is in the quarantine.
	 * Otherwise it might be used for the allocator freelist.
	 */
	struct qlist_node quarantine_link;
Alexander Potapenko's avatar
Alexander Potapenko committed
122
123
124
125
126
127
128
};

struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
					const void *object);
struct kasan_free_meta *get_free_info(struct kmem_cache *cache,
					const void *object);

129
130
131
132
133
134
static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
{
	return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET)
		<< KASAN_SHADOW_SCALE_SHIFT);
}

135
136
137
138
139
static inline bool addr_has_shadow(const void *addr)
{
	return (addr >= kasan_shadow_to_mem((void *)KASAN_SHADOW_START));
}

140
141
void kasan_poison_shadow(const void *address, size_t size, u8 value);

142
143
144
145
146
147
148
149
150
/**
 * check_memory_region - Check memory region, and report if invalid access.
 * @addr: the accessed address
 * @size: the accessed size
 * @write: true if access is a write access
 * @ret_ip: return address
 * @return: true if access was valid, false if invalid
 */
bool check_memory_region(unsigned long addr, size_t size, bool write,
151
152
				unsigned long ret_ip);

153
void *find_first_bad_addr(void *addr, size_t size);
154
155
const char *get_bug_type(struct kasan_access_info *info);

156
bool kasan_report(unsigned long addr, size_t size,
157
		bool is_write, unsigned long ip);
158
void kasan_report_invalid_free(void *object, unsigned long ip);
159

160
161
struct page *kasan_addr_to_page(const void *addr);

162
163
#if defined(CONFIG_KASAN_GENERIC) && \
	(defined(CONFIG_SLAB) || defined(CONFIG_SLUB))
164
165
166
167
168
169
170
171
172
173
void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache);
void quarantine_reduce(void);
void quarantine_remove_cache(struct kmem_cache *cache);
#else
static inline void quarantine_put(struct kasan_free_meta *info,
				struct kmem_cache *cache) { }
static inline void quarantine_reduce(void) { }
static inline void quarantine_remove_cache(struct kmem_cache *cache) { }
#endif

174
175
#ifdef CONFIG_KASAN_SW_TAGS

176
177
void print_tags(u8 addr_tag, const void *addr);

178
179
180
181
u8 random_tag(void);

#else

182
183
static inline void print_tags(u8 addr_tag, const void *addr) { }

184
185
186
187
188
189
190
191
static inline u8 random_tag(void)
{
	return 0;
}

#endif

#ifndef arch_kasan_set_tag
192
193
194
195
static inline const void *arch_kasan_set_tag(const void *addr, u8 tag)
{
	return addr;
}
196
197
198
199
200
201
202
203
204
205
206
207
#endif
#ifndef arch_kasan_reset_tag
#define arch_kasan_reset_tag(addr)	((void *)(addr))
#endif
#ifndef arch_kasan_get_tag
#define arch_kasan_get_tag(addr)	0
#endif

#define set_tag(addr, tag)	((void *)arch_kasan_set_tag((addr), (tag)))
#define reset_tag(addr)		((void *)arch_kasan_reset_tag(addr))
#define get_tag(addr)		arch_kasan_get_tag(addr)

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*
 * Exported functions for interfaces called from assembly or from generated
 * code. Declarations here to avoid warning about missing declarations.
 */
asmlinkage void kasan_unpoison_task_stack_below(const void *watermark);
void __asan_register_globals(struct kasan_global *globals, size_t size);
void __asan_unregister_globals(struct kasan_global *globals, size_t size);
void __asan_loadN(unsigned long addr, size_t size);
void __asan_storeN(unsigned long addr, size_t size);
void __asan_handle_no_return(void);
void __asan_alloca_poison(unsigned long addr, size_t size);
void __asan_allocas_unpoison(const void *stack_top, const void *stack_bottom);

void __asan_load1(unsigned long addr);
void __asan_store1(unsigned long addr);
void __asan_load2(unsigned long addr);
void __asan_store2(unsigned long addr);
void __asan_load4(unsigned long addr);
void __asan_store4(unsigned long addr);
void __asan_load8(unsigned long addr);
void __asan_store8(unsigned long addr);
void __asan_load16(unsigned long addr);
void __asan_store16(unsigned long addr);

void __asan_load1_noabort(unsigned long addr);
void __asan_store1_noabort(unsigned long addr);
void __asan_load2_noabort(unsigned long addr);
void __asan_store2_noabort(unsigned long addr);
void __asan_load4_noabort(unsigned long addr);
void __asan_store4_noabort(unsigned long addr);
void __asan_load8_noabort(unsigned long addr);
void __asan_store8_noabort(unsigned long addr);
void __asan_load16_noabort(unsigned long addr);
void __asan_store16_noabort(unsigned long addr);

void __asan_set_shadow_00(const void *addr, size_t size);
void __asan_set_shadow_f1(const void *addr, size_t size);
void __asan_set_shadow_f2(const void *addr, size_t size);
void __asan_set_shadow_f3(const void *addr, size_t size);
void __asan_set_shadow_f5(const void *addr, size_t size);
void __asan_set_shadow_f8(const void *addr, size_t size);

250
#endif