mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 06:04:57 +00:00
Kernel: Handle mmap requests on zero-length data file inodes safely
This commit is contained in:
parent
c88cc8557f
commit
3ad0e1a1d5
5 changed files with 28 additions and 5 deletions
|
@ -80,11 +80,11 @@ ErrorOr<void> InodeFile::ioctl(OpenFileDescription& description, unsigned reques
|
|||
}
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Memory::VMObject>> InodeFile::vmobject_for_mmap(Process&, Memory::VirtualRange const&, u64&, bool shared)
|
||||
ErrorOr<NonnullLockRefPtr<Memory::VMObject>> InodeFile::vmobject_for_mmap(Process&, Memory::VirtualRange const& range, u64& offset, bool shared)
|
||||
{
|
||||
if (shared)
|
||||
return TRY(Memory::SharedInodeVMObject::try_create_with_inode(inode()));
|
||||
return TRY(Memory::PrivateInodeVMObject::try_create_with_inode(inode()));
|
||||
return TRY(Memory::SharedInodeVMObject::try_create_with_inode_and_range(inode(), offset, range.size()));
|
||||
return TRY(Memory::PrivateInodeVMObject::try_create_with_inode_and_range(inode(), offset, range.size()));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullOwnPtr<KString>> InodeFile::pseudo_path(OpenFileDescription const&) const
|
||||
|
|
|
@ -11,7 +11,18 @@ namespace Kernel::Memory {
|
|||
|
||||
ErrorOr<NonnullLockRefPtr<PrivateInodeVMObject>> PrivateInodeVMObject::try_create_with_inode(Inode& inode)
|
||||
{
|
||||
auto new_physical_pages = TRY(VMObject::try_create_physical_pages(inode.size()));
|
||||
if (inode.size() == 0)
|
||||
return EINVAL;
|
||||
return try_create_with_inode_and_range(inode, 0, inode.size());
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<PrivateInodeVMObject>> PrivateInodeVMObject::try_create_with_inode_and_range(Inode& inode, u64 offset, size_t range_size)
|
||||
{
|
||||
// Note: To ensure further allocation of a Region with this VMObject will not complain
|
||||
// on "smaller" VMObject than the requested Region, we simply take the max size between both values.
|
||||
auto size = max(inode.size(), (offset + range_size));
|
||||
VERIFY(size > 0);
|
||||
auto new_physical_pages = TRY(VMObject::try_create_physical_pages(size));
|
||||
auto dirty_pages = TRY(Bitmap::try_create(new_physical_pages.size(), false));
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) PrivateInodeVMObject(inode, move(new_physical_pages), move(dirty_pages)));
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ public:
|
|||
virtual ~PrivateInodeVMObject() override;
|
||||
|
||||
static ErrorOr<NonnullLockRefPtr<PrivateInodeVMObject>> try_create_with_inode(Inode&);
|
||||
static ErrorOr<NonnullLockRefPtr<PrivateInodeVMObject>> try_create_with_inode_and_range(Inode&, u64 offset, size_t range_size);
|
||||
virtual ErrorOr<NonnullLockRefPtr<VMObject>> try_clone() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -12,7 +12,17 @@ namespace Kernel::Memory {
|
|||
|
||||
ErrorOr<NonnullLockRefPtr<SharedInodeVMObject>> SharedInodeVMObject::try_create_with_inode(Inode& inode)
|
||||
{
|
||||
size_t size = inode.size();
|
||||
if (inode.size() == 0)
|
||||
return EINVAL;
|
||||
return try_create_with_inode_and_range(inode, 0, inode.size());
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<SharedInodeVMObject>> SharedInodeVMObject::try_create_with_inode_and_range(Inode& inode, u64 offset, size_t range_size)
|
||||
{
|
||||
// Note: To ensure further allocation of a Region with this VMObject will not complain
|
||||
// on "smaller" VMObject than the requested Region, we simply take the max size between both values.
|
||||
auto size = max(inode.size(), (offset + range_size));
|
||||
VERIFY(size > 0);
|
||||
if (auto shared_vmobject = inode.shared_vmobject())
|
||||
return shared_vmobject.release_nonnull();
|
||||
auto new_physical_pages = TRY(VMObject::try_create_physical_pages(size));
|
||||
|
|
|
@ -16,6 +16,7 @@ class SharedInodeVMObject final : public InodeVMObject {
|
|||
|
||||
public:
|
||||
static ErrorOr<NonnullLockRefPtr<SharedInodeVMObject>> try_create_with_inode(Inode&);
|
||||
static ErrorOr<NonnullLockRefPtr<SharedInodeVMObject>> try_create_with_inode_and_range(Inode&, u64 offset, size_t range_size);
|
||||
virtual ErrorOr<NonnullLockRefPtr<VMObject>> try_clone() override;
|
||||
|
||||
ErrorOr<void> sync(off_t offset_in_pages = 0, size_t pages = -1);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue