mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
slab: detect corrupted slab and invalid frees
and report about that. Fixes #2350
This commit is contained in:
parent
62c59a56d1
commit
1c79ba4182
@ -1,3 +1,8 @@
|
||||
if {[get_cmd_switch --autopilot] && [have_include "power_on/qemu"]} {
|
||||
puts "\nRunning slab benchmark in autopilot on Qemu is not recommended.\n"
|
||||
exit
|
||||
}
|
||||
|
||||
build "core init drivers/timer test/slab"
|
||||
|
||||
create_boot_directory
|
||||
|
@ -23,6 +23,8 @@ using namespace Genode;
|
||||
*/
|
||||
class Genode::Slab::Block
|
||||
{
|
||||
friend struct Genode::Slab::Entry;
|
||||
|
||||
public:
|
||||
|
||||
Block *next = this; /* next block in ring */
|
||||
@ -71,6 +73,12 @@ class Genode::Slab::Block
|
||||
*/
|
||||
int _slab_entry_idx(Entry *e);
|
||||
|
||||
/**
|
||||
* These functions are called by Slab::Entry.
|
||||
*/
|
||||
void inc_avail(Entry &e);
|
||||
void dec_avail() { _avail--; }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -96,12 +104,6 @@ class Genode::Slab::Block
|
||||
* Return a used slab block entry
|
||||
*/
|
||||
Entry *any_used_entry();
|
||||
|
||||
/**
|
||||
* These functions are called by Slab::Entry.
|
||||
*/
|
||||
void inc_avail(Entry &e);
|
||||
void dec_avail() { _avail--; }
|
||||
};
|
||||
|
||||
|
||||
@ -124,6 +126,9 @@ struct Genode::Slab::Entry
|
||||
block.inc_avail(*this);
|
||||
}
|
||||
|
||||
bool used() {
|
||||
return block._state(block._slab_entry_idx(this)) == Block::USED; }
|
||||
|
||||
/**
|
||||
* Lookup Entry by given address
|
||||
*
|
||||
@ -317,7 +322,7 @@ bool Slab::alloc(size_t size, void **out_addr)
|
||||
|
||||
/* too large for us ? */
|
||||
if (size > _slab_size) {
|
||||
Genode::error("requested size ", size, " is larger then slab size ",
|
||||
error("requested size ", size, " is larger then slab size ",
|
||||
_slab_size);
|
||||
return false;
|
||||
}
|
||||
@ -370,8 +375,20 @@ void Slab::_free(void *addr)
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
if (addr < (void *)((addr_t)&e->block + sizeof(e->block)) ||
|
||||
addr >= (void *)((addr_t)&e->block + _block_size)) {
|
||||
error("slab block ", Hex_range<addr_t>((addr_t)&e->block, _block_size),
|
||||
" is corrupt - slab address ", addr);
|
||||
return;
|
||||
}
|
||||
|
||||
Block &block = e->block;
|
||||
|
||||
if (!e->used()) {
|
||||
error("slab address ", addr, " freed which is unused");
|
||||
return;
|
||||
}
|
||||
|
||||
e->~Entry();
|
||||
_total_avail++;
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
* \brief Slab allocator test
|
||||
* \author Norman Feske
|
||||
* \date 2015-03-31
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -65,7 +64,7 @@ struct Array_of_slab_elements
|
||||
|
||||
void Component::construct(Genode::Env & env)
|
||||
{
|
||||
Genode::Heap heap(env.ram(), env.rm());
|
||||
static Genode::Heap heap(env.ram(), env.rm());
|
||||
|
||||
log("--- slab test ---");
|
||||
|
||||
@ -94,7 +93,7 @@ void Component::construct(Genode::Env & env)
|
||||
* take the overhead of the two block allocations at the heap into
|
||||
* account.
|
||||
*/
|
||||
enum { HEAP_OVERHEAD = 36 };
|
||||
enum { HEAP_OVERHEAD = 9*sizeof(long) };
|
||||
if (alloc.consumed() > 2*(BLOCK_SIZE + HEAP_OVERHEAD)) {
|
||||
error("slab failed to release empty slab blocks");
|
||||
return;
|
||||
@ -108,5 +107,21 @@ void Component::construct(Genode::Env & env)
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
log("test double-free detection - error message is expected");
|
||||
|
||||
Genode::Slab slab(SLAB_SIZE, BLOCK_SIZE, nullptr, &alloc);
|
||||
|
||||
void *p = nullptr;
|
||||
{
|
||||
Array_of_slab_elements array(slab, 4096, SLAB_SIZE, heap);
|
||||
p = array.elem[1705];
|
||||
}
|
||||
slab.free(p, SLAB_SIZE);
|
||||
{
|
||||
Array_of_slab_elements array(slab, 4096, SLAB_SIZE, heap);
|
||||
}
|
||||
}
|
||||
|
||||
log("Test done");
|
||||
}
|
||||
|
@ -90,3 +90,4 @@ trace
|
||||
input_filter
|
||||
init
|
||||
nic_dump
|
||||
slab
|
||||
|
Loading…
Reference in New Issue
Block a user