mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
![Andrey Konovalov](/assets/img/avatar_default.png)
Patch series "kasan: HW_TAGS tests support and fixes", v4. This patchset adds support for running KASAN-KUnit tests with the hardware tag-based mode and also contains a few fixes. This patch (of 15): There's a number of internal KASAN functions that are used across multiple source code files and therefore aren't marked as static inline. To avoid littering the kernel function names list with generic function names, prefix all such KASAN functions with kasan_. As a part of this change: - Rename internal (un)poison_range() to kasan_(un)poison() (no _range) to avoid name collision with a public kasan_unpoison_range(). - Rename check_memory_region() to kasan_check_range(), as it's a more fitting name. Link: https://lkml.kernel.org/r/cover.1610733117.git.andreyknvl@google.com Link: https://linux-review.googlesource.com/id/I719cc93483d4ba288a634dba80ee6b7f2809cd26 Link: https://lkml.kernel.org/r/13777aedf8d3ebbf35891136e1f2287e2f34aaba.1610733117.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Suggested-by: Marco Elver <elver@google.com> Reviewed-by: Marco Elver <elver@google.com> Reviewed-by: Alexander Potapenko <glider@google.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Vincenzo Frascino <vincenzo.frascino@arm.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Peter Collingbourne <pcc@google.com> Cc: Evgenii Stepanov <eugenis@google.com> Cc: Branislav Rankov <Branislav.Rankov@arm.com> Cc: Kevin Brodsky <kevin.brodsky@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
96 lines
2.4 KiB
C
96 lines
2.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* This file contains software 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>
|
|
*/
|
|
|
|
#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 *kasan_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 = kasan_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 = kasan_get_alloc_meta(cache, object);
|
|
|
|
if (alloc_meta) {
|
|
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
|
|
/*
|
|
* If access_size is a negative number, then it has reason to be
|
|
* defined as out-of-bounds bug type.
|
|
*
|
|
* Casting negative numbers to size_t would indeed turn up as
|
|
* a large size_t and its value will be larger than ULONG_MAX/2,
|
|
* so that this can qualify as out-of-bounds.
|
|
*/
|
|
if (info->access_addr + info->access_size < info->access_addr)
|
|
return "out-of-bounds";
|
|
|
|
return "invalid-access";
|
|
}
|
|
|
|
void *kasan_find_first_bad_addr(void *addr, size_t size)
|
|
{
|
|
u8 tag = get_tag(addr);
|
|
void *p = kasan_reset_tag(addr);
|
|
void *end = p + size;
|
|
|
|
while (p < end && tag == *(u8 *)kasan_mem_to_shadow(p))
|
|
p += KASAN_GRANULE_SIZE;
|
|
return p;
|
|
}
|
|
|
|
void kasan_metadata_fetch_row(char *buffer, void *row)
|
|
{
|
|
memcpy(buffer, kasan_mem_to_shadow(row), META_BYTES_PER_ROW);
|
|
}
|
|
|
|
void kasan_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);
|
|
}
|