Commit 73228c7e authored by Patricia Alfonso's avatar Patricia Alfonso Committed by Linus Torvalds

KASAN: port KASAN Tests to KUnit

Transfer all previous tests for KASAN to KUnit so they can be run more
easily.  Using kunit_tool, developers can run these tests with their other
KUnit tests and see "pass" or "fail" with the appropriate KASAN report
instead of needing to parse each KASAN report to test KASAN
functionalities.  All KASAN reports are still printed to dmesg.

Stack tests do not work properly when KASAN_STACK is enabled so those
tests use a check for "if IS_ENABLED(CONFIG_KASAN_STACK)" so they only run
if stack instrumentation is enabled.  If KASAN_STACK is not enabled, KUnit
will print a statement to let the user know this test was not run with
KASAN_STACK enabled.

copy_user_test and kasan_rcu_uaf cannot be run in KUnit so there is a
separate test file for those tests, which can be run as before as a
module.

[trishalfonso@google.com: v14]
  Link: https://lkml.kernel.org/r/20200915035828.570483-4-davidgow@google.comSigned-off-by: default avatarPatricia Alfonso <trishalfonso@google.com>
Signed-off-by: default avatarDavid Gow <davidgow@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Tested-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Reviewed-by: default avatarBrendan Higgins <brendanhiggins@google.com>
Reviewed-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Reviewed-by: default avatarDmitry Vyukov <dvyukov@google.com>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Link: https://lkml.kernel.org/r/20200910070331.3358048-4-davidgow@google.comSigned-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 83c4e7a0
...@@ -166,12 +166,24 @@ config KASAN_VMALLOC ...@@ -166,12 +166,24 @@ config KASAN_VMALLOC
for KASAN to detect more sorts of errors (and to support vmapped for KASAN to detect more sorts of errors (and to support vmapped
stacks), but at the cost of higher memory usage. stacks), but at the cost of higher memory usage.
config TEST_KASAN config KASAN_KUNIT_TEST
tristate "Module for testing KASAN for bug detection" tristate "KUnit-compatible tests of KASAN bug detection capabilities" if !KUNIT_ALL_TESTS
depends on m depends on KASAN && KUNIT
default KUNIT_ALL_TESTS
help help
This is a test module doing various nasty things like This is a KUnit test suite doing various nasty things like
out of bounds accesses, use after free. It is useful for testing out of bounds and use after free accesses. It is useful for testing
kernel debugging features like KASAN. kernel debugging features like KASAN.
For more information on KUnit and unit tests in general, please refer
to the KUnit documentation in Documentation/dev-tools/kunit
config TEST_KASAN_MODULE
tristate "KUnit-incompatible tests of KASAN bug detection capabilities"
depends on m && KASAN
help
This is a part of the KASAN test suite that is incompatible with
KUnit. Currently includes tests that do bad copy_from/to_user
accesses.
endif # KASAN endif # KASAN
...@@ -65,9 +65,11 @@ CFLAGS_test_bitops.o += -Werror ...@@ -65,9 +65,11 @@ CFLAGS_test_bitops.o += -Werror
obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o
obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o
obj-$(CONFIG_TEST_IDA) += test_ida.o obj-$(CONFIG_TEST_IDA) += test_ida.o
obj-$(CONFIG_TEST_KASAN) += test_kasan.o obj-$(CONFIG_KASAN_KUNIT_TEST) += test_kasan.o
CFLAGS_test_kasan.o += -fno-builtin CFLAGS_test_kasan.o += -fno-builtin
CFLAGS_test_kasan.o += $(call cc-disable-warning, vla) CFLAGS_test_kasan.o += $(call cc-disable-warning, vla)
obj-$(CONFIG_TEST_KASAN_MODULE) += test_kasan_module.o
CFLAGS_test_kasan_module.o += -fno-builtin
obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o
CFLAGS_test_ubsan.o += $(call cc-disable-warning, vla) CFLAGS_test_ubsan.o += $(call cc-disable-warning, vla)
UBSAN_SANITIZE_test_ubsan.o := y UBSAN_SANITIZE_test_ubsan.o := y
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/*
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* Author: Andrey Ryabinin <a.ryabinin@samsung.com>
*/
#define pr_fmt(fmt) "kasan test: %s " fmt, __func__
#include <linux/mman.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include "../mm/kasan/kasan.h"
#define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : KASAN_SHADOW_SCALE_SIZE)
static noinline void __init copy_user_test(void)
{
char *kmem;
char __user *usermem;
size_t size = 10;
int unused;
kmem = kmalloc(size, GFP_KERNEL);
if (!kmem)
return;
usermem = (char __user *)vm_mmap(NULL, 0, PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, 0);
if (IS_ERR(usermem)) {
pr_err("Failed to allocate user memory\n");
kfree(kmem);
return;
}
pr_info("out-of-bounds in copy_from_user()\n");
unused = copy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
pr_info("out-of-bounds in copy_to_user()\n");
unused = copy_to_user(usermem, kmem, size + 1 + OOB_TAG_OFF);
pr_info("out-of-bounds in __copy_from_user()\n");
unused = __copy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
pr_info("out-of-bounds in __copy_to_user()\n");
unused = __copy_to_user(usermem, kmem, size + 1 + OOB_TAG_OFF);
pr_info("out-of-bounds in __copy_from_user_inatomic()\n");
unused = __copy_from_user_inatomic(kmem, usermem, size + 1 + OOB_TAG_OFF);
pr_info("out-of-bounds in __copy_to_user_inatomic()\n");
unused = __copy_to_user_inatomic(usermem, kmem, size + 1 + OOB_TAG_OFF);
pr_info("out-of-bounds in strncpy_from_user()\n");
unused = strncpy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
vm_munmap((unsigned long)usermem, PAGE_SIZE);
kfree(kmem);
}
static struct kasan_rcu_info {
int i;
struct rcu_head rcu;
} *global_rcu_ptr;
static noinline void __init kasan_rcu_reclaim(struct rcu_head *rp)
{
struct kasan_rcu_info *fp = container_of(rp,
struct kasan_rcu_info, rcu);
kfree(fp);
fp->i = 1;
}
static noinline void __init kasan_rcu_uaf(void)
{
struct kasan_rcu_info *ptr;
pr_info("use-after-free in kasan_rcu_reclaim\n");
ptr = kmalloc(sizeof(struct kasan_rcu_info), GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
global_rcu_ptr = rcu_dereference_protected(ptr, NULL);
call_rcu(&global_rcu_ptr->rcu, kasan_rcu_reclaim);
}
static int __init test_kasan_module_init(void)
{
/*
* Temporarily enable multi-shot mode. Otherwise, we'd only get a
* report for the first case.
*/
bool multishot = kasan_save_enable_multi_shot();
copy_user_test();
kasan_rcu_uaf();
kasan_restore_multi_shot(multishot);
return -EAGAIN;
}
module_init(test_kasan_module_init);
MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment