base: enable executable memory fault handling

Fixes #1723
This commit is contained in:
Alexander Boettcher 2017-10-13 15:26:33 +02:00 committed by Christian Helmuth
parent 03b8e70d3f
commit db329b02b5
11 changed files with 77 additions and 32 deletions

View File

@ -48,11 +48,10 @@ namespace Genode {
*/
Mapping(addr_t dst_addr, addr_t src_addr,
Cache_attribute cacheability, bool io_mem,
unsigned l2size = L4_LOG2_PAGESIZE,
bool rw = true, bool grant = false)
unsigned l2size, bool rw, bool executable)
:
_dst_addr(dst_addr),
_fpage(Fiasco::l4_fpage(src_addr, l2size, rw, grant))
_fpage(Fiasco::l4_fpage(src_addr, l2size, rw, false))
{
if (cacheability == WRITE_COMBINED)
_fpage.fp.cache = Fiasco::L4_FPAGE_BUFFERABLE;
@ -163,6 +162,8 @@ namespace Genode {
bool write_fault() const { return (_pf_addr & 2); }
bool exec_fault() const { return false; }
/**
* Return true if last fault was an exception
*/

View File

@ -45,7 +45,6 @@ namespace Genode {
bool _iomem;
unsigned _log2size;
bool _rw;
bool _grant;
public:
@ -54,20 +53,20 @@ namespace Genode {
*/
Mapping(addr_t dst_addr, addr_t src_addr,
Cache_attribute c, bool io_mem,
unsigned l2size = L4_LOG2_PAGESIZE,
bool rw = true, bool grant = false)
unsigned l2size,
bool rw, bool executable)
: _dst_addr(dst_addr), _src_addr(src_addr),
_cacheability(c), _iomem(io_mem), _log2size(l2size),
_rw(rw), _grant(grant) { }
_rw(rw) { }
/**
* Construct invalid flexpage
*/
Mapping() : _dst_addr(0), _src_addr(0), _cacheability(UNCACHED),
_iomem(false), _log2size(0), _rw(false), _grant(false) { }
_iomem(false), _log2size(0), _rw(false) { }
Fiasco::l4_umword_t dst_addr() const { return _dst_addr; }
bool grant() const { return _grant; }
bool grant() const { return false; }
Fiasco::l4_fpage_t fpage() const
{
@ -176,6 +175,8 @@ namespace Genode {
bool write_fault() const { return (_pf_addr & 2); }
bool exec_fault() const { return false; }
/**
* Return true if last fault was an exception
*/

View File

@ -65,7 +65,8 @@ struct Genode::Mapping : Hw::Mapping
Cache_attribute cacheable,
bool io,
unsigned size_log2,
bool writeable)
bool writeable,
bool executable)
: Hw::Mapping(phys, virt, 1 << size_log2,
{ writeable ? Hw::RW : Hw::RO, Hw::EXEC, Hw::USER,
Hw::NO_GLOBAL, io ? Hw::DEVICE : Hw::RAM, cacheable }) {}
@ -108,6 +109,11 @@ class Genode::Ipc_pager
*/
bool write_fault() const;
/**
* Executable permission fault
*/
bool exec_fault() const { return false; }
/**
* Input mapping data as reply to current page fault
*/

View File

@ -43,8 +43,8 @@ namespace Genode {
*/
Mapping(addr_t dst_addr, addr_t map_addr,
Cache_attribute c, bool io_mem,
unsigned size_log2 = PAGE_SIZE_LOG2,
bool rw = true)
unsigned size_log2,
bool rw, bool executable)
:
_dst_addr(dst_addr), _core_local_addr(map_addr),
_attr(c), _size_log2(size_log2), _rw(rw)
@ -125,6 +125,11 @@ namespace Genode {
*/
bool write_fault() const { return _fault_type & ERR_W; }
/**
* Return true if fault was a non-executable fault
*/
bool exec_fault() const { return false; }
/**
* Return true if last fault was an exception
*/

View File

@ -41,7 +41,7 @@ namespace Genode {
*/
Mapping(addr_t dst_addr, addr_t src_addr,
Cache_attribute cacheability, bool io_mem,
unsigned l2size = 12, bool rw = true);
unsigned l2size, bool rw, bool executable);
/**
* Construct invalid mapping
@ -162,6 +162,11 @@ namespace Genode {
*/
bool write_fault() const { return L4_Label(_faulter_tag) & 2; }
/**
* Return true if last fault was a executable fault
*/
bool exec_fault() const { return false; }
/**
* Return true if last fault was an exception
*/

View File

@ -73,7 +73,7 @@ static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
Mapping::Mapping(addr_t dst_addr, addr_t src_addr,
Cache_attribute cacheability, bool io_mem,
unsigned l2size, bool rw)
unsigned l2size, bool rw, bool executable)
:
_fpage(L4_FpageLog2(dst_addr, l2size)),
/*

View File

@ -46,8 +46,8 @@ namespace Genode {
*/
Mapping(addr_t dst_addr, addr_t src_addr,
Cache_attribute, bool io_mem,
unsigned l2size = Pistachio::get_page_size_log2(),
bool rw = true, bool grant = false);
unsigned l2size,
bool rw, bool executable);
/**
* Construct invalid mapping
@ -169,6 +169,11 @@ namespace Genode {
*/
bool write_fault() const { return (_flags & 2); }
/**
* Return true if last fault was a executable fault
*/
bool exec_fault() const { return false; }
/**
* Return true if last fault was an exception
*/

View File

@ -41,8 +41,10 @@ using namespace Pistachio;
Mapping::Mapping(addr_t dst_addr, addr_t src_addr,
Cache_attribute, bool io_mem, unsigned l2size,
bool rw, bool grant)
bool rw, bool executable)
{
bool const grant = false;
L4_Fpage_t fpage = L4_FpageLog2(src_addr, l2size);
fpage += rw ? L4_FullyAccessible : L4_Readable;

View File

@ -44,8 +44,7 @@ namespace Genode {
*/
Mapping(addr_t dst_addr, addr_t src_addr,
Cache_attribute const cacheability, bool io_mem,
unsigned l2size = PAGE_SIZE_LOG2,
bool rw = true)
unsigned l2size, bool rw, bool executable)
:
_from_phys_addr(src_addr),
_to_virt_addr(dst_addr),
@ -142,6 +141,11 @@ namespace Genode {
* Return true if page fault was a write fault
*/
bool write_fault() const { return _pf_write; }
/**
* Return true if page fault was on non-executable memory
*/
bool exec_fault() const { return false; }
};
}

View File

@ -65,6 +65,7 @@ class Genode::Rm_region : public List<Rm_region>::Element
addr_t _base = 0;
size_t _size = 0;
bool _write = false;
bool _exec = false;
Dataspace_component *_dsc = nullptr;
off_t _off = 0;
@ -80,8 +81,8 @@ class Genode::Rm_region : public List<Rm_region>::Element
Rm_region(addr_t base, size_t size, bool write,
Dataspace_component *dsc, off_t offset,
Region_map_component *rm)
: _base(base), _size(size), _write(write),
Region_map_component *rm, bool exec)
: _base(base), _size(size), _write(write), _exec(exec),
_dsc(dsc), _off(offset), _rm(rm) { }
@ -89,12 +90,13 @@ class Genode::Rm_region : public List<Rm_region>::Element
** Accessors **
***************/
addr_t base() const { return _base; }
size_t size() const { return _size; }
bool write() const { return _write; }
Dataspace_component* dataspace() const { return _dsc; }
off_t offset() const { return _off; }
Region_map_component* rm() const { return _rm; }
addr_t base() const { return _base; }
size_t size() const { return _size; }
bool write() const { return _write; }
bool executable() const { return _exec; }
Dataspace_component* dataspace() const { return _dsc; }
off_t offset() const { return _off; }
Region_map_component* rm() const { return _rm; }
};

