]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - mm/kasan/report_sw_tags.c
kasan: separate metadata_fetch_row for each mode
[mirror_ubuntu-hirsute-kernel.git] / mm / kasan / report_sw_tags.c
CommitLineData
e886bf9d 1// SPDX-License-Identifier: GPL-2.0
11cd3cd6
AK
2/*
3 * This file contains tag-based KASAN specific error reporting code.
4 *
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
6 * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
7 *
8 * Some code borrowed from https://github.com/xairy/kasan-prototype by
9 * Andrey Konovalov <andreyknvl@gmail.com>
11cd3cd6
AK
10 */
11
12#include <linux/bitops.h>
13#include <linux/ftrace.h>
14#include <linux/init.h>
15#include <linux/kernel.h>
16#include <linux/mm.h>
17#include <linux/printk.h>
18#include <linux/sched.h>
19#include <linux/slab.h>
20#include <linux/stackdepot.h>
21#include <linux/stacktrace.h>
22#include <linux/string.h>
23#include <linux/types.h>
24#include <linux/kasan.h>
25#include <linux/module.h>
26
27#include <asm/sections.h>
28
29#include "kasan.h"
30#include "../slab.h"
31
32const char *get_bug_type(struct kasan_access_info *info)
33{
ae8f06b3
WW
34#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
35 struct kasan_alloc_meta *alloc_meta;
36 struct kmem_cache *cache;
37 struct page *page;
38 const void *addr;
39 void *object;
40 u8 tag;
41 int i;
42
43 tag = get_tag(info->access_addr);
44 addr = reset_tag(info->access_addr);
45 page = kasan_addr_to_page(addr);
46 if (page && PageSlab(page)) {
47 cache = page->slab_cache;
48 object = nearest_obj(cache, page, (void *)addr);
49 alloc_meta = get_alloc_info(cache, object);
50
51 for (i = 0; i < KASAN_NR_FREE_STACKS; i++)
52 if (alloc_meta->free_pointer_tag[i] == tag)
53 return "use-after-free";
54 return "out-of-bounds";
55 }
56
57#endif
8cceeff4
WW
58 /*
59 * If access_size is a negative number, then it has reason to be
60 * defined as out-of-bounds bug type.
61 *
62 * Casting negative numbers to size_t would indeed turn up as
63 * a large size_t and its value will be larger than ULONG_MAX/2,
64 * so that this can qualify as out-of-bounds.
65 */
66 if (info->access_addr + info->access_size < info->access_addr)
67 return "out-of-bounds";
68
11cd3cd6
AK
69 return "invalid-access";
70}
121e8f81
AK
71
72void *find_first_bad_addr(void *addr, size_t size)
73{
74 u8 tag = get_tag(addr);
75 void *p = reset_tag(addr);
76 void *end = p + size;
77
78 while (p < end && tag == *(u8 *)kasan_mem_to_shadow(p))
1f600626 79 p += KASAN_GRANULE_SIZE;
121e8f81
AK
80 return p;
81}
82
96e0279d
AK
83void metadata_fetch_row(char *buffer, void *row)
84{
85 memcpy(buffer, kasan_mem_to_shadow(row), META_BYTES_PER_ROW);
86}
87
121e8f81
AK
88void print_tags(u8 addr_tag, const void *addr)
89{
90 u8 *shadow = (u8 *)kasan_mem_to_shadow(addr);
91
92 pr_err("Pointer tag: [%02x], memory tag: [%02x]\n", addr_tag, *shadow);
93}