diff --git a/Kernel/Devices/KCOVDevice.cpp b/Kernel/Devices/KCOVDevice.cpp index 4d38ce15053..647a3ab1610 100644 --- a/Kernel/Devices/KCOVDevice.cpp +++ b/Kernel/Devices/KCOVDevice.cpp @@ -116,7 +116,7 @@ ErrorOr KCOVDevice::ioctl(OpenFileDescription&, unsigned request, Userspac } } -ErrorOr KCOVDevice::mmap(Process& process, Memory::AddressSpace& address_space, OpenFileDescription&, Memory::VirtualRange const& range, u64 offset, int prot, bool shared) +ErrorOr> KCOVDevice::vmobject_for_mmap(Process& process, Memory::VirtualRange const&, u64&, bool) { auto pid = process.pid(); auto maybe_kcov_instance = proc_instance->get(pid); @@ -126,7 +126,7 @@ ErrorOr KCOVDevice::mmap(Process& process, Memory::AddressSpace if (!kcov_instance->vmobject()) return ENOBUFS; // mmaped, before KCOV_SETBUFSIZE - return address_space.allocate_region_with_vmobject(range, *kcov_instance->vmobject(), offset, {}, prot, shared); + return *kcov_instance->vmobject(); } } diff --git a/Kernel/Devices/KCOVDevice.h b/Kernel/Devices/KCOVDevice.h index bc5883c61f9..40d7e708721 100644 --- a/Kernel/Devices/KCOVDevice.h +++ b/Kernel/Devices/KCOVDevice.h @@ -22,7 +22,7 @@ public: static void free_process(); // ^File - ErrorOr mmap(Process&, Memory::AddressSpace&, OpenFileDescription&, Memory::VirtualRange const&, u64 offset, int prot, bool shared) override; + ErrorOr> vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64& offset, bool shared) override; ErrorOr> open(int options) override; protected: diff --git a/Kernel/Devices/MemoryDevice.cpp b/Kernel/Devices/MemoryDevice.cpp index b8234987068..73cb912be8d 100644 --- a/Kernel/Devices/MemoryDevice.cpp +++ b/Kernel/Devices/MemoryDevice.cpp @@ -42,7 +42,7 @@ ErrorOr MemoryDevice::read(OpenFileDescription&, u64 offset, UserOrKerne return length; } -ErrorOr MemoryDevice::mmap(Process&, Memory::AddressSpace& address_space, OpenFileDescription&, Memory::VirtualRange const& range, u64 offset, int prot, bool shared) +ErrorOr> MemoryDevice::vmobject_for_mmap(Process&, Memory::VirtualRange const& range, u64& offset, bool) { auto viewed_address = PhysicalAddress(offset); @@ -61,15 +61,8 @@ ErrorOr MemoryDevice::mmap(Process&, Memory::AddressSpace& addr return EINVAL; } - auto vmobject = TRY(Memory::AnonymousVMObject::try_create_for_physical_range(viewed_address, range.size())); - - return address_space.allocate_region_with_vmobject( - range, - move(vmobject), - 0, - "Mapped Physical Memory"sv, - prot, - shared); + offset = 0; + return TRY(Memory::AnonymousVMObject::try_create_for_physical_range(viewed_address, range.size())); } } diff --git a/Kernel/Devices/MemoryDevice.h b/Kernel/Devices/MemoryDevice.h index 274438c3de0..a73eca7ca54 100644 --- a/Kernel/Devices/MemoryDevice.h +++ b/Kernel/Devices/MemoryDevice.h @@ -19,7 +19,7 @@ public: static NonnullLockRefPtr must_create(); ~MemoryDevice(); - virtual ErrorOr mmap(Process&, Memory::AddressSpace&, OpenFileDescription&, Memory::VirtualRange const&, u64 offset, int prot, bool shared) override; + virtual ErrorOr> vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64& offset, bool shared) override; private: MemoryDevice(); diff --git a/Kernel/FileSystem/AnonymousFile.cpp b/Kernel/FileSystem/AnonymousFile.cpp index 850782495f4..0e7a738f16b 100644 --- a/Kernel/FileSystem/AnonymousFile.cpp +++ b/Kernel/FileSystem/AnonymousFile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2021-2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -17,12 +17,12 @@ AnonymousFile::AnonymousFile(NonnullLockRefPtr vmobje AnonymousFile::~AnonymousFile() = default; -ErrorOr AnonymousFile::mmap(Process&, Memory::AddressSpace& address_space, OpenFileDescription&, Memory::VirtualRange const& range, u64 offset, int prot, bool shared) +ErrorOr> AnonymousFile::vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64& offset, bool) { if (offset != 0) return EINVAL; - return address_space.allocate_region_with_vmobject(range, m_vmobject, offset, {}, prot, shared); + return m_vmobject; } ErrorOr> AnonymousFile::pseudo_path(OpenFileDescription const&) const diff --git a/Kernel/FileSystem/AnonymousFile.h b/Kernel/FileSystem/AnonymousFile.h index 45500671f91..792c161f2a1 100644 --- a/Kernel/FileSystem/AnonymousFile.h +++ b/Kernel/FileSystem/AnonymousFile.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2021-2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -20,7 +20,7 @@ public: virtual ~AnonymousFile() override; - virtual ErrorOr mmap(Process&, Memory::AddressSpace&, OpenFileDescription&, Memory::VirtualRange const&, u64 offset, int prot, bool shared) override; + virtual ErrorOr> vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64& offset, bool shared) override; private: virtual StringView class_name() const override { return "AnonymousFile"sv; } diff --git a/Kernel/FileSystem/File.cpp b/Kernel/FileSystem/File.cpp index fa15688e038..25b1202577f 100644 --- a/Kernel/FileSystem/File.cpp +++ b/Kernel/FileSystem/File.cpp @@ -35,7 +35,7 @@ ErrorOr File::ioctl(OpenFileDescription&, unsigned, Userspace) return ENOTTY; } -ErrorOr File::mmap(Process&, Memory::AddressSpace&, OpenFileDescription&, Memory::VirtualRange const&, u64, int, bool) +ErrorOr> File::vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64&, bool) { return ENODEV; } diff --git a/Kernel/FileSystem/File.h b/Kernel/FileSystem/File.h index 456a6757f68..9b2a4bb817c 100644 --- a/Kernel/FileSystem/File.h +++ b/Kernel/FileSystem/File.h @@ -64,11 +64,11 @@ public: // - Can be overridden in subclasses to implement arbitrary functionality. // - Subclasses should take care to validate incoming addresses before dereferencing. // -// mmap() +// vmobject_for_mmap() // // - Optional. If unimplemented, mmap() on this File will fail with -ENODEV. // - Called by mmap() when userspace wants to memory-map this File somewhere. -// - Should create a Region in the Process and return it if successful. +// - Should return a VMObject suitable for mapping into the calling process. class File : public AtomicRefCounted @@ -90,7 +90,7 @@ public: virtual ErrorOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) = 0; virtual ErrorOr write(OpenFileDescription&, u64, UserOrKernelBuffer const&, size_t) = 0; virtual ErrorOr ioctl(OpenFileDescription&, unsigned request, Userspace arg); - virtual ErrorOr mmap(Process&, Memory::AddressSpace&, OpenFileDescription&, Memory::VirtualRange const&, u64 offset, int prot, bool shared); + virtual ErrorOr> vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64& offset, bool shared); virtual ErrorOr stat() const { return EBADF; } // Although this might be better described "name" or "description", these terms already have other meanings. diff --git a/Kernel/FileSystem/InodeFile.cpp b/Kernel/FileSystem/InodeFile.cpp index 8d69cd787f2..a61f3c56754 100644 --- a/Kernel/FileSystem/InodeFile.cpp +++ b/Kernel/FileSystem/InodeFile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2018-2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -85,16 +85,11 @@ ErrorOr InodeFile::ioctl(OpenFileDescription& description, unsigned reques } } -ErrorOr InodeFile::mmap(Process&, Memory::AddressSpace& address_space, OpenFileDescription& description, Memory::VirtualRange const& range, u64 offset, int prot, bool shared) +ErrorOr> InodeFile::vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64&, bool shared) { - // FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec. - LockRefPtr vmobject; if (shared) - vmobject = TRY(Memory::SharedInodeVMObject::try_create_with_inode(inode())); - else - vmobject = TRY(Memory::PrivateInodeVMObject::try_create_with_inode(inode())); - auto path = TRY(description.pseudo_path()); - return address_space.allocate_region_with_vmobject(range, vmobject.release_nonnull(), offset, path->view(), prot, shared); + return TRY(Memory::SharedInodeVMObject::try_create_with_inode(inode())); + return TRY(Memory::PrivateInodeVMObject::try_create_with_inode(inode())); } ErrorOr> InodeFile::pseudo_path(OpenFileDescription const&) const diff --git a/Kernel/FileSystem/InodeFile.h b/Kernel/FileSystem/InodeFile.h index c05177362ec..5da7cbdce5c 100644 --- a/Kernel/FileSystem/InodeFile.h +++ b/Kernel/FileSystem/InodeFile.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2018-2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -33,7 +33,7 @@ public: virtual ErrorOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; virtual ErrorOr write(OpenFileDescription&, u64, UserOrKernelBuffer const&, size_t) override; virtual ErrorOr ioctl(OpenFileDescription&, unsigned request, Userspace arg) override; - virtual ErrorOr mmap(Process&, Memory::AddressSpace&, OpenFileDescription&, Memory::VirtualRange const&, u64 offset, int prot, bool shared) override; + virtual ErrorOr> vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64& offset, bool shared) override; virtual ErrorOr stat() const override { return inode().metadata().stat(); } virtual ErrorOr> pseudo_path(OpenFileDescription const&) const override; diff --git a/Kernel/FileSystem/OpenFileDescription.cpp b/Kernel/FileSystem/OpenFileDescription.cpp index 153a1baeb33..a6634a644b6 100644 --- a/Kernel/FileSystem/OpenFileDescription.cpp +++ b/Kernel/FileSystem/OpenFileDescription.cpp @@ -374,9 +374,9 @@ InodeMetadata OpenFileDescription::metadata() const return {}; } -ErrorOr OpenFileDescription::mmap(Process& process, Memory::AddressSpace& address_space, Memory::VirtualRange const& range, u64 offset, int prot, bool shared) +ErrorOr> OpenFileDescription::vmobject_for_mmap(Process& process, Memory::VirtualRange const& range, u64& offset, bool shared) { - return m_file->mmap(process, address_space, *this, range, offset, prot, shared); + return m_file->vmobject_for_mmap(process, range, offset, shared); } ErrorOr OpenFileDescription::truncate(u64 length) diff --git a/Kernel/FileSystem/OpenFileDescription.h b/Kernel/FileSystem/OpenFileDescription.h index c280ecf71fe..236257038fe 100644 --- a/Kernel/FileSystem/OpenFileDescription.h +++ b/Kernel/FileSystem/OpenFileDescription.h @@ -92,7 +92,7 @@ public: RefPtr custody(); RefPtr custody() const; - ErrorOr mmap(Process&, Memory::AddressSpace&, Memory::VirtualRange const&, u64 offset, int prot, bool shared); + ErrorOr> vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64& offset, bool shared); bool is_blocking() const; void set_blocking(bool b); diff --git a/Kernel/Graphics/DisplayConnector.cpp b/Kernel/Graphics/DisplayConnector.cpp index de02a4ed6f6..e1bcc9de4d7 100644 --- a/Kernel/Graphics/DisplayConnector.cpp +++ b/Kernel/Graphics/DisplayConnector.cpp @@ -32,19 +32,13 @@ DisplayConnector::DisplayConnector(size_t framebuffer_resource_size, bool enable { } -ErrorOr DisplayConnector::mmap(Process&, Memory::AddressSpace& address_space, OpenFileDescription&, Memory::VirtualRange const& range, u64 offset, int prot, bool shared) +ErrorOr> DisplayConnector::vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64& offset, bool) { VERIFY(m_shared_framebuffer_vmobject); if (offset != 0) return Error::from_errno(ENOTSUP); - return address_space.allocate_region_with_vmobject( - range, - *m_shared_framebuffer_vmobject, - 0, - "Mapped Framebuffer"sv, - prot, - shared); + return *m_shared_framebuffer_vmobject; } ErrorOr DisplayConnector::read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) diff --git a/Kernel/Graphics/DisplayConnector.h b/Kernel/Graphics/DisplayConnector.h index 5dc0dc0cd84..ed218936c3f 100644 --- a/Kernel/Graphics/DisplayConnector.h +++ b/Kernel/Graphics/DisplayConnector.h @@ -137,7 +137,7 @@ private: virtual bool can_write(OpenFileDescription const&, u64) const final override { return true; } virtual ErrorOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override final; virtual ErrorOr write(OpenFileDescription&, u64, UserOrKernelBuffer const&, size_t) override final; - virtual ErrorOr mmap(Process&, Memory::AddressSpace&, OpenFileDescription&, Memory::VirtualRange const&, u64, int, bool) override final; + virtual ErrorOr> vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64&, bool) override final; virtual ErrorOr ioctl(OpenFileDescription&, unsigned request, Userspace arg) override final; virtual StringView class_name() const override final { return "DisplayConnector"sv; } diff --git a/Kernel/Syscalls/mmap.cpp b/Kernel/Syscalls/mmap.cpp index 0d5ebba9bdd..1e5be912ab0 100644 --- a/Kernel/Syscalls/mmap.cpp +++ b/Kernel/Syscalls/mmap.cpp @@ -190,10 +190,17 @@ ErrorOr Process::sys$mmap(Userspace use if (map_stack && (!map_private || !map_anonymous)) return EINVAL; + Memory::VirtualRange requested_range { VirtualAddress { addr }, rounded_size }; + if (addr && !(map_fixed || map_fixed_noreplace)) { + // If there's an address but MAP_FIXED wasn't specified, the address is just a hint. + requested_range = { {}, rounded_size }; + } + Memory::Region* region = nullptr; LockRefPtr description; - LockRefPtr vmobject; + LockRefPtr vmobject; + u64 used_offset = 0; if (map_anonymous) { auto strategy = map_noreserve ? AllocationStrategy::None : AllocationStrategy::Reserve; @@ -206,6 +213,7 @@ ErrorOr Process::sys$mmap(Userspace use } else { if (offset < 0) return EINVAL; + used_offset = static_cast(offset); if (static_cast(offset) & ~PAGE_MASK) return EINVAL; description = TRY(open_file_description(fd)); @@ -220,6 +228,8 @@ ErrorOr Process::sys$mmap(Userspace use } if (description->inode()) TRY(validate_inode_mmap_prot(prot, *description->inode(), map_shared)); + + vmobject = TRY(description->vmobject_for_mmap(*this, requested_range, used_offset, map_shared)); } return address_space().with([&](auto& space) -> ErrorOr { @@ -227,17 +237,16 @@ ErrorOr Process::sys$mmap(Userspace use if (map_fixed) TRY(space->unmap_mmap_range(VirtualAddress(addr), size)); - Memory::VirtualRange requested_range { VirtualAddress { addr }, rounded_size }; - if (addr && !(map_fixed || map_fixed_noreplace)) { - // If there's an address but MAP_FIXED wasn't specified, the address is just a hint. - requested_range = { {}, rounded_size }; - } - - if (map_anonymous) { - region = TRY(space->allocate_region_with_vmobject(map_randomized ? Memory::RandomizeVirtualAddress::Yes : Memory::RandomizeVirtualAddress::No, requested_range.base(), requested_range.size(), alignment, vmobject.release_nonnull(), 0, {}, prot, map_shared)); - } else { - region = TRY(description->mmap(*this, *space, requested_range, static_cast(offset), prot, map_shared)); - } + region = TRY(space->allocate_region_with_vmobject( + map_randomized ? Memory::RandomizeVirtualAddress::Yes : Memory::RandomizeVirtualAddress::No, + requested_range.base(), + requested_range.size(), + alignment, + vmobject.release_nonnull(), + used_offset, + {}, + prot, + map_shared)); if (!region) return ENOMEM;