summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-12 20:22:26 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-12 20:22:26 +0200
commitc19b56dc990eeb808c01b4cefd735322f0f0329f (patch)
treeb72b443f311d782b3bde3a243e1aa43a7020fce3 /Kernel
parentdd00175ae2d6f23b08cb803eb86fc0108c393971 (diff)
downloadserenity-c19b56dc990eeb808c01b4cefd735322f0f0329f.zip
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().
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Process.cpp26
-rw-r--r--Kernel/Process.h1
-rw-r--r--Kernel/Syscall.h3
-rw-r--r--Kernel/UnixTypes.h2
-rw-r--r--Kernel/VM/Region.cpp10
-rw-r--r--Kernel/VM/Region.h8
6 files changed, 49 insertions, 1 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index 9b8850793a..b786f92258 100644
--- a/Kernel/Process.cpp
+++ b/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;
diff --git a/Kernel/Process.h b/Kernel/Process.h
index 259b164144..708385ac25 100644
--- a/Kernel/Process.h
+++ b/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);
diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h
index d3167bff87..3c2c876e8a 100644
--- a/Kernel/Syscall.h
+++ b/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 {
diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h
index d7eab8cf5f..c890befbf7 100644
--- a/Kernel/UnixTypes.h
+++ b/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
diff --git a/Kernel/VM/Region.cpp b/Kernel/VM/Region.cpp
index 37629baa03..79104439a8 100644
--- a/Kernel/VM/Region.cpp
+++ b/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
diff --git a/Kernel/VM/Region.h b/Kernel/VM/Region.h
index 075079c7bd..5671dec795 100644
--- a/Kernel/VM/Region.h
+++ b/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 };