1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Copyright (c) 2020 Google, Inc.
7 #include <linux/atomic.h>
12 extern struct kasan_stack_ring stack_ring;
14 static const char *get_common_bug_type(struct kasan_report_info *info)
17 * If access_size is a negative number, then it has reason to be
18 * defined as out-of-bounds bug type.
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.
24 if (info->access_addr + info->access_size < info->access_addr)
25 return "out-of-bounds";
27 return "invalid-access";
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)
34 track->cpu = entry->cpu;
35 track->timestamp = entry->timestamp;
37 #endif /* CONFIG_KASAN_EXTRA_INFO */
39 void kasan_complete_mode_report_info(struct kasan_report_info *info)
43 struct kasan_stack_ring_entry *entry;
44 bool alloc_found = false, free_found = false;
46 if ((!info->cache || !info->object) && !info->bug_type) {
47 info->bug_type = get_common_bug_type(info);
51 write_lock_irqsave(&stack_ring.lock, flags);
53 pos = atomic64_read(&stack_ring.pos);
56 * The loop below tries to find stack ring entries relevant to the
57 * buggy object. This is a best-effort process.
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.
64 for (u64 i = pos - 1; i != pos - 1 - stack_ring.size; i--) {
65 if (alloc_found && free_found)
68 entry = &stack_ring.entries[i % stack_ring.size];
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)
77 * Second free of the same object.
78 * Give up on trying to find the alloc entry.
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 */
91 * If a free entry is found first, the bug is likely
95 info->bug_type = "slab-use-after-free";
97 /* Second alloc of the same object. Give up. */
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 */
109 * If an alloc entry is found first, the bug is likely
113 info->bug_type = "slab-out-of-bounds";
117 write_unlock_irqrestore(&stack_ring.lock, flags);
119 /* Assign the common bug type if no entries were found. */
121 info->bug_type = get_common_bug_type(info);