summaryrefslogtreecommitdiffstats
path: root/include/linux/kasan.h
blob: 7c184cd0e234862fc5bef5b73b06d27e1df555f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_KASAN_H
#define _LINUX_KASAN_H

#include <linux/types.h>

/*
 * On 64bit architectures tlsf aligns all allocations to a 64bit
 * boundary, otherwise they are only 32bit aligned.
 */
#ifdef CONFIG_64BIT
#define KASAN_SHADOW_SCALE_SHIFT	3
#else
#define KASAN_SHADOW_SCALE_SHIFT	2
#endif

#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 */

#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) */
#define KASAN_KMALLOC_FREETRACK 0xFA  /* object was freed and has free track set */

#define KASAN_GLOBAL_REDZONE    0xF9  /* redzone for global variable */
#define KASAN_VMALLOC_INVALID   0xF8  /* unallocated space in vmapped page */

/*
 * 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

/*
 * alloca redzone shadow values
 */
#define KASAN_ALLOCA_LEFT	0xCA
#define KASAN_ALLOCA_RIGHT	0xCB

#ifdef CONFIG_KASAN

extern unsigned long kasan_shadow_start;
extern unsigned long kasan_shadow_base;

static inline void *kasan_mem_to_shadow(const void *addr)
{
	unsigned long a = (unsigned long)addr;

	a -= kasan_shadow_start;
	a >>= KASAN_SHADOW_SCALE_SHIFT;
	a += kasan_shadow_base;

	return (void *)a;
}

void kasan_init(unsigned long membase, unsigned long memsize,
		unsigned long shadow_base);

/* Enable reporting bugs after kasan_disable_current() */
extern void kasan_enable_current(void);

/* Disable reporting bugs for current task */
extern void kasan_disable_current(void);

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

bool kasan_save_enable_multi_shot(void);
void kasan_restore_multi_shot(bool enabled);

#else /* CONFIG_KASAN */

static inline void kasan_poison_shadow(const void *address, size_t size, u8 value) {}
static inline void kasan_unpoison_shadow(const void *address, size_t size) {}

static inline void kasan_enable_current(void) {}
static inline void kasan_disable_current(void) {}

static inline void kasan_init(unsigned long membase, unsigned long memsize,
		unsigned long shadow_base) {}

#endif /* CONFIG_KASAN */

#endif /* LINUX_KASAN_H */