From db329b02b51b608217079a216fd86faf936bd152 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Fri, 13 Oct 2017 15:26:33 +0200 Subject: [PATCH] base: enable executable memory fault handling Fixes #1723 --- .../base-fiasco/src/core/include/ipc_pager.h | 7 +++--- repos/base-foc/src/core/include/ipc_pager.h | 13 +++++----- repos/base-hw/src/core/pager.h | 8 ++++++- repos/base-nova/src/core/include/ipc_pager.h | 9 +++++-- repos/base-okl4/src/core/include/ipc_pager.h | 7 +++++- repos/base-okl4/src/core/pager.cc | 2 +- .../src/core/include/ipc_pager.h | 9 +++++-- repos/base-pistachio/src/core/pager.cc | 4 +++- repos/base-sel4/src/core/include/ipc_pager.h | 8 +++++-- .../src/core/include/region_map_component.h | 18 +++++++------- repos/base/src/core/region_map_component.cc | 24 +++++++++++++++---- 11 files changed, 77 insertions(+), 32 deletions(-) diff --git a/repos/base-fiasco/src/core/include/ipc_pager.h b/repos/base-fiasco/src/core/include/ipc_pager.h index 7b0c0d0c0..0dd2bd50b 100644 --- a/repos/base-fiasco/src/core/include/ipc_pager.h +++ b/repos/base-fiasco/src/core/include/ipc_pager.h @@ -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 */ diff --git a/repos/base-foc/src/core/include/ipc_pager.h b/repos/base-foc/src/core/include/ipc_pager.h index 77995a033..c197d564e 100644 --- a/repos/base-foc/src/core/include/ipc_pager.h +++ b/repos/base-foc/src/core/include/ipc_pager.h @@ -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 */ diff --git a/repos/base-hw/src/core/pager.h b/repos/base-hw/src/core/pager.h index 77992a06f..45ece49f5 100644 --- a/repos/base-hw/src/core/pager.h +++ b/repos/base-hw/src/core/pager.h @@ -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 */ diff --git a/repos/base-nova/src/core/include/ipc_pager.h b/repos/base-nova/src/core/include/ipc_pager.h index 0e68567ed..df2329e68 100644 --- a/repos/base-nova/src/core/include/ipc_pager.h +++ b/repos/base-nova/src/core/include/ipc_pager.h @@ -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 */ diff --git a/repos/base-okl4/src/core/include/ipc_pager.h b/repos/base-okl4/src/core/include/ipc_pager.h index 3c89496ea..f51e0b15c 100644 --- a/repos/base-okl4/src/core/include/ipc_pager.h +++ b/repos/base-okl4/src/core/include/ipc_pager.h @@ -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 */ diff --git a/repos/base-okl4/src/core/pager.cc b/repos/base-okl4/src/core/pager.cc index 787853acf..aef397b41 100644 --- a/repos/base-okl4/src/core/pager.cc +++ b/repos/base-okl4/src/core/pager.cc @@ -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)), /* diff --git a/repos/base-pistachio/src/core/include/ipc_pager.h b/repos/base-pistachio/src/core/include/ipc_pager.h index 100f7518c..56553dc68 100644 --- a/repos/base-pistachio/src/core/include/ipc_pager.h +++ b/repos/base-pistachio/src/core/include/ipc_pager.h @@ -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 */ diff --git a/repos/base-pistachio/src/core/pager.cc b/repos/base-pistachio/src/core/pager.cc index db79e0667..e9a8347cc 100644 --- a/repos/base-pistachio/src/core/pager.cc +++ b/repos/base-pistachio/src/core/pager.cc @@ -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; diff --git a/repos/base-sel4/src/core/include/ipc_pager.h b/repos/base-sel4/src/core/include/ipc_pager.h index 995f8a3b7..b3939b007 100644 --- a/repos/base-sel4/src/core/include/ipc_pager.h +++ b/repos/base-sel4/src/core/include/ipc_pager.h @@ -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; } }; } diff --git a/repos/base/src/core/include/region_map_component.h b/repos/base/src/core/include/region_map_component.h index 9eae9e621..898cf1897 100644 --- a/repos/base/src/core/include/region_map_component.h +++ b/repos/base/src/core/include/region_map_component.h @@ -65,6 +65,7 @@ class Genode::Rm_region : public List::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::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::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; } }; diff --git a/repos/base/src/core/region_map_component.cc b/repos/base/src/core/region_map_component.cc index 731f02976..5ca58390c 100644 --- a/repos/base/src/core/region_map_component.cc +++ b/repos/base/src/core/region_map_component.cc @@ -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::Assign_metadata_failed) {