mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
nova: use 16bit for reference count of caps
Bomb and any server may generate references to capabilities exceeding 256 - use a 16bit counter until the cap handling in Genode gets unified. Additionally try to print a warning, instead of dying, if we get cap reference count under or overflow. Issue #1615
This commit is contained in:
parent
b1dd5fdf1d
commit
4ee8919f29
@ -39,10 +39,10 @@ namespace Genode {
|
||||
WORDS = (CAP_RANGE_SIZE - HEADER - sizeof(Avl_node<Cap_range>)) / sizeof(addr_t),
|
||||
};
|
||||
|
||||
uint8_t _cap_array[WORDS * sizeof(addr_t)];
|
||||
uint16_t _cap_array[WORDS * sizeof(addr_t) / 2];
|
||||
|
||||
bool _match(addr_t id) {
|
||||
return _base <= id && id < _base + sizeof(_cap_array); };
|
||||
return _base <= id && id < _base + elements(); };
|
||||
|
||||
public:
|
||||
|
||||
@ -51,12 +51,12 @@ namespace Genode {
|
||||
static_assert(sizeof(*this) == CAP_RANGE_SIZE,
|
||||
"Cap_range misconfigured");
|
||||
|
||||
for (unsigned i=0; i < sizeof(_cap_array); i++)
|
||||
for (unsigned i = 0; i < elements(); i++)
|
||||
_cap_array[i] = 0;
|
||||
}
|
||||
|
||||
addr_t const base() const { return _base; }
|
||||
unsigned const elements() { return sizeof(_cap_array); }
|
||||
unsigned const elements() { return sizeof(_cap_array) / sizeof(_cap_array[0]); }
|
||||
|
||||
Cap_range *find_by_id(addr_t);
|
||||
|
||||
|
53
repos/base-nova/src/base/env/cap_map.cc
vendored
53
repos/base-nova/src/base/env/cap_map.cc
vendored
@ -13,13 +13,16 @@
|
||||
|
||||
#include <base/cap_map.h>
|
||||
|
||||
#include <base/printf.h>
|
||||
|
||||
/* base-nova specific include */
|
||||
#include <nova/syscalls.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Capability_map *Genode::cap_map() {
|
||||
Capability_map *Genode::cap_map()
|
||||
{
|
||||
static Genode::Capability_map map;
|
||||
return ↦
|
||||
}
|
||||
@ -39,34 +42,46 @@ Cap_range *Cap_range::find_by_id(addr_t id)
|
||||
}
|
||||
|
||||
|
||||
void Cap_range::inc(unsigned id, bool inc_if_one) {
|
||||
void Cap_range::inc(unsigned id, bool inc_if_one)
|
||||
{
|
||||
bool failure = false;
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
Lock::Guard guard(_lock);
|
||||
if (inc_if_one && _cap_array[id] != 1)
|
||||
return;
|
||||
|
||||
if (inc_if_one && _cap_array[id] != 1)
|
||||
return;
|
||||
|
||||
if (_cap_array[id] == 255) {
|
||||
// PERR("cap overflow - selector %lx - return address %p",
|
||||
// _base + id, __builtin_return_address(0));
|
||||
*reinterpret_cast<addr_t *>(0) = 0xdead;
|
||||
if (_cap_array[id] + 1 == 0)
|
||||
failure = true;
|
||||
else
|
||||
_cap_array[id]++;
|
||||
}
|
||||
|
||||
_cap_array[id]++;
|
||||
if (failure)
|
||||
PERR("cap reference counting error - reference overflow of cap=%lx",
|
||||
_base + id);
|
||||
}
|
||||
|
||||
|
||||
void Cap_range::dec(unsigned id, bool revoke) {
|
||||
void Cap_range::dec(unsigned id, bool revoke)
|
||||
{
|
||||
bool failure = false;
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
Lock::Guard guard(_lock);
|
||||
if (_cap_array[id] == 0)
|
||||
failure = true;
|
||||
else {
|
||||
if (revoke && _cap_array[id] == 1)
|
||||
Nova::revoke(Nova::Obj_crd(_base + id, 0));
|
||||
|
||||
if (_cap_array[id] == 0)
|
||||
*reinterpret_cast<addr_t *>(0) = 0xdead;
|
||||
_cap_array[id]--;
|
||||
}
|
||||
}
|
||||
|
||||
if (revoke && _cap_array[id] == 1)
|
||||
Nova::revoke(Nova::Obj_crd(_base + id, 0));
|
||||
|
||||
_cap_array[id]--;
|
||||
if (failure)
|
||||
PERR("cap reference counting error - count of cap=%lx is already zero",
|
||||
_base + id);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user