blob: 6e811d0f6242bfba829a50b988c81142393cb5b5 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001/* SPDX-License-Identifier: GPL-2.0 */
Andrey Ryabinin0b24bec2015-02-13 14:39:17 -08002#ifndef __MM_KASAN_KASAN_H
3#define __MM_KASAN_KASAN_H
4
5#include <linux/kasan.h>
Alexander Potapenkocd110162016-03-25 14:22:08 -07006#include <linux/stackdepot.h>
Andrey Ryabinin0b24bec2015-02-13 14:39:17 -08007
Andrey Konovalov6c6a04f2020-12-22 12:01:59 -08008#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
Andrey Konovalov1f600622020-12-22 12:00:24 -08009#define KASAN_GRANULE_SIZE (1UL << KASAN_SHADOW_SCALE_SHIFT)
Andrey Konovalov6c6a04f2020-12-22 12:01:59 -080010#else
11#include <asm/mte-kasan.h>
12#define KASAN_GRANULE_SIZE MTE_GRANULE_SIZE
13#endif
14
Andrey Konovalov1f600622020-12-22 12:00:24 -080015#define KASAN_GRANULE_MASK (KASAN_GRANULE_SIZE - 1)
Andrey Ryabinin0b24bec2015-02-13 14:39:17 -080016
Andrey Konovalovaffc3f02020-12-22 12:00:35 -080017#define KASAN_MEMORY_PER_SHADOW_PAGE (KASAN_GRANULE_SIZE << PAGE_SHIFT)
18
Andrey Konovalov3c9e3aa2018-12-28 00:30:16 -080019#define KASAN_TAG_KERNEL 0xFF /* native kernel pointers tag */
20#define KASAN_TAG_INVALID 0xFE /* inaccessible memory tag */
21#define KASAN_TAG_MAX 0xFD /* maximum value for random tags */
22
Andrey Konovalov7f94ffb2018-12-28 00:30:50 -080023#ifdef CONFIG_KASAN_GENERIC
Andrey Ryabininb8c73fc2015-02-13 14:39:28 -080024#define KASAN_FREE_PAGE 0xFF /* page was freed */
Andrey Ryabinin0316bec2015-02-13 14:39:42 -080025#define KASAN_PAGE_REDZONE 0xFE /* redzone for kmalloc_large allocations */
26#define KASAN_KMALLOC_REDZONE 0xFC /* redzone inside slub object */
27#define KASAN_KMALLOC_FREE 0xFB /* object was freed (kmem_cache_free/kfree) */
Walter Wue4b78182020-08-06 23:24:39 -070028#define KASAN_KMALLOC_FREETRACK 0xFA /* object was freed and has free track set */
Andrey Konovalov7f94ffb2018-12-28 00:30:50 -080029#else
30#define KASAN_FREE_PAGE KASAN_TAG_INVALID
31#define KASAN_PAGE_REDZONE KASAN_TAG_INVALID
32#define KASAN_KMALLOC_REDZONE KASAN_TAG_INVALID
33#define KASAN_KMALLOC_FREE KASAN_TAG_INVALID
Walter Wue4b78182020-08-06 23:24:39 -070034#define KASAN_KMALLOC_FREETRACK KASAN_TAG_INVALID
Andrey Konovalov7f94ffb2018-12-28 00:30:50 -080035#endif
36
Walter Wue4b78182020-08-06 23:24:39 -070037#define KASAN_GLOBAL_REDZONE 0xF9 /* redzone for global variable */
38#define KASAN_VMALLOC_INVALID 0xF8 /* unallocated space in vmapped page */
Andrey Ryabinin0316bec2015-02-13 14:39:42 -080039
Andrey Ryabininc420f162015-02-13 14:39:59 -080040/*
41 * Stack redzone shadow values
42 * (Those are compiler's ABI, don't change them)
43 */
44#define KASAN_STACK_LEFT 0xF1
45#define KASAN_STACK_MID 0xF2
46#define KASAN_STACK_RIGHT 0xF3
47#define KASAN_STACK_PARTIAL 0xF4
48
Paul Lawrence342061e2018-02-06 15:36:11 -080049/*
50 * alloca redzone shadow values
51 */
52#define KASAN_ALLOCA_LEFT 0xCA
53#define KASAN_ALLOCA_RIGHT 0xCB
54
55#define KASAN_ALLOCA_REDZONE_SIZE 32
56
Marco Elvere8969212019-07-11 20:53:49 -070057/*
58 * Stack frame marker (compiler ABI).
59 */
60#define KASAN_CURRENT_STACK_FRAME_MAGIC 0x41B58AB3
61
Andrey Ryabininbebf56a2015-02-13 14:40:17 -080062/* Don't break randconfig/all*config builds */
63#ifndef KASAN_ABI_VERSION
64#define KASAN_ABI_VERSION 1
65#endif
Andrey Ryabininb8c73fc2015-02-13 14:39:28 -080066
Andrey Konovalov96e02792020-12-22 12:01:17 -080067/* Metadata layout customization. */
68#define META_BYTES_PER_BLOCK 1
69#define META_BLOCKS_PER_ROW 16
70#define META_BYTES_PER_ROW (META_BLOCKS_PER_ROW * META_BYTES_PER_BLOCK)
71#define META_MEM_BYTES_PER_ROW (META_BYTES_PER_ROW * KASAN_GRANULE_SIZE)
72#define META_ROWS_AROUND_ADDR 2
73
Andrey Ryabinin0b24bec2015-02-13 14:39:17 -080074struct kasan_access_info {
75 const void *access_addr;
76 const void *first_bad_addr;
77 size_t access_size;
78 bool is_write;
79 unsigned long ip;
80};
81
Andrey Ryabininbebf56a2015-02-13 14:40:17 -080082/* The layout of struct dictated by compiler */
83struct kasan_source_location {
84 const char *filename;
85 int line_no;
86 int column_no;
87};
88
89/* The layout of struct dictated by compiler */
90struct kasan_global {
91 const void *beg; /* Address of the beginning of the global variable. */
92 size_t size; /* Size of the global variable. */
93 size_t size_with_redzone; /* Size of the variable + size of the red zone. 32 bytes aligned */
94 const void *name;
95 const void *module_name; /* Name of the module where the global variable is declared. */
96 unsigned long has_dynamic_init; /* This needed for C++ */
97#if KASAN_ABI_VERSION >= 4
98 struct kasan_source_location *location;
99#endif
Dmitry Vyukov045d5992016-11-30 15:54:13 -0800100#if KASAN_ABI_VERSION >= 5
101 char *odr_indicator;
102#endif
Andrey Ryabininbebf56a2015-02-13 14:40:17 -0800103};
104
Alexander Potapenko7ed2f9e2016-03-25 14:21:59 -0700105/**
106 * Structures to keep alloc and free tracks *
107 */
108
Alexander Potapenkocd110162016-03-25 14:22:08 -0700109#define KASAN_STACK_DEPTH 64
110
Alexander Potapenko7ed2f9e2016-03-25 14:21:59 -0700111struct kasan_track {
Alexander Potapenkocd110162016-03-25 14:22:08 -0700112 u32 pid;
113 depot_stack_handle_t stack;
Alexander Potapenko7ed2f9e2016-03-25 14:21:59 -0700114};
115
Walter Wuae8f06b2019-09-23 15:34:13 -0700116#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
117#define KASAN_NR_FREE_STACKS 5
118#else
119#define KASAN_NR_FREE_STACKS 1
120#endif
121
Alexander Potapenko7ed2f9e2016-03-25 14:21:59 -0700122struct kasan_alloc_meta {
Andrey Ryabininb3cbd9b2016-08-02 14:02:52 -0700123 struct kasan_track alloc_track;
Walter Wu26e760c2020-08-06 23:24:35 -0700124#ifdef CONFIG_KASAN_GENERIC
125 /*
126 * call_rcu() call stack is stored into struct kasan_alloc_meta.
127 * The free stack is stored into struct kasan_free_meta.
128 */
129 depot_stack_handle_t aux_stack[2];
Walter Wue4b78182020-08-06 23:24:39 -0700130#else
Walter Wuae8f06b2019-09-23 15:34:13 -0700131 struct kasan_track free_track[KASAN_NR_FREE_STACKS];
Walter Wue4b78182020-08-06 23:24:39 -0700132#endif
Walter Wuae8f06b2019-09-23 15:34:13 -0700133#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
134 u8 free_pointer_tag[KASAN_NR_FREE_STACKS];
135 u8 free_track_idx;
136#endif
Alexander Potapenko7ed2f9e2016-03-25 14:21:59 -0700137};
138
Alexander Potapenko55834c52016-05-20 16:59:11 -0700139struct qlist_node {
140 struct qlist_node *next;
141};
Alexander Potapenko7ed2f9e2016-03-25 14:21:59 -0700142struct kasan_free_meta {
Alexander Potapenko55834c52016-05-20 16:59:11 -0700143 /* This field is used while the object is in the quarantine.
144 * Otherwise it might be used for the allocator freelist.
145 */
146 struct qlist_node quarantine_link;
Walter Wue4b78182020-08-06 23:24:39 -0700147#ifdef CONFIG_KASAN_GENERIC
148 struct kasan_track free_track;
149#endif
Alexander Potapenko7ed2f9e2016-03-25 14:21:59 -0700150};
151
Andrey Konovalov64767922020-12-22 12:02:34 -0800152struct kasan_alloc_meta *kasan_get_alloc_meta(struct kmem_cache *cache,
153 const void *object);
154struct kasan_free_meta *kasan_get_free_meta(struct kmem_cache *cache,
155 const void *object);
Alexander Potapenko7ed2f9e2016-03-25 14:21:59 -0700156
Andrey Konovalov2e903b92020-12-22 12:02:10 -0800157#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
158
Andrey Ryabinin0b24bec2015-02-13 14:39:17 -0800159static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
160{
161 return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET)
162 << KASAN_SHADOW_SCALE_SHIFT);
163}
164
Andrey Konovalov68824642020-12-22 12:01:07 -0800165static inline bool addr_has_metadata(const void *addr)
Andrey Konovalov11cd3cd2018-12-28 00:30:38 -0800166{
167 return (addr >= kasan_shadow_to_mem((void *)KASAN_SHADOW_START));
168}
169
Marco Elverb5f6e0f2019-07-11 20:54:07 -0700170/**
171 * check_memory_region - Check memory region, and report if invalid access.
172 * @addr: the accessed address
173 * @size: the accessed size
174 * @write: true if access is a write access
175 * @ret_ip: return address
176 * @return: true if access was valid, false if invalid
177 */
178bool check_memory_region(unsigned long addr, size_t size, bool write,
Andrey Konovalovbffa9862018-12-28 00:29:45 -0800179 unsigned long ret_ip);
180
Andrey Konovalov2e903b92020-12-22 12:02:10 -0800181#else /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */
182
183static inline bool addr_has_metadata(const void *addr)
184{
185 return true;
186}
187
188#endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */
189
Andrey Konovalovd8dd3972020-12-22 12:02:56 -0800190#if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS)
191void print_tags(u8 addr_tag, const void *addr);
192#else
193static inline void print_tags(u8 addr_tag, const void *addr) { }
194#endif
195
Andrey Konovalov121e8f82018-12-28 00:30:42 -0800196void *find_first_bad_addr(void *addr, size_t size);
Andrey Konovalov11cd3cd2018-12-28 00:30:38 -0800197const char *get_bug_type(struct kasan_access_info *info);
Andrey Konovalov96e02792020-12-22 12:01:17 -0800198void metadata_fetch_row(char *buffer, void *row);
Andrey Konovalov11cd3cd2018-12-28 00:30:38 -0800199
Andrey Konovalov97fc7122020-12-22 12:00:49 -0800200#if defined(CONFIG_KASAN_GENERIC) && CONFIG_KASAN_STACK
201void print_address_stack_frame(const void *addr);
202#else
203static inline void print_address_stack_frame(const void *addr) { }
204#endif
205
Walter Wu8cceeff2020-04-01 21:09:37 -0700206bool kasan_report(unsigned long addr, size_t size,
Andrey Ryabinin0b24bec2015-02-13 14:39:17 -0800207 bool is_write, unsigned long ip);
Dmitry Vyukovee3ce772018-02-06 15:36:27 -0800208void kasan_report_invalid_free(void *object, unsigned long ip);
Andrey Ryabinin0b24bec2015-02-13 14:39:17 -0800209
Walter Wuae8f06b2019-09-23 15:34:13 -0700210struct page *kasan_addr_to_page(const void *addr);
211
Walter Wu26e760c2020-08-06 23:24:35 -0700212depot_stack_handle_t kasan_save_stack(gfp_t flags);
Walter Wue4b78182020-08-06 23:24:39 -0700213void kasan_set_track(struct kasan_track *track, gfp_t flags);
214void kasan_set_free_info(struct kmem_cache *cache, void *object, u8 tag);
215struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
216 void *object, u8 tag);
Walter Wu26e760c2020-08-06 23:24:35 -0700217
Andrey Konovalov2bd926b2018-12-28 00:29:53 -0800218#if defined(CONFIG_KASAN_GENERIC) && \
219 (defined(CONFIG_SLAB) || defined(CONFIG_SLUB))
Andrey Konovalovc696de92020-12-22 12:02:31 -0800220void quarantine_put(struct kmem_cache *cache, void *object);
Alexander Potapenko55834c52016-05-20 16:59:11 -0700221void quarantine_reduce(void);
222void quarantine_remove_cache(struct kmem_cache *cache);
223#else
Andrey Konovalovc696de92020-12-22 12:02:31 -0800224static inline void quarantine_put(struct kmem_cache *cache, void *object) { }
Alexander Potapenko55834c52016-05-20 16:59:11 -0700225static inline void quarantine_reduce(void) { }
226static inline void quarantine_remove_cache(struct kmem_cache *cache) { }
227#endif
228
Andrey Konovalov3c9e3aa2018-12-28 00:30:16 -0800229#ifndef arch_kasan_set_tag
Qian Caic412a762019-03-28 20:43:15 -0700230static inline const void *arch_kasan_set_tag(const void *addr, u8 tag)
231{
232 return addr;
233}
Andrey Konovalov3c9e3aa2018-12-28 00:30:16 -0800234#endif
Andrey Konovalov3c9e3aa2018-12-28 00:30:16 -0800235#ifndef arch_kasan_get_tag
236#define arch_kasan_get_tag(addr) 0
237#endif
238
239#define set_tag(addr, tag) ((void *)arch_kasan_set_tag((addr), (tag)))
Andrey Konovalov3c9e3aa2018-12-28 00:30:16 -0800240#define get_tag(addr) arch_kasan_get_tag(addr)
241
Andrey Konovalovccbe2aa2020-12-22 12:01:56 -0800242#ifdef CONFIG_KASAN_HW_TAGS
243
244#ifndef arch_enable_tagging
245#define arch_enable_tagging()
246#endif
247#ifndef arch_init_tags
248#define arch_init_tags(max_tag)
249#endif
250#ifndef arch_get_random_tag
251#define arch_get_random_tag() (0xFF)
252#endif
253#ifndef arch_get_mem_tag
254#define arch_get_mem_tag(addr) (0xFF)
255#endif
256#ifndef arch_set_mem_tag_range
257#define arch_set_mem_tag_range(addr, size, tag) ((void *)(addr))
258#endif
259
260#define hw_enable_tagging() arch_enable_tagging()
261#define hw_init_tags(max_tag) arch_init_tags(max_tag)
262#define hw_get_random_tag() arch_get_random_tag()
263#define hw_get_mem_tag(addr) arch_get_mem_tag(addr)
264#define hw_set_mem_tag_range(addr, size, tag) arch_set_mem_tag_range((addr), (size), (tag))
265
266#endif /* CONFIG_KASAN_HW_TAGS */
267
Andrey Konovalovd8dd3972020-12-22 12:02:56 -0800268#ifdef CONFIG_KASAN_SW_TAGS
269u8 random_tag(void);
270#elif defined(CONFIG_KASAN_HW_TAGS)
271static inline u8 random_tag(void) { return hw_get_random_tag(); }
272#else
273static inline u8 random_tag(void) { return 0; }
274#endif
275
Andrey Konovalov57345fa2020-12-22 12:03:03 -0800276#ifdef CONFIG_KASAN_HW_TAGS
277
278static inline void poison_range(const void *address, size_t size, u8 value)
279{
280 hw_set_mem_tag_range(kasan_reset_tag(address),
281 round_up(size, KASAN_GRANULE_SIZE), value);
282}
283
284static inline void unpoison_range(const void *address, size_t size)
285{
286 hw_set_mem_tag_range(kasan_reset_tag(address),
287 round_up(size, KASAN_GRANULE_SIZE), get_tag(address));
288}
289
290static inline bool check_invalid_free(void *addr)
291{
292 u8 ptr_tag = get_tag(addr);
293 u8 mem_tag = hw_get_mem_tag(addr);
294
295 return (mem_tag == KASAN_TAG_INVALID) ||
296 (ptr_tag != KASAN_TAG_KERNEL && ptr_tag != mem_tag);
297}
298
299#else /* CONFIG_KASAN_HW_TAGS */
300
301void poison_range(const void *address, size_t size, u8 value);
302void unpoison_range(const void *address, size_t size);
303bool check_invalid_free(void *addr);
304
305#endif /* CONFIG_KASAN_HW_TAGS */
306
Alexander Potapenkod3215992018-02-06 15:36:20 -0800307/*
308 * Exported functions for interfaces called from assembly or from generated
309 * code. Declarations here to avoid warning about missing declarations.
310 */
311asmlinkage void kasan_unpoison_task_stack_below(const void *watermark);
312void __asan_register_globals(struct kasan_global *globals, size_t size);
313void __asan_unregister_globals(struct kasan_global *globals, size_t size);
Alexander Potapenkod3215992018-02-06 15:36:20 -0800314void __asan_handle_no_return(void);
Alexander Potapenkod3215992018-02-06 15:36:20 -0800315void __asan_alloca_poison(unsigned long addr, size_t size);
316void __asan_allocas_unpoison(const void *stack_top, const void *stack_bottom);
317
318void __asan_load1(unsigned long addr);
319void __asan_store1(unsigned long addr);
320void __asan_load2(unsigned long addr);
321void __asan_store2(unsigned long addr);
322void __asan_load4(unsigned long addr);
323void __asan_store4(unsigned long addr);
324void __asan_load8(unsigned long addr);
325void __asan_store8(unsigned long addr);
326void __asan_load16(unsigned long addr);
327void __asan_store16(unsigned long addr);
Andrey Konovalov13cf0482020-05-13 17:50:54 -0700328void __asan_loadN(unsigned long addr, size_t size);
329void __asan_storeN(unsigned long addr, size_t size);
Alexander Potapenkod3215992018-02-06 15:36:20 -0800330
331void __asan_load1_noabort(unsigned long addr);
332void __asan_store1_noabort(unsigned long addr);
333void __asan_load2_noabort(unsigned long addr);
334void __asan_store2_noabort(unsigned long addr);
335void __asan_load4_noabort(unsigned long addr);
336void __asan_store4_noabort(unsigned long addr);
337void __asan_load8_noabort(unsigned long addr);
338void __asan_store8_noabort(unsigned long addr);
339void __asan_load16_noabort(unsigned long addr);
340void __asan_store16_noabort(unsigned long addr);
Andrey Konovalov13cf0482020-05-13 17:50:54 -0700341void __asan_loadN_noabort(unsigned long addr, size_t size);
342void __asan_storeN_noabort(unsigned long addr, size_t size);
343
344void __asan_report_load1_noabort(unsigned long addr);
345void __asan_report_store1_noabort(unsigned long addr);
346void __asan_report_load2_noabort(unsigned long addr);
347void __asan_report_store2_noabort(unsigned long addr);
348void __asan_report_load4_noabort(unsigned long addr);
349void __asan_report_store4_noabort(unsigned long addr);
350void __asan_report_load8_noabort(unsigned long addr);
351void __asan_report_store8_noabort(unsigned long addr);
352void __asan_report_load16_noabort(unsigned long addr);
353void __asan_report_store16_noabort(unsigned long addr);
354void __asan_report_load_n_noabort(unsigned long addr, size_t size);
355void __asan_report_store_n_noabort(unsigned long addr, size_t size);
Alexander Potapenkod3215992018-02-06 15:36:20 -0800356
357void __asan_set_shadow_00(const void *addr, size_t size);
358void __asan_set_shadow_f1(const void *addr, size_t size);
359void __asan_set_shadow_f2(const void *addr, size_t size);
360void __asan_set_shadow_f3(const void *addr, size_t size);
361void __asan_set_shadow_f5(const void *addr, size_t size);
362void __asan_set_shadow_f8(const void *addr, size_t size);
363
Andrey Konovalov13cf0482020-05-13 17:50:54 -0700364void __hwasan_load1_noabort(unsigned long addr);
365void __hwasan_store1_noabort(unsigned long addr);
366void __hwasan_load2_noabort(unsigned long addr);
367void __hwasan_store2_noabort(unsigned long addr);
368void __hwasan_load4_noabort(unsigned long addr);
369void __hwasan_store4_noabort(unsigned long addr);
370void __hwasan_load8_noabort(unsigned long addr);
371void __hwasan_store8_noabort(unsigned long addr);
372void __hwasan_load16_noabort(unsigned long addr);
373void __hwasan_store16_noabort(unsigned long addr);
374void __hwasan_loadN_noabort(unsigned long addr, size_t size);
375void __hwasan_storeN_noabort(unsigned long addr, size_t size);
376
377void __hwasan_tag_memory(unsigned long addr, u8 tag, unsigned long size);
378
Andrey Ryabinin0b24bec2015-02-13 14:39:17 -0800379#endif