From 60a819c14ac5a843c521f1c7b947dd578223b5ca Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 9 Apr 2019 02:37:05 +0200 Subject: [PATCH] Kernel: Yet more work on bringing up POSIX SHM. --- AK/Retained.h | 2 +- Kernel/FileSystem/FileDescriptor.cpp | 18 ++++++++++++ Kernel/FileSystem/FileDescriptor.h | 4 ++- Kernel/KResult.h | 8 ++++++ Kernel/Process.cpp | 13 +++++++-- Kernel/SharedMemory.cpp | 43 +++++++++++++++++++++++++++- Kernel/SharedMemory.h | 18 +++++++++--- 7 files changed, 97 insertions(+), 9 deletions(-) diff --git a/AK/Retained.h b/AK/Retained.h index 93f245e0bc..ebf61bc468 100644 --- a/AK/Retained.h +++ b/AK/Retained.h @@ -35,7 +35,7 @@ class CONSUMABLE(unconsumed) Retained { public: enum AdoptTag { Adopt }; - RETURN_TYPESTATE(unconsumed) Retained(const T& object) : m_ptr(&object) { m_ptr->retain(); } + RETURN_TYPESTATE(unconsumed) Retained(const T& object) : m_ptr(const_cast(&object)) { m_ptr->retain(); } RETURN_TYPESTATE(unconsumed) Retained(T& object) : m_ptr(&object) { m_ptr->retain(); } template RETURN_TYPESTATE(unconsumed) Retained(U& object) : m_ptr(&static_cast(object)) { m_ptr->retain(); } RETURN_TYPESTATE(unconsumed) Retained(AdoptTag, T& object) : m_ptr(&object) { } diff --git a/Kernel/FileSystem/FileDescriptor.cpp b/Kernel/FileSystem/FileDescriptor.cpp index 4327155acd..fd839a55a3 100644 --- a/Kernel/FileSystem/FileDescriptor.cpp +++ b/Kernel/FileSystem/FileDescriptor.cpp @@ -23,6 +23,11 @@ Retained FileDescriptor::create(RetainPtr&& device) return adopt(*new FileDescriptor(move(device))); } +Retained FileDescriptor::create(RetainPtr&& shared_memory) +{ + return adopt(*new FileDescriptor(move(shared_memory))); +} + Retained FileDescriptor::create(RetainPtr&& socket, SocketRole role) { return adopt(*new FileDescriptor(move(socket), role)); @@ -48,6 +53,11 @@ FileDescriptor::FileDescriptor(RetainPtr&& device) { } +FileDescriptor::FileDescriptor(RetainPtr&& shared_memory) + : m_shared_memory(move(shared_memory)) +{ +} + FileDescriptor::FileDescriptor(RetainPtr&& socket, SocketRole role) : m_socket(move(socket)) { @@ -397,6 +407,8 @@ bool FileDescriptor::supports_mmap() const { if (m_inode) return true; + if (m_shared_memory) + return true; if (m_device) return m_device->is_block_device(); return false; @@ -409,6 +421,12 @@ Region* FileDescriptor::mmap(Process& process, LinearAddress laddr, size_t offse if (is_block_device()) return static_cast(*m_device).mmap(process, laddr, offset, size); + if (is_shared_memory()) { + if (!shared_memory()->vmo()) + return nullptr; + return process.allocate_region_with_vmo(laddr, size, *shared_memory()->vmo(), offset, shared_memory()->name(), true, true); + } + ASSERT(m_inode); // FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec. String region_name; diff --git a/Kernel/FileSystem/FileDescriptor.h b/Kernel/FileSystem/FileDescriptor.h index 65361712bc..4b0892651e 100644 --- a/Kernel/FileSystem/FileDescriptor.h +++ b/Kernel/FileSystem/FileDescriptor.h @@ -9,13 +9,13 @@ #include #include #include +#include class TTY; class MasterPTY; class Process; class Region; class CharacterDevice; -class SharedMemory; class FileDescriptor : public Retainable { public: @@ -23,6 +23,7 @@ public: static Retained create(RetainPtr&&, SocketRole = SocketRole::None); static Retained create(RetainPtr&&); static Retained create(RetainPtr&&); + static Retained create(RetainPtr&&); static Retained create_pipe_writer(FIFO&); static Retained create_pipe_reader(FIFO&); ~FileDescriptor(); @@ -105,6 +106,7 @@ private: FileDescriptor(RetainPtr&&, SocketRole); explicit FileDescriptor(RetainPtr&&); explicit FileDescriptor(RetainPtr&&); + explicit FileDescriptor(RetainPtr&&); FileDescriptor(FIFO&, FIFO::Direction); RetainPtr m_inode; diff --git a/Kernel/KResult.h b/Kernel/KResult.h index 309d9340f4..1cc740bc74 100644 --- a/Kernel/KResult.h +++ b/Kernel/KResult.h @@ -58,6 +58,14 @@ public: T& value() { ASSERT(!m_is_error); return *reinterpret_cast(&m_storage); } const T& value() const { ASSERT(!m_is_error); return *reinterpret_cast(&m_storage); } + T release_value() + { + ASSERT(!m_is_error); + T released_value = *reinterpret_cast(&m_storage); + value().~T(); + return released_value; + } + private: char m_storage[sizeof(T)] __attribute__((aligned(sizeof(T)))); KResult m_error; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index fbd1f9ce6b..324d15a7b4 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -22,6 +22,7 @@ #include #include #include +#include //#define DEBUG_IO //#define TASK_DEBUG @@ -2459,14 +2460,22 @@ int Process::sys$shm_open(const char* name, int flags, mode_t mode) { if (!validate_read_str(name)) return -EFAULT; - return -ENOTIMPL; + int fd = alloc_fd(); + if (fd < 0) + return fd; + auto shm_or_error = SharedMemory::open(String(name), flags, mode); + if (shm_or_error.is_error()) + return shm_or_error.error(); + auto descriptor = FileDescriptor::create(shm_or_error.value().ptr()); + m_fds[fd].set(move(descriptor), FD_CLOEXEC); + return fd; } int Process::sys$shm_unlink(const char* name) { if (!validate_read_str(name)) return -EFAULT; - return -ENOTIMPL; + return SharedMemory::unlink(String(name)); } int Process::sys$ftruncate(int fd, off_t length) diff --git a/Kernel/SharedMemory.cpp b/Kernel/SharedMemory.cpp index 1af385de17..40437026f5 100644 --- a/Kernel/SharedMemory.cpp +++ b/Kernel/SharedMemory.cpp @@ -1,7 +1,48 @@ #include #include +#include +#include +#include -SharedMemory::SharedMemory() +Lockable>>& shared_memories() +{ + static Lockable>>* map; + if (!map) + map = new Lockable>>; + return *map; +} + +KResultOr> SharedMemory::open(const String& name, int flags, mode_t mode) +{ + LOCKER(shared_memories().lock()); + auto it = shared_memories().resource().find(name); + if (it != shared_memories().resource().end()) { + auto shared_memory = it->value; + // FIXME: Improved access checking. + if (shared_memory->uid() != current->process().uid()) + return KResult(-EACCES); + return *shared_memory; + } + auto shared_memory = adopt(*new SharedMemory(name, current->process().uid(), current->process().gid(), mode)); + shared_memories().resource().set(name, shared_memory.ptr()); + return shared_memory; +} + +KResult SharedMemory::unlink(const String& name) +{ + LOCKER(shared_memories().lock()); + auto it = shared_memories().resource().find(name); + if (it == shared_memories().resource().end()) + return KResult(-ENOENT); + shared_memories().resource().remove(it); + return KSuccess; +} + +SharedMemory::SharedMemory(const String& name, uid_t uid, gid_t gid, mode_t mode) + : m_name(name) + , m_uid(uid) + , m_gid(gid) + , m_mode(mode) { } diff --git a/Kernel/SharedMemory.h b/Kernel/SharedMemory.h index 7b693bbd4b..b45eff726b 100644 --- a/Kernel/SharedMemory.h +++ b/Kernel/SharedMemory.h @@ -2,21 +2,31 @@ #include #include +#include #include +#include class VMObject; class SharedMemory : public Retainable { public: - static Retained create(); + static KResultOr> open(const String& name, int flags, mode_t); + static KResult unlink(const String& name); ~SharedMemory(); + String name() const { return m_name; } KResult truncate(int); + VMObject* vmo() { return m_vmo.ptr(); } + const VMObject* vmo() const { return m_vmo.ptr(); } + uid_t uid() const { return m_uid; } + gid_t gid() const { return m_gid; } private: - SharedMemory(); + SharedMemory(const String& name, uid_t, gid_t, mode_t); - int m_uid { 0 }; - int m_gid { 0 }; + String m_name; + uid_t m_uid { 0 }; + gid_t m_gid { 0 }; + mode_t m_mode { 0 }; RetainPtr m_vmo; };