FILE
report_tags.c
File preview with syntax highlighting.
linux-6.19.14/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 12extern struct kasan_stack_ring stack_ring; 13 14static 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 30void kasan_complete_mode_report_info(struct kasan_report_info *info) 31{ 32 unsigned long flags; 33 u64 pos; 34 struct kasan_stack_ring_entry *entry; 35 bool alloc_found = false, free_found = false; 36 37 if ((!info->cache || !info->object) && !info->bug_type) { 38 info->bug_type = get_common_bug_type(info); 39 return; 40 } 41 42 write_lock_irqsave(&stack_ring.lock, flags); 43 44 pos = atomic64_read(&stack_ring.pos); 45 46 /* 47 * The loop below tries to find stack ring entries relevant to the 48 * buggy object. This is a best-effort process. 49 * 50 * First, another object with the same tag can be allocated in place of 51 * the buggy object. Also, since the number of entries is limited, the 52 * entries relevant to the buggy object can be overwritten. 53 */ 54 55 for (u64 i = pos - 1; i != pos - 1 - stack_ring.size; i--) { 56 if (alloc_found && free_found) 57 break; 58 59 entry = &stack_ring.entries[i % stack_ring.size]; 60 61 if (kasan_reset_tag(entry->ptr) != info->object || 62 get_tag(entry->ptr) != get_tag(info->access_addr) || 63 info->cache->object_size != entry->size) 64 continue; 65 66 if (entry->is_free) { 67 /* 68 * Second free of the same object. 69 * Give up on trying to find the alloc entry. 70 */ 71 if (free_found) 72 break; 73 74 memcpy(&info->free_track, &entry->track, 75 sizeof(info->free_track)); 76 free_found = true; 77 78 /* 79 * If a free entry is found first, the bug is likely 80 * a use-after-free. 81 */ 82 if (!info->bug_type) 83 info->bug_type = "slab-use-after-free"; 84 } else { 85 /* Second alloc of the same object. Give up. */ 86 if (alloc_found) 87 break; 88 89 memcpy(&info->alloc_track, &entry->track, 90 sizeof(info->alloc_track)); 91 alloc_found = true; 92 93 /* 94 * If an alloc entry is found first, the bug is likely 95 * an out-of-bounds. 96 */ 97 if (!info->bug_type) 98 info->bug_type = "slab-out-of-bounds"; 99 } 100 } 101 102 write_unlock_irqrestore(&stack_ring.lock, flags); 103 104 /* Assign the common bug type if no entries were found. */ 105 if (!info->bug_type) 106 info->bug_type = get_common_bug_type(info); 107}
~/
Read-only file preview.