Commit a2f11547 authored by Matthew Maurer's avatar Matthew Maurer Committed by Miguel Ojeda

kasan: rust: Add KASAN smoke test via UAF

Adds a smoke test to ensure that KASAN in Rust is actually detecting a
Rust-native UAF. There is significant room to expand this test suite,
but this will at least ensure that flags are having the intended effect.

The rename from kasan_test.c to kasan_test_c.c is in order to allow the
single kasan_test.ko test suite to contain both a .o file produced
by the C compiler and one produced by rustc.
Signed-off-by: default avatarMatthew Maurer <mmaurer@google.com>
Reviewed-by: default avatarAndrey Konovalov <andreyknvl@gmail.com>
Link: https://lore.kernel.org/r/20240820194910.187826-5-mmaurer@google.com
[ Applied empty line nit, removed double empty line,
  applied `rustfmt` and formatted crate comment. - Miguel ]
Signed-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
parent e3117404
...@@ -44,7 +44,8 @@ ifndef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX ...@@ -44,7 +44,8 @@ ifndef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX
CFLAGS_KASAN_TEST += -fno-builtin CFLAGS_KASAN_TEST += -fno-builtin
endif endif
CFLAGS_kasan_test.o := $(CFLAGS_KASAN_TEST) CFLAGS_kasan_test_c.o := $(CFLAGS_KASAN_TEST)
RUSTFLAGS_kasan_test_rust.o := $(RUSTFLAGS_KASAN)
CFLAGS_kasan_test_module.o := $(CFLAGS_KASAN_TEST) CFLAGS_kasan_test_module.o := $(CFLAGS_KASAN_TEST)
obj-y := common.o report.o obj-y := common.o report.o
...@@ -52,5 +53,10 @@ obj-$(CONFIG_KASAN_GENERIC) += init.o generic.o report_generic.o shadow.o quaran ...@@ -52,5 +53,10 @@ obj-$(CONFIG_KASAN_GENERIC) += init.o generic.o report_generic.o shadow.o quaran
obj-$(CONFIG_KASAN_HW_TAGS) += hw_tags.o report_hw_tags.o tags.o report_tags.o obj-$(CONFIG_KASAN_HW_TAGS) += hw_tags.o report_hw_tags.o tags.o report_tags.o
obj-$(CONFIG_KASAN_SW_TAGS) += init.o report_sw_tags.o shadow.o sw_tags.o tags.o report_tags.o obj-$(CONFIG_KASAN_SW_TAGS) += init.o report_sw_tags.o shadow.o sw_tags.o tags.o report_tags.o
kasan_test-objs := kasan_test_c.o
ifdef CONFIG_RUST
kasan_test-objs += kasan_test_rust.o
endif
obj-$(CONFIG_KASAN_KUNIT_TEST) += kasan_test.o obj-$(CONFIG_KASAN_KUNIT_TEST) += kasan_test.o
obj-$(CONFIG_KASAN_MODULE_TEST) += kasan_test_module.o obj-$(CONFIG_KASAN_MODULE_TEST) += kasan_test_module.o
...@@ -555,6 +555,12 @@ static inline bool kasan_arch_is_ready(void) { return true; } ...@@ -555,6 +555,12 @@ static inline bool kasan_arch_is_ready(void) { return true; }
void kasan_kunit_test_suite_start(void); void kasan_kunit_test_suite_start(void);
void kasan_kunit_test_suite_end(void); void kasan_kunit_test_suite_end(void);
#ifdef CONFIG_RUST
char kasan_test_rust_uaf(void);
#else
static inline char kasan_test_rust_uaf(void) { return '\0'; }
#endif
#else /* CONFIG_KASAN_KUNIT_TEST */ #else /* CONFIG_KASAN_KUNIT_TEST */
static inline void kasan_kunit_test_suite_start(void) { } static inline void kasan_kunit_test_suite_start(void) { }
......
...@@ -1899,6 +1899,16 @@ static void match_all_mem_tag(struct kunit *test) ...@@ -1899,6 +1899,16 @@ static void match_all_mem_tag(struct kunit *test)
kfree(ptr); kfree(ptr);
} }
/*
* Check that Rust performing a use-after-free using `unsafe` is detected.
* This is a smoke test to make sure that Rust is being sanitized properly.
*/
static void rust_uaf(struct kunit *test)
{
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_RUST);
KUNIT_EXPECT_KASAN_FAIL(test, kasan_test_rust_uaf());
}
static struct kunit_case kasan_kunit_test_cases[] = { static struct kunit_case kasan_kunit_test_cases[] = {
KUNIT_CASE(kmalloc_oob_right), KUNIT_CASE(kmalloc_oob_right),
KUNIT_CASE(kmalloc_oob_left), KUNIT_CASE(kmalloc_oob_left),
...@@ -1971,6 +1981,7 @@ static struct kunit_case kasan_kunit_test_cases[] = { ...@@ -1971,6 +1981,7 @@ static struct kunit_case kasan_kunit_test_cases[] = {
KUNIT_CASE(match_all_not_assigned), KUNIT_CASE(match_all_not_assigned),
KUNIT_CASE(match_all_ptr_tag), KUNIT_CASE(match_all_ptr_tag),
KUNIT_CASE(match_all_mem_tag), KUNIT_CASE(match_all_mem_tag),
KUNIT_CASE(rust_uaf),
{} {}
}; };
......
// SPDX-License-Identifier: GPL-2.0
//! Helper crate for KASAN testing.
//!
//! Provides behavior to check the sanitization of Rust code.
use core::ptr::addr_of_mut;
use kernel::prelude::*;
/// Trivial UAF - allocate a big vector, grab a pointer partway through,
/// drop the vector, and touch it.
#[no_mangle]
pub extern "C" fn kasan_test_rust_uaf() -> u8 {
let mut v: Vec<u8> = Vec::new();
for _ in 0..4096 {
v.push(0x42, GFP_KERNEL).unwrap();
}
let ptr: *mut u8 = addr_of_mut!(v[2048]);
drop(v);
unsafe { *ptr }
}
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