mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
ae8f06b31a
Add memory corruption identification at bug report for software tag-based mode. The report shows whether it is "use-after-free" or "out-of-bound" error instead of "invalid-access" error. This will make it easier for programmers to see the memory corruption problem. We extend the slab to store five old free pointer tag and free backtrace, we can check if the tagged address is in the slab record and make a good guess if the object is more like "use-after-free" or "out-of-bound". therefore every slab memory corruption can be identified whether it's "use-after-free" or "out-of-bound". [aryabinin@virtuozzo.com: simplify & clenup code] Link: https://lkml.kernel.org/r/3318f9d7-a760-3cc8-b700-f06108ae745f@virtuozzo.com] Link: http://lkml.kernel.org/r/20190821180332.11450-1-aryabinin@virtuozzo.com Signed-off-by: Walter Wu <walter-zh.wu@mediatek.com> Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com> Acked-by: Andrey Konovalov <andreyknvl@google.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Alexander Potapenko <glider@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
82 lines
2 KiB
C
82 lines
2 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* This file contains tag-based KASAN specific error reporting code.
|
|
*
|
|
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
|
|
* Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
|
|
*
|
|
* Some code borrowed from https://github.com/xairy/kasan-prototype by
|
|
* Andrey Konovalov <andreyknvl@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
*/
|
|
|
|
#include <linux/bitops.h>
|
|
#include <linux/ftrace.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/printk.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/stackdepot.h>
|
|
#include <linux/stacktrace.h>
|
|
#include <linux/string.h>
|
|
#include <linux/types.h>
|
|
#include <linux/kasan.h>
|
|
#include <linux/module.h>
|
|
|
|
#include <asm/sections.h>
|
|
|
|
#include "kasan.h"
|
|
#include "../slab.h"
|
|
|
|
const char *get_bug_type(struct kasan_access_info *info)
|
|
{
|
|
#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
|
|
struct kasan_alloc_meta *alloc_meta;
|
|
struct kmem_cache *cache;
|
|
struct page *page;
|
|
const void *addr;
|
|
void *object;
|
|
u8 tag;
|
|
int i;
|
|
|
|
tag = get_tag(info->access_addr);
|
|
addr = reset_tag(info->access_addr);
|
|
page = kasan_addr_to_page(addr);
|
|
if (page && PageSlab(page)) {
|
|
cache = page->slab_cache;
|
|
object = nearest_obj(cache, page, (void *)addr);
|
|
alloc_meta = get_alloc_info(cache, object);
|
|
|
|
for (i = 0; i < KASAN_NR_FREE_STACKS; i++)
|
|
if (alloc_meta->free_pointer_tag[i] == tag)
|
|
return "use-after-free";
|
|
return "out-of-bounds";
|
|
}
|
|
|
|
#endif
|
|
return "invalid-access";
|
|
}
|
|
|
|
void *find_first_bad_addr(void *addr, size_t size)
|
|
{
|
|
u8 tag = get_tag(addr);
|
|
void *p = reset_tag(addr);
|
|
void *end = p + size;
|
|
|
|
while (p < end && tag == *(u8 *)kasan_mem_to_shadow(p))
|
|
p += KASAN_SHADOW_SCALE_SIZE;
|
|
return p;
|
|
}
|
|
|
|
void print_tags(u8 addr_tag, const void *addr)
|
|
{
|
|
u8 *shadow = (u8 *)kasan_mem_to_shadow(addr);
|
|
|
|
pr_err("Pointer tag: [%02x], memory tag: [%02x]\n", addr_tag, *shadow);
|
|
}
|