slab: detect corrupted slab and invalid frees

and report about that.

Fixes #2350
This commit is contained in:
Alexander Boettcher
2017-03-23 23:20:35 +01:00
committed by Christian Helmuth
parent 62c59a56d1
commit 1c79ba4182
4 changed files with 49 additions and 11 deletions

View File

@ -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,8 +322,8 @@ 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 ",
_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++;