View File

@ -156,8 +156,9 @@ static void print_page_fault(char const *msg,
Pager_object const &obj)
{
log(msg, " (",
pf_type == Region_map::State::WRITE_FAULT ? "WRITE" : "READ",
" pf_addr=", Hex(pf_addr), " pf_ip=", Hex(pf_ip), " from ", obj, ")");
pf_type == Region_map::State::WRITE_FAULT ? "WRITE" :
pf_type == Region_map::State::READ_FAULT ? "READ" : "EXEC",
" pf_addr=", Hex(pf_addr), " pf_ip=", Hex(pf_ip), " from ", obj, ") ");
}
@ -173,6 +174,9 @@ int Rm_client::pager(Ipc_pager &pager)
{
Region_map::State::Fault_type pf_type = pager.write_fault() ? Region_map::State::WRITE_FAULT
: Region_map::State::READ_FAULT;
if (pager.exec_fault())
pf_type = Region_map::State::EXEC_FAULT;
addr_t pf_addr = pager.fault_addr();
addr_t pf_ip = pager.fault_ip();
@ -211,7 +215,6 @@ int Rm_client::pager(Ipc_pager &pager)
*/
if (pf_type == Region_map::State::WRITE_FAULT && !dsc->writable()) {
/* attempted there is no attachment return an error condition */
print_page_fault("attempted write at read-only memory",
pf_addr, pf_ip, pf_type, *this);
@ -221,6 +224,17 @@ int Rm_client::pager(Ipc_pager &pager)
return 2;
}
if (pf_type == Region_map::State::EXEC_FAULT) {
print_page_fault("attempted exec at non-executable memory",
pf_addr, pf_ip, pf_type, *this);
/* register fault at responsible region map */
if (region_map)
region_map->fault(this, pf_addr - region_offset, pf_type);
return 3;
}
Mapping mapping = Region_map_component::create_map_item(region_map,
region,
ds_offset,
@ -323,7 +337,7 @@ Mapping Region_map_component::create_map_item(Region_map_component *region_map,
return Mapping(dst_fault_area.base(), src_fault_area.base(),
dsc->cacheability(), dsc->io_mem(),
map_size_log2, dsc->writable());
map_size_log2, dsc->writable(), region->executable());
};
@ -414,7 +428,7 @@ Region_map_component::attach(Dataspace_capability ds_cap, size_t size,
/* store attachment info in meta data */
try {
_map.metadata(attach_at, Rm_region((addr_t)attach_at, size, true,
dsc, offset, this));
dsc, offset, this, executable));
} catch (Allocator_avl_tpl<Rm_region>::Assign_metadata_failed) {