Commit 9ec42f94 authored by Andrew Morton's avatar Andrew Morton Committed by James Bottomley

[PATCH] slab use-after-free detector

Patch from Petr Vandrovec <vandrove@vc.cvut.cz>

Modifies check_poison function to not only verify that last byte is
POISON_END, but also that all preceeding bytes are either POISON_BEFORE or
POISON_AFTER bytes.
parent 7a6b4e0d
......@@ -768,6 +768,21 @@ static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val)
*(unsigned char *)(addr+size-1) = POISON_END;
}
static void *fprob(unsigned char* addr, unsigned int size)
{
unsigned char *end;
end = addr + size - 1;
for (; addr < end; addr++) {
if (*addr != POISON_BEFORE && *addr != POISON_AFTER)
return addr;
}
if (*addr != POISON_END)
return addr;
return NULL;
}
static void check_poison_obj(kmem_cache_t *cachep, void *addr)
{
int size = cachep->objsize;
......@@ -776,9 +791,33 @@ static void check_poison_obj(kmem_cache_t *cachep, void *addr)
addr += BYTES_PER_WORD;
size -= 2*BYTES_PER_WORD;
}
end = memchr(addr, POISON_END, size);
if (end != (addr+size-1))
end = fprob(addr, size);
if (end) {
int s;
printk(KERN_ERR "Slab corruption: start=%p, expend=%p, "
"problemat=%p\n", addr, addr+size-1, end);
printk(KERN_ERR "Data: ");
for (s = 0; s < size; s++) {
if (((char*)addr)[s] == POISON_BEFORE)
printk(".");
else if (((char*)addr)[s] == POISON_AFTER)
printk("*");
else
printk("%02X ", ((unsigned char*)addr)[s]);
}
printk("\n");
printk(KERN_ERR "Next: ");
for (; s < size + 32; s++) {
if (((char*)addr)[s] == POISON_BEFORE)
printk(".");
else if (((char*)addr)[s] == POISON_AFTER)
printk("*");
else
printk("%02X ", ((unsigned char*)addr)[s]);
}
printk("\n");
slab_error(cachep, "object was modified after freeing");
}
}
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment