diff options
author | Kees Cook <keescook@chromium.org> | 2016-02-26 18:27:35 -0500 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2016-03-01 17:29:16 -0500 |
commit | 7c0ae5be821c1b6a700c5506de9b62e95f60df3c (patch) | |
tree | 8fc2ec6f89e2a2ceb36822397f47046ac22008c8 | |
parent | 5fd9e48084f5566aafb759882f549f37e5940501 (diff) |
lkdtm: improve use-after-free tests
This improves the order of operations on the use-after-free tests to
try to make sure we've executed any available sanity-checking code,
and to report the poisoning that was found.
Signed-off-by: Kees Cook <keescook@chromium.org>
-rw-r--r-- | drivers/misc/lkdtm.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index c333e813ed34..9345999f5673 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -417,7 +417,7 @@ static void lkdtm_do_action(enum ctype which) | |||
417 | break; | 417 | break; |
418 | } | 418 | } |
419 | case CT_WRITE_AFTER_FREE: { | 419 | case CT_WRITE_AFTER_FREE: { |
420 | int *base; | 420 | int *base, *again; |
421 | size_t len = 1024; | 421 | size_t len = 1024; |
422 | /* | 422 | /* |
423 | * The slub allocator uses the first word to store the free | 423 | * The slub allocator uses the first word to store the free |
@@ -428,10 +428,16 @@ static void lkdtm_do_action(enum ctype which) | |||
428 | 428 | ||
429 | base = kmalloc(len, GFP_KERNEL); | 429 | base = kmalloc(len, GFP_KERNEL); |
430 | pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]); | 430 | pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]); |
431 | kfree(base); | ||
432 | pr_info("Attempting bad write to freed memory at %p\n", | 431 | pr_info("Attempting bad write to freed memory at %p\n", |
433 | &base[offset]); | 432 | &base[offset]); |
433 | kfree(base); | ||
434 | base[offset] = 0x0abcdef0; | 434 | base[offset] = 0x0abcdef0; |
435 | /* Attempt to notice the overwrite. */ | ||
436 | again = kmalloc(len, GFP_KERNEL); | ||
437 | kfree(again); | ||
438 | if (again != base) | ||
439 | pr_info("Hmm, didn't get the same memory range.\n"); | ||
440 | |||
435 | break; | 441 | break; |
436 | } | 442 | } |
437 | case CT_READ_AFTER_FREE: { | 443 | case CT_READ_AFTER_FREE: { |
@@ -462,7 +468,7 @@ static void lkdtm_do_action(enum ctype which) | |||
462 | saw = base[offset]; | 468 | saw = base[offset]; |
463 | if (saw != *val) { | 469 | if (saw != *val) { |
464 | /* Good! Poisoning happened, so declare a win. */ | 470 | /* Good! Poisoning happened, so declare a win. */ |
465 | pr_info("Memory correctly poisoned, calling BUG\n"); | 471 | pr_info("Memory correctly poisoned (%x)\n", saw); |
466 | BUG(); | 472 | BUG(); |
467 | } | 473 | } |
468 | pr_info("Memory was not poisoned\n"); | 474 | pr_info("Memory was not poisoned\n"); |
@@ -480,6 +486,11 @@ static void lkdtm_do_action(enum ctype which) | |||
480 | schedule(); | 486 | schedule(); |
481 | pr_info("Attempting bad write to the buddy page after free\n"); | 487 | pr_info("Attempting bad write to the buddy page after free\n"); |
482 | memset((void *)p, 0x78, PAGE_SIZE); | 488 | memset((void *)p, 0x78, PAGE_SIZE); |
489 | /* Attempt to notice the overwrite. */ | ||
490 | p = __get_free_page(GFP_KERNEL); | ||
491 | free_page(p); | ||
492 | schedule(); | ||
493 | |||
483 | break; | 494 | break; |
484 | } | 495 | } |
485 | case CT_READ_BUDDY_AFTER_FREE: { | 496 | case CT_READ_BUDDY_AFTER_FREE: { |
@@ -503,7 +514,7 @@ static void lkdtm_do_action(enum ctype which) | |||
503 | saw = base[0]; | 514 | saw = base[0]; |
504 | if (saw != *val) { | 515 | if (saw != *val) { |
505 | /* Good! Poisoning happened, so declare a win. */ | 516 | /* Good! Poisoning happened, so declare a win. */ |
506 | pr_info("Buddy page correctly poisoned, calling BUG\n"); | 517 | pr_info("Memory correctly poisoned (%x)\n", saw); |
507 | BUG(); | 518 | BUG(); |
508 | } | 519 | } |
509 | pr_info("Buddy page was not poisoned\n"); | 520 | pr_info("Buddy page was not poisoned\n"); |