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"
|
build "core init drivers/timer test/slab"
|
||||||
|
|
||||||
create_boot_directory
|
create_boot_directory
|
||||||
|
@ -23,6 +23,8 @@ using namespace Genode;
|
|||||||
*/
|
*/
|
||||||
class Genode::Slab::Block
|
class Genode::Slab::Block
|
||||||
{
|
{
|
||||||
|
friend struct Genode::Slab::Entry;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Block *next = this; /* next block in ring */
|
Block *next = this; /* next block in ring */
|
||||||
@ -71,6 +73,12 @@ class Genode::Slab::Block
|
|||||||
*/
|
*/
|
||||||
int _slab_entry_idx(Entry *e);
|
int _slab_entry_idx(Entry *e);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These functions are called by Slab::Entry.
|
||||||
|
*/
|
||||||
|
void inc_avail(Entry &e);
|
||||||
|
void dec_avail() { _avail--; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,12 +104,6 @@ class Genode::Slab::Block
|
|||||||
* Return a used slab block entry
|
* Return a used slab block entry
|
||||||
*/
|
*/
|
||||||
Entry *any_used_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);
|
block.inc_avail(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool used() {
|
||||||
|
return block._state(block._slab_entry_idx(this)) == Block::USED; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup Entry by given address
|
* Lookup Entry by given address
|
||||||
*
|
*
|
||||||
@ -317,8 +322,8 @@ bool Slab::alloc(size_t size, void **out_addr)
|
|||||||
|
|
||||||
/* too large for us ? */
|
/* too large for us ? */
|
||||||
if (size > _slab_size) {
|
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);
|
_slab_size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,8 +375,20 @@ void Slab::_free(void *addr)
|
|||||||
if (!e)
|
if (!e)
|
||||||
return;
|
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;
|
Block &block = e->block;
|
||||||
|
|
||||||
|
if (!e->used()) {
|
||||||
|
error("slab address ", addr, " freed which is unused");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
e->~Entry();
|
e->~Entry();
|
||||||
_total_avail++;
|
_total_avail++;
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
* \brief Slab allocator test
|
* \brief Slab allocator test
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
* \date 2015-03-31
|
* \date 2015-03-31
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -65,7 +64,7 @@ struct Array_of_slab_elements
|
|||||||
|
|
||||||
void Component::construct(Genode::Env & env)
|
void Component::construct(Genode::Env & env)
|
||||||
{
|
{
|
||||||
Genode::Heap heap(env.ram(), env.rm());
|
static Genode::Heap heap(env.ram(), env.rm());
|
||||||
|
|
||||||
log("--- slab test ---");
|
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
|
* take the overhead of the two block allocations at the heap into
|
||||||
* account.
|
* account.
|
||||||
*/
|
*/
|
||||||
enum { HEAP_OVERHEAD = 36 };
|
enum { HEAP_OVERHEAD = 9*sizeof(long) };
|
||||||
if (alloc.consumed() > 2*(BLOCK_SIZE + HEAP_OVERHEAD)) {
|
if (alloc.consumed() > 2*(BLOCK_SIZE + HEAP_OVERHEAD)) {
|
||||||
error("slab failed to release empty slab blocks");
|
error("slab failed to release empty slab blocks");
|
||||||
return;
|
return;
|
||||||
@ -108,5 +107,21 @@ void Component::construct(Genode::Env & env)
|
|||||||
return;
|
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");
|
log("Test done");
|
||||||
}
|
}
|
||||||
|
@ -90,3 +90,4 @@ trace
|
|||||||
input_filter
|
input_filter
|
||||||
init
|
init
|
||||||
nic_dump
|
nic_dump
|
||||||
|
slab
|
||||||
|
Loading…
Reference in New Issue
Block a user