From da13c9a2648de7c7d799952389e228e739dc486d Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 3 Nov 2018 11:36:45 +0100 Subject: [PATCH] Map pages in read-only ELF sections as non-writable. This is so cool! :^) Now you'll crash if you try to write into your .text or .rodata segments. --- Kernel/MemoryManager.cpp | 6 +++--- Kernel/MemoryManager.h | 4 +++- Kernel/Process.cpp | 6 ++++-- Userland/sh.cpp | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index f86cbd315b..7dd4cd6cb5 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -304,8 +304,8 @@ void MemoryManager::map_region_at_address(PageDirectory* page_directory, Region& auto page_laddr = laddr.offset(i * PAGE_SIZE); auto pte = ensurePTE(page_directory, page_laddr); pte.setPhysicalPageBase(zone.m_pages[i].get()); - pte.setPresent(true); - pte.setWritable(true); + pte.setPresent(true); // FIXME: Maybe we could use the is_readable flag here? + pte.setWritable(region.is_writable); pte.setUserAllowed(user_allowed); flushTLB(page_laddr); #ifdef MM_DEBUG @@ -430,7 +430,7 @@ RetainPtr Region::clone() // FIXME: Implement COW regions. auto clone_zone = MM.createZone(zone->size()); - auto clone_region = adopt(*new Region(linearAddress, size, move(clone_zone), String(name))); + auto clone_region = adopt(*new Region(linearAddress, size, move(clone_zone), String(name), is_readable, is_writable)); // FIXME: It would be cool to make the src_alias a read-only mapping. byte* src_alias = MM.create_kernel_alias_for_region(*this); diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index 3c3df0d58d..0ebe056666 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -38,7 +38,7 @@ private: }; struct Region : public Retainable { - Region(LinearAddress, size_t, RetainPtr&&, String&&); + Region(LinearAddress, size_t, RetainPtr&&, String&&, bool r, bool w); ~Region(); RetainPtr clone(); @@ -46,6 +46,8 @@ struct Region : public Retainable { size_t size { 0 }; RetainPtr zone; String name; + bool is_readable { true }; + bool is_writable { true }; }; #define MM MemoryManager::the() diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 1f622fc2c1..8f9ac2bcbc 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -147,7 +147,7 @@ Region* Process::allocate_region(LinearAddress laddr, size_t size, String&& name auto zone = MM.createZone(size); ASSERT(zone); - m_regions.append(adopt(*new Region(laddr, size, move(zone), move(name)))); + m_regions.append(adopt(*new Region(laddr, size, move(zone), move(name), is_readable, is_writable))); MM.mapRegion(*this, *m_regions.last()); return m_regions.last().ptr(); @@ -1260,11 +1260,13 @@ Process* Process::kernelProcess() return s_kernelProcess; } -Region::Region(LinearAddress a, size_t s, RetainPtr&& z, String&& n) +Region::Region(LinearAddress a, size_t s, RetainPtr&& z, String&& n, bool r, bool w) : linearAddress(a) , size(s) , zone(move(z)) , name(move(n)) + , is_readable(r) + , is_writable(w) { } diff --git a/Userland/sh.cpp b/Userland/sh.cpp index 8df8ae9c58..1ec61c2ed4 100644 --- a/Userland/sh.cpp +++ b/Userland/sh.cpp @@ -65,6 +65,18 @@ static int sh_fef(int, const char**) return 0; } +static int sh_wt(int, const char**) +{ + const char* rodata_ptr = "foo"; + printf("Writing to rodata=%p...\n", rodata_ptr); + *(char*)rodata_ptr = 0; + + char* text_ptr = (char*)sh_fef; + printf("Writing to text=%p...\n", text_ptr); + *text_ptr = 0; + return 0; +} + static int sh_exit(int, const char**) { printf("Good-bye!\n"); @@ -135,6 +147,10 @@ static bool handle_builtin(int argc, const char** argv, int& retval) retval = sh_fef(argc, argv); return true; } + if (!strcmp(argv[0], "wt")) { + retval = sh_wt(argc, argv); + return true; + } if (!strcmp(argv[0], "fork")) { retval = sh_fork(argc, argv); return true;