kasan, arm64: implement HW_TAGS runtime
[linux-block.git] / mm / kasan / hw_tags.c
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 }