lkdtm: Add READ_AFTER_FREE test
In a similar manner to WRITE_AFTER_FREE, add a READ_AFTER_FREE test to test free poisoning features. Sample output when no sanitization is present: # echo READ_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT [ 17.542473] lkdtm: Performing direct entry READ_AFTER_FREE [ 17.543866] lkdtm: Value in memory before free: 12345678 [ 17.545212] lkdtm: Attempting bad read from freed memory [ 17.546542] lkdtm: Memory was not poisoned with slub_debug=P: # echo READ_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT [ 22.415531] lkdtm: Performing direct entry READ_AFTER_FREE [ 22.416366] lkdtm: Value in memory before free: 12345678 [ 22.417137] lkdtm: Attempting bad read from freed memory [ 22.417897] lkdtm: Memory correctly poisoned, calling BUG Signed-off-by: Laura Abbott <labbott@fedoraproject.org> Signed-off-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
parent
ea861d73a9
commit
bc0b8cc6cb
|
@ -92,6 +92,7 @@ enum ctype {
|
|||
CT_UNALIGNED_LOAD_STORE_WRITE,
|
||||
CT_OVERWRITE_ALLOCATION,
|
||||
CT_WRITE_AFTER_FREE,
|
||||
CT_READ_AFTER_FREE,
|
||||
CT_SOFTLOCKUP,
|
||||
CT_HARDLOCKUP,
|
||||
CT_SPINLOCKUP,
|
||||
|
@ -129,6 +130,7 @@ static char* cp_type[] = {
|
|||
"UNALIGNED_LOAD_STORE_WRITE",
|
||||
"OVERWRITE_ALLOCATION",
|
||||
"WRITE_AFTER_FREE",
|
||||
"READ_AFTER_FREE",
|
||||
"SOFTLOCKUP",
|
||||
"HARDLOCKUP",
|
||||
"SPINLOCKUP",
|
||||
|
@ -417,6 +419,42 @@ static void lkdtm_do_action(enum ctype which)
|
|||
memset(data, 0x78, len);
|
||||
break;
|
||||
}
|
||||
case CT_READ_AFTER_FREE: {
|
||||
int *base, *val, saw;
|
||||
size_t len = 1024;
|
||||
/*
|
||||
* The slub allocator uses the first word to store the free
|
||||
* pointer in some configurations. Use the middle of the
|
||||
* allocation to avoid running into the freelist
|
||||
*/
|
||||
size_t offset = (len / sizeof(*base)) / 2;
|
||||
|
||||
base = kmalloc(len, GFP_KERNEL);
|
||||
if (!base)
|
||||
break;
|
||||
|
||||
val = kmalloc(len, GFP_KERNEL);
|
||||
if (!val)
|
||||
break;
|
||||
|
||||
*val = 0x12345678;
|
||||
base[offset] = *val;
|
||||
pr_info("Value in memory before free: %x\n", base[offset]);
|
||||
|
||||
kfree(base);
|
||||
|
||||
pr_info("Attempting bad read from freed memory\n");
|
||||
saw = base[offset];
|
||||
if (saw != *val) {
|
||||
/* Good! Poisoning happened, so declare a win. */
|
||||
pr_info("Memory correctly poisoned, calling BUG\n");
|
||||
BUG();
|
||||
}
|
||||
pr_info("Memory was not poisoned\n");
|
||||
|
||||
kfree(val);
|
||||
break;
|
||||
}
|
||||
case CT_SOFTLOCKUP:
|
||||
preempt_disable();
|
||||
for (;;)
|
||||
|
|
Loading…
Reference in a new issue