Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm: kmsan: add tests for high-order page freeing

Add regression tests to verify that KMSAN correctly poisons the full
memory range when freeing pages.

Specifically, verify that accessing the tail pages of a high-order
non-compound allocation triggers a use-after-free report. This ensures
that the fix "mm: kmsan: Fix poisoning of high-order non-compound pages"
is working as expected.

Also add a test for standard order-0 pages for completeness.

Link: https://lore.kernel.org/all/20260104134348.3544298-1-ryan.roberts@arm.com/
Link: https://lkml.kernel.org/r/20260113091151.4035013-1-glider@google.com
Signed-off-by: Alexander Potapenko <glider@google.com>
Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Marco Elver <elver@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Alexander Potapenko and committed by
Andrew Morton
79ffad20 ed581147

+48 -1
+48 -1
mm/kmsan/kmsan_test.c
··· 361 361 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 362 362 } 363 363 364 - /* Test case: ensure that use-after-free reporting works. */ 364 + /* Test case: ensure that use-after-free reporting works for kmalloc. */ 365 365 static void test_uaf(struct kunit *test) 366 366 { 367 367 EXPECTATION_USE_AFTER_FREE(expect); ··· 375 375 /* Copy the invalid value before checking it. */ 376 376 value = var[3]; 377 377 USE(value); 378 + KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 379 + } 380 + 381 + static volatile char *test_uaf_pages_helper(int order, int offset) 382 + { 383 + struct page *page; 384 + volatile char *var; 385 + 386 + /* Memory is initialized up until __free_pages() thanks to __GFP_ZERO. */ 387 + page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); 388 + var = page_address(page) + offset; 389 + __free_pages(page, order); 390 + 391 + return var; 392 + } 393 + 394 + /* Test case: ensure that use-after-free reporting works for a freed page. */ 395 + static void test_uaf_pages(struct kunit *test) 396 + { 397 + EXPECTATION_USE_AFTER_FREE(expect); 398 + volatile char value; 399 + 400 + kunit_info(test, "use-after-free on a freed page (UMR report)\n"); 401 + /* Allocate a single page, free it, then try to access it. */ 402 + value = *test_uaf_pages_helper(0, 3); 403 + USE(value); 404 + 405 + KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 406 + } 407 + 408 + /* Test case: ensure that UAF reporting works for high order pages. */ 409 + static void test_uaf_high_order_pages(struct kunit *test) 410 + { 411 + EXPECTATION_USE_AFTER_FREE(expect); 412 + volatile char value; 413 + 414 + kunit_info(test, 415 + "use-after-free on a freed high-order page (UMR report)\n"); 416 + /* 417 + * Create a high-order non-compound page, free it, then try to access 418 + * its tail page. 419 + */ 420 + value = *test_uaf_pages_helper(1, PAGE_SIZE + 3); 421 + USE(value); 422 + 378 423 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 379 424 } 380 425 ··· 728 683 KUNIT_CASE(test_init_kmsan_vmap_vunmap), 729 684 KUNIT_CASE(test_init_vmalloc), 730 685 KUNIT_CASE(test_uaf), 686 + KUNIT_CASE(test_uaf_pages), 687 + KUNIT_CASE(test_uaf_high_order_pages), 731 688 KUNIT_CASE(test_percpu_propagate), 732 689 KUNIT_CASE(test_printk), 733 690 KUNIT_CASE(test_init_memcpy),