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

kasan: test: bypass __alloc_size checks

Intentional overflows, as performed by the KASAN tests, are detected at
compile time[1] (instead of only at run-time) with the addition of
__alloc_size. Fix this by forcing the compiler into not being able to
trust the size used following the kmalloc()s.

[1] https://lore.kernel.org/lkml/20211005184717.65c6d8eb39350395e387b71f@linux-foundation.org

Link: https://lkml.kernel.org/r/20211006181544.1670992-1-keescook@chromium.org
Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Konovalov <andreyknvl@gmail.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Kees Cook and committed by
Linus Torvalds
d73dad4e 8772716f

+9 -1
+7 -1
lib/test_kasan.c
··· 440 440 ptr = kmalloc(size, GFP_KERNEL); 441 441 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); 442 442 443 + OPTIMIZER_HIDE_VAR(size); 443 444 KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 1, 0, 2)); 444 445 kfree(ptr); 445 446 } ··· 453 452 ptr = kmalloc(size, GFP_KERNEL); 454 453 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); 455 454 455 + OPTIMIZER_HIDE_VAR(size); 456 456 KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 3, 0, 4)); 457 457 kfree(ptr); 458 458 } ··· 466 464 ptr = kmalloc(size, GFP_KERNEL); 467 465 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); 468 466 467 + OPTIMIZER_HIDE_VAR(size); 469 468 KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 7, 0, 8)); 470 469 kfree(ptr); 471 470 } ··· 479 476 ptr = kmalloc(size, GFP_KERNEL); 480 477 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); 481 478 479 + OPTIMIZER_HIDE_VAR(size); 482 480 KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 15, 0, 16)); 483 481 kfree(ptr); 484 482 } ··· 492 488 ptr = kmalloc(size, GFP_KERNEL); 493 489 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); 494 490 491 + OPTIMIZER_HIDE_VAR(size); 495 492 KUNIT_EXPECT_KASAN_FAIL(test, 496 493 memset(ptr, 0, size + KASAN_GRANULE_SIZE)); 497 494 kfree(ptr); ··· 502 497 { 503 498 char *ptr; 504 499 size_t size = 64; 505 - volatile size_t invalid_size = -2; 500 + size_t invalid_size = -2; 506 501 507 502 /* 508 503 * Hardware tag-based mode doesn't check memmove for negative size. ··· 515 510 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); 516 511 517 512 memset((char *)ptr, 0, 64); 513 + OPTIMIZER_HIDE_VAR(invalid_size); 518 514 KUNIT_EXPECT_KASAN_FAIL(test, 519 515 memmove((char *)ptr, (char *)ptr + 4, invalid_size)); 520 516 kfree(ptr);
+2
lib/test_kasan_module.c
··· 35 35 return; 36 36 } 37 37 38 + OPTIMIZER_HIDE_VAR(size); 39 + 38 40 pr_info("out-of-bounds in copy_from_user()\n"); 39 41 unused = copy_from_user(kmem, usermem, size + 1); 40 42