Skip to content

Commit a2f1154

Browse files
maurerojeda
authored andcommitted
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: Matthew Maurer <[email protected]> Reviewed-by: Andrey Konovalov <[email protected]> Link: https://lore.kernel.org/r/[email protected] [ Applied empty line nit, removed double empty line, applied `rustfmt` and formatted crate comment. - Miguel ] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent e311740 commit a2f1154

File tree

4 files changed

+45
-1
lines changed

4 files changed

+45
-1
lines changed

mm/kasan/Makefile

+7-1
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,19 @@ ifndef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX
4444
CFLAGS_KASAN_TEST += -fno-builtin
4545
endif
4646

47-
CFLAGS_kasan_test.o := $(CFLAGS_KASAN_TEST)
47+
CFLAGS_kasan_test_c.o := $(CFLAGS_KASAN_TEST)
48+
RUSTFLAGS_kasan_test_rust.o := $(RUSTFLAGS_KASAN)
4849
CFLAGS_kasan_test_module.o := $(CFLAGS_KASAN_TEST)
4950

5051
obj-y := common.o report.o
5152
obj-$(CONFIG_KASAN_GENERIC) += init.o generic.o report_generic.o shadow.o quarantine.o
5253
obj-$(CONFIG_KASAN_HW_TAGS) += hw_tags.o report_hw_tags.o tags.o report_tags.o
5354
obj-$(CONFIG_KASAN_SW_TAGS) += init.o report_sw_tags.o shadow.o sw_tags.o tags.o report_tags.o
5455

56+
kasan_test-objs := kasan_test_c.o
57+
ifdef CONFIG_RUST
58+
kasan_test-objs += kasan_test_rust.o
59+
endif
60+
5561
obj-$(CONFIG_KASAN_KUNIT_TEST) += kasan_test.o
5662
obj-$(CONFIG_KASAN_MODULE_TEST) += kasan_test_module.o

mm/kasan/kasan.h

+6
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,12 @@ static inline bool kasan_arch_is_ready(void) { return true; }
555555
void kasan_kunit_test_suite_start(void);
556556
void kasan_kunit_test_suite_end(void);
557557

558+
#ifdef CONFIG_RUST
559+
char kasan_test_rust_uaf(void);
560+
#else
561+
static inline char kasan_test_rust_uaf(void) { return '\0'; }
562+
#endif
563+
558564
#else /* CONFIG_KASAN_KUNIT_TEST */
559565

560566
static inline void kasan_kunit_test_suite_start(void) { }

mm/kasan/kasan_test.c renamed to mm/kasan/kasan_test_c.c

+11
Original file line numberDiff line numberDiff line change
@@ -1899,6 +1899,16 @@ static void match_all_mem_tag(struct kunit *test)
18991899
kfree(ptr);
19001900
}
19011901

1902+
/*
1903+
* Check that Rust performing a use-after-free using `unsafe` is detected.
1904+
* This is a smoke test to make sure that Rust is being sanitized properly.
1905+
*/
1906+
static void rust_uaf(struct kunit *test)
1907+
{
1908+
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_RUST);
1909+
KUNIT_EXPECT_KASAN_FAIL(test, kasan_test_rust_uaf());
1910+
}
1911+
19021912
static struct kunit_case kasan_kunit_test_cases[] = {
19031913
KUNIT_CASE(kmalloc_oob_right),
19041914
KUNIT_CASE(kmalloc_oob_left),
@@ -1971,6 +1981,7 @@ static struct kunit_case kasan_kunit_test_cases[] = {
19711981
KUNIT_CASE(match_all_not_assigned),
19721982
KUNIT_CASE(match_all_ptr_tag),
19731983
KUNIT_CASE(match_all_mem_tag),
1984+
KUNIT_CASE(rust_uaf),
19741985
{}
19751986
};
19761987

mm/kasan/kasan_test_rust.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Helper crate for KASAN testing.
4+
//!
5+
//! Provides behavior to check the sanitization of Rust code.
6+
7+
use core::ptr::addr_of_mut;
8+
use kernel::prelude::*;
9+
10+
/// Trivial UAF - allocate a big vector, grab a pointer partway through,
11+
/// drop the vector, and touch it.
12+
#[no_mangle]
13+
pub extern "C" fn kasan_test_rust_uaf() -> u8 {
14+
let mut v: Vec<u8> = Vec::new();
15+
for _ in 0..4096 {
16+
v.push(0x42, GFP_KERNEL).unwrap();
17+
}
18+
let ptr: *mut u8 = addr_of_mut!(v[2048]);
19+
drop(v);
20+
unsafe { *ptr }
21+
}

0 commit comments

Comments
 (0)