Prechádzať zdrojové kódy

Kernel+SystemMonitor: Prevent userspace access to process ELF image

Every process keeps its own ELF executable mapped in memory in case we
need to do symbol lookup (for backtraces, etc.)

Until now, it was mapped in a way that made it accessible to the
program, despite the program not having mapped it itself.
I don't really see a need for userspace to have access to this right
now, so let's lock things down a little bit.

This patch makes it inaccessible to userspace and exposes that fact
through /proc/PID/vm (per-region "user_accessible" flag.)
Andreas Kling 5 rokov pred
rodič
commit
931e4b7f5e

+ 2 - 0
Applications/SystemMonitor/ProcessMemoryMapWidget.cpp

@@ -20,6 +20,8 @@ ProcessMemoryMapWidget::ProcessMemoryMapWidget(GWidget* parent)
     pid_vm_fields.empend("amount_resident", "Resident", TextAlignment::CenterRight);
     pid_vm_fields.empend("Access", TextAlignment::CenterLeft, [](auto& object) {
         StringBuilder builder;
+        if (!object.get("user_accessible").to_bool())
+            builder.append('K');
         if (object.get("readable").to_bool())
             builder.append('R');
         if (object.get("writable").to_bool())

+ 1 - 0
Kernel/FileSystem/ProcFS.cpp

@@ -265,6 +265,7 @@ Optional<KBuffer> procfs$pid_vm(InodeIdentifier identifier)
         region_object.add("writable", region.is_writable());
         region_object.add("stack", region.is_stack());
         region_object.add("shared", region.is_shared());
+        region_object.add("user_accessible", region.is_user_accessible());
         region_object.add("purgeable", region.vmobject().is_purgeable());
         if (region.vmobject().is_purgeable()) {
             region_object.add("volatile", static_cast<const PurgeableVMObject&>(region.vmobject()).is_volatile());

+ 3 - 0
Kernel/Process.cpp

@@ -570,6 +570,9 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> envir
         entry_eip = loader->entry().get();
     }
 
+    region->set_user_accessible(false);
+    region->remap();
+
     m_elf_loader = move(loader);
     m_executable = description->custody();
 

+ 0 - 3
Kernel/VM/Region.cpp

@@ -54,9 +54,6 @@ NonnullOwnPtr<Region> Region::clone()
 {
     ASSERT(current);
 
-    // NOTE: Kernel-only regions should never be cloned.
-    ASSERT(is_user_accessible());
-
     // FIXME: What should we do for privately mapped InodeVMObjects?
     if (m_shared || vmobject().is_inode()) {
         ASSERT(!m_stack);

+ 1 - 0
Kernel/VM/Region.h

@@ -57,6 +57,7 @@ public:
     void set_mmap(bool mmap) { m_mmap = mmap; }
 
     bool is_user_accessible() const { return m_user_accessible; }
+    void set_user_accessible(bool b) { m_user_accessible = b; }
 
     PageFaultResponse handle_fault(const PageFault&);