Commit | Line | Data |
---|---|---|
2e903b91 AK |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * This file contains core hardware tag-based KASAN code. | |
4 | * | |
5 | * Copyright (c) 2020 Google, Inc. | |
6 | * Author: Andrey Konovalov <andreyknvl@google.com> | |
7 | */ | |
8 | ||
9 | #define pr_fmt(fmt) "kasan: " fmt | |
10 | ||
11 | #include <linux/kasan.h> | |
12 | #include <linux/kernel.h> | |
13 | #include <linux/memory.h> | |
14 | #include <linux/mm.h> | |
15 | #include <linux/string.h> | |
16 | #include <linux/types.h> | |
17 | ||
18 | #include "kasan.h" | |
19 | ||
20 | /* kasan_init_hw_tags_cpu() is called for each CPU. */ | |
21 | void kasan_init_hw_tags_cpu(void) | |
22 | { | |
23 | hw_init_tags(KASAN_TAG_MAX); | |
24 | hw_enable_tagging(); | |
25 | } | |
26 | ||
27 | /* kasan_init_hw_tags() is called once on boot CPU. */ | |
28 | void __init kasan_init_hw_tags(void) | |
29 | { | |
30 | pr_info("KernelAddressSanitizer initialized\n"); | |
31 | } | |
32 | ||
33 | void *kasan_reset_tag(const void *addr) | |
34 | { | |
35 | return reset_tag(addr); | |
36 | } | |
37 | ||
38 | void poison_range(const void *address, size_t size, u8 value) | |
39 | { | |
40 | hw_set_mem_tag_range(reset_tag(address), | |
41 | round_up(size, KASAN_GRANULE_SIZE), value); | |
42 | } | |
43 | ||
44 | void unpoison_range(const void *address, size_t size) | |
45 | { | |
46 | hw_set_mem_tag_range(reset_tag(address), | |
47 | round_up(size, KASAN_GRANULE_SIZE), get_tag(address)); | |
48 | } | |
49 | ||
50 | u8 random_tag(void) | |
51 | { | |
52 | return hw_get_random_tag(); | |
53 | } | |
54 | ||
55 | bool check_invalid_free(void *addr) | |
56 | { | |
57 | u8 ptr_tag = get_tag(addr); | |
58 | u8 mem_tag = hw_get_mem_tag(addr); | |
59 | ||
60 | return (mem_tag == KASAN_TAG_INVALID) || | |
61 | (ptr_tag != KASAN_TAG_KERNEL && ptr_tag != mem_tag); | |
62 | } | |
63 | ||
64 | void kasan_set_free_info(struct kmem_cache *cache, | |
65 | void *object, u8 tag) | |
66 | { | |
67 | struct kasan_alloc_meta *alloc_meta; | |
68 | ||
69 | alloc_meta = get_alloc_info(cache, object); | |
70 | kasan_set_track(&alloc_meta->free_track[0], GFP_NOWAIT); | |
71 | } | |
72 | ||
73 | struct kasan_track *kasan_get_free_track(struct kmem_cache *cache, | |
74 | void *object, u8 tag) | |
75 | { | |
76 | struct kasan_alloc_meta *alloc_meta; | |
77 | ||
78 | alloc_meta = get_alloc_info(cache, object); | |
79 | return &alloc_meta->free_track[0]; | |
80 | } |