Przeglądaj źródła

Kernel+LibC: Add minherit() and MAP_INHERIT_ZERO

This patch adds the minherit() syscall originally invented by OpenBSD.
Only the MAP_INHERIT_ZERO mode is supported for now. If set on an mmap
region, that region will be zeroed out on fork().
Andreas Kling 5 lat temu
rodzic
commit
c19b56dc99

+ 26 - 0
Kernel/Process.cpp

@@ -632,6 +632,32 @@ int Process::sys$madvise(void* address, size_t size, int advice)
     return -EINVAL;
 }
 
+int Process::sys$minherit(void* address, size_t size, int inherit)
+{
+    REQUIRE_PROMISE(stdio);
+
+    auto* region = region_from_range({ VirtualAddress(address), size });
+    if (!region)
+        return -EINVAL;
+
+    if (!region->is_mmap())
+        return -EINVAL;
+
+    if (region->is_shared())
+        return -EINVAL;
+
+    if (!region->vmobject().is_anonymous())
+        return -EINVAL;
+
+    switch (inherit) {
+    case MAP_INHERIT_ZERO:
+        region->set_inherit_mode(Region::InheritMode::ZeroedOnFork);
+        return 0;
+    }
+
+    return -EINVAL;
+}
+
 int Process::sys$purge(int mode)
 {
     REQUIRE_NO_PROMISES;

+ 1 - 0
Kernel/Process.h

@@ -204,6 +204,7 @@ public:
     int sys$set_mmap_name(const Syscall::SC_set_mmap_name_params*);
     int sys$mprotect(void*, size_t, int prot);
     int sys$madvise(void*, size_t, int advice);
+    int sys$minherit(void*, size_t, int inherit);
     int sys$purge(int mode);
     int sys$select(const Syscall::SC_select_params*);
     int sys$poll(pollfd*, int nfds, int timeout);

+ 2 - 1
Kernel/Syscall.h

@@ -182,7 +182,8 @@ namespace Kernel {
     __ENUMERATE_SYSCALL(perf_event)           \
     __ENUMERATE_SYSCALL(shutdown)             \
     __ENUMERATE_SYSCALL(get_stack_bounds)     \
-    __ENUMERATE_SYSCALL(ptrace)
+    __ENUMERATE_SYSCALL(ptrace)               \
+    __ENUMERATE_SYSCALL(minherit)
 
 namespace Syscall {
 

+ 2 - 0
Kernel/UnixTypes.h

@@ -67,6 +67,8 @@
 #define MADV_SET_NONVOLATILE 0x200
 #define MADV_GET_VOLATILE 0x400
 
+#define MAP_INHERIT_ZERO 1
+
 #define F_DUPFD 0
 #define F_GETFD 1
 #define F_SETFD 2

+ 10 - 0
Kernel/VM/Region.cpp

@@ -68,6 +68,16 @@ NonnullOwnPtr<Region> Region::clone()
 {
     ASSERT(Process::current);
 
+    if (m_inherit_mode == InheritMode::ZeroedOnFork) {
+        ASSERT(m_mmap);
+        ASSERT(!m_shared);
+        ASSERT(vmobject().is_anonymous());
+        auto zeroed_region = Region::create_user_accessible(m_range, AnonymousVMObject::create_with_size(size()), 0, m_name, m_access);
+        zeroed_region->set_mmap(m_mmap);
+        zeroed_region->set_inherit_mode(m_inherit_mode);
+        return zeroed_region;
+    }
+
     if (m_shared) {
         ASSERT(!m_stack);
 #ifdef MM_DEBUG

+ 8 - 0
Kernel/VM/Region.h

@@ -55,6 +55,11 @@ public:
         Execute = 4,
     };
 
+    enum class InheritMode {
+        Default,
+        ZeroedOnFork,
+    };
+
     static NonnullOwnPtr<Region> create_user_accessible(const Range&, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, const StringView& name, u8 access, bool cacheable = true);
     static NonnullOwnPtr<Region> create_kernel_only(const Range&, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, const StringView& name, u8 access, bool cacheable = true);
 
@@ -160,6 +165,8 @@ public:
     // NOTE: These are public so we can make<> them.
     Region(const Range&, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, const String&, u8 access, bool cacheable);
 
+    void set_inherit_mode(InheritMode inherit_mode) { m_inherit_mode = inherit_mode; }
+
 private:
     Bitmap& ensure_cow_map() const;
 
@@ -183,6 +190,7 @@ private:
     NonnullRefPtr<VMObject> m_vmobject;
     String m_name;
     u8 m_access { 0 };
+    InheritMode m_inherit_mode : 3 { InheritMode::Default };
     bool m_shared : 1 { false };
     bool m_user_accessible : 1 { false };
     bool m_cacheable : 1 { false };

+ 6 - 0
Libraries/LibC/mman.cpp

@@ -81,4 +81,10 @@ int madvise(void* address, size_t size, int advice)
     int rc = syscall(SC_madvise, address, size, advice);
     __RETURN_WITH_ERRNO(rc, rc, -1);
 }
+
+int minherit(void* address, size_t size, int inherit)
+{
+    int rc = syscall(SC_minherit, address, size, inherit);
+    __RETURN_WITH_ERRNO(rc, rc, -1);
+}
 }

+ 3 - 0
Libraries/LibC/mman.h

@@ -49,6 +49,8 @@
 #define MADV_SET_NONVOLATILE 0x200
 #define MADV_GET_VOLATILE 0x400
 
+#define MAP_INHERIT_ZERO 1
+
 __BEGIN_DECLS
 
 void* mmap(void* addr, size_t, int prot, int flags, int fd, off_t);
@@ -58,5 +60,6 @@ int munmap(void*, size_t);
 int mprotect(void*, size_t, int prot);
 int set_mmap_name(void*, size_t, const char*);
 int madvise(void*, size_t, int advice);
+int minherit(void*, size_t, int inherit);
 
 __END_DECLS