kasan: introduce kasan_mempool_unpoison_pages
[linux-2.6-microblaze.git] / mm / kasan / report_tags.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4  * Copyright (c) 2020 Google, Inc.
5  */
6
7 #include <linux/atomic.h>
8
9 #include "kasan.h"
10 #include "../slab.h"
11
12 extern struct kasan_stack_ring stack_ring;
13
14 static const char *get_common_bug_type(struct kasan_report_info *info)
15 {
16         /*
17          * If access_size is a negative number, then it has reason to be
18          * defined as out-of-bounds bug type.
19          *
20          * Casting negative numbers to size_t would indeed turn up as
21          * a large size_t and its value will be larger than ULONG_MAX/2,
22          * so that this can qualify as out-of-bounds.
23          */
24         if (info->access_addr + info->access_size < info->access_addr)
25                 return "out-of-bounds";
26
27         return "invalid-access";
28 }
29
30 #ifdef CONFIG_KASAN_EXTRA_INFO
31 static void kasan_complete_extra_report_info(struct kasan_track *track,
32                                          struct kasan_stack_ring_entry *entry)
33 {
34         track->cpu = entry->cpu;
35         track->timestamp = entry->timestamp;
36 }
37 #endif /* CONFIG_KASAN_EXTRA_INFO */
38
39 void kasan_complete_mode_report_info(struct kasan_report_info *info)
40 {
41         unsigned long flags;
42         u64 pos;
43         struct kasan_stack_ring_entry *entry;
44         bool alloc_found = false, free_found = false;
45
46         if ((!info->cache || !info->object) && !info->bug_type) {
47                 info->bug_type = get_common_bug_type(info);
48                 return;
49         }
50
51         write_lock_irqsave(&stack_ring.lock, flags);
52
53         pos = atomic64_read(&stack_ring.pos);
54
55         /*
56          * The loop below tries to find stack ring entries relevant to the
57          * buggy object. This is a best-effort process.
58          *
59          * First, another object with the same tag can be allocated in place of
60          * the buggy object. Also, since the number of entries is limited, the
61          * entries relevant to the buggy object can be overwritten.
62          */
63
64         for (u64 i = pos - 1; i != pos - 1 - stack_ring.size; i--) {
65                 if (alloc_found && free_found)
66                         break;
67
68                 entry = &stack_ring.entries[i % stack_ring.size];
69
70                 if (kasan_reset_tag(entry->ptr) != info->object ||
71                     get_tag(entry->ptr) != get_tag(info->access_addr) ||
72                     info->cache->object_size != entry->size)
73                         continue;
74
75                 if (entry->is_free) {
76                         /*
77                          * Second free of the same object.
78                          * Give up on trying to find the alloc entry.
79                          */
80                         if (free_found)
81                                 break;
82
83                         info->free_track.pid = entry->pid;
84                         info->free_track.stack = entry->stack;
85 #ifdef CONFIG_KASAN_EXTRA_INFO
86                         kasan_complete_extra_report_info(&info->free_track, entry);
87 #endif /* CONFIG_KASAN_EXTRA_INFO */
88                         free_found = true;
89
90                         /*
91                          * If a free entry is found first, the bug is likely
92                          * a use-after-free.
93                          */
94                         if (!info->bug_type)
95                                 info->bug_type = "slab-use-after-free";
96                 } else {
97                         /* Second alloc of the same object. Give up. */
98                         if (alloc_found)
99                                 break;
100
101                         info->alloc_track.pid = entry->pid;
102                         info->alloc_track.stack = entry->stack;
103 #ifdef CONFIG_KASAN_EXTRA_INFO
104                         kasan_complete_extra_report_info(&info->alloc_track, entry);
105 #endif /* CONFIG_KASAN_EXTRA_INFO */
106                         alloc_found = true;
107
108                         /*
109                          * If an alloc entry is found first, the bug is likely
110                          * an out-of-bounds.
111                          */
112                         if (!info->bug_type)
113                                 info->bug_type = "slab-out-of-bounds";
114                 }
115         }
116
117         write_unlock_irqrestore(&stack_ring.lock, flags);
118
119         /* Assign the common bug type if no entries were found. */
120         if (!info->bug_type)
121                 info->bug_type = get_common_bug_type(info);
122 }