From b63a1dda633a4d7e657c12e35d884362a3264c30 Mon Sep 17 00:00:00 2001 From: Liav A Date: Sat, 10 Feb 2024 12:49:31 +0200 Subject: [PATCH] Kernel/FileSystem: Enforce locking of m_inode_lock when truncating Inode Such operation is almost equivalent to writing on an Inode, so lock the Inode m_inode_lock exclusively. All FileSystem Inode implementations then override a new method called truncate_locked which should implement the actual truncating. --- Kernel/FileSystem/Ext2FS/Inode.cpp | 4 ++-- Kernel/FileSystem/Ext2FS/Inode.h | 2 +- Kernel/FileSystem/ISO9660FS/Inode.cpp | 2 +- Kernel/FileSystem/ISO9660FS/Inode.h | 2 +- Kernel/FileSystem/Inode.cpp | 6 ++++++ Kernel/FileSystem/Inode.h | 3 ++- Kernel/FileSystem/Plan9FS/Inode.cpp | 3 ++- Kernel/FileSystem/Plan9FS/Inode.h | 2 +- Kernel/FileSystem/ProcFS/Inode.h | 2 +- Kernel/FileSystem/RAMFS/Inode.cpp | 4 ++-- Kernel/FileSystem/RAMFS/Inode.h | 2 +- Kernel/FileSystem/SysFS/Inode.cpp | 3 ++- Kernel/FileSystem/SysFS/Inode.h | 2 +- 13 files changed, 23 insertions(+), 14 deletions(-) diff --git a/Kernel/FileSystem/Ext2FS/Inode.cpp b/Kernel/FileSystem/Ext2FS/Inode.cpp index a555ee1653..43faef822f 100644 --- a/Kernel/FileSystem/Ext2FS/Inode.cpp +++ b/Kernel/FileSystem/Ext2FS/Inode.cpp @@ -1071,9 +1071,9 @@ ErrorOr Ext2FSInode::chown(UserID uid, GroupID gid) return {}; } -ErrorOr Ext2FSInode::truncate(u64 size) +ErrorOr Ext2FSInode::truncate_locked(u64 size) { - MutexLocker locker(m_inode_lock); + VERIFY(m_inode_lock.is_locked()); if (static_cast(m_raw_inode.i_size) == size) return {}; TRY(resize(size)); diff --git a/Kernel/FileSystem/Ext2FS/Inode.h b/Kernel/FileSystem/Ext2FS/Inode.h index 048c4c55d0..620bc9b183 100644 --- a/Kernel/FileSystem/Ext2FS/Inode.h +++ b/Kernel/FileSystem/Ext2FS/Inode.h @@ -42,7 +42,7 @@ private: virtual ErrorOr decrement_link_count() override; virtual ErrorOr chmod(mode_t) override; virtual ErrorOr chown(UserID, GroupID) override; - virtual ErrorOr truncate(u64) override; + virtual ErrorOr truncate_locked(u64) override; virtual ErrorOr get_block_address(int) override; ErrorOr write_directory(Vector&); diff --git a/Kernel/FileSystem/ISO9660FS/Inode.cpp b/Kernel/FileSystem/ISO9660FS/Inode.cpp index bd225878cb..ff7c2a8cd2 100644 --- a/Kernel/FileSystem/ISO9660FS/Inode.cpp +++ b/Kernel/FileSystem/ISO9660FS/Inode.cpp @@ -140,7 +140,7 @@ ErrorOr ISO9660Inode::chown(UserID, GroupID) return EROFS; } -ErrorOr ISO9660Inode::truncate(u64) +ErrorOr ISO9660Inode::truncate_locked(u64) { return EROFS; } diff --git a/Kernel/FileSystem/ISO9660FS/Inode.h b/Kernel/FileSystem/ISO9660FS/Inode.h index dd11d742b1..83ddacebb8 100644 --- a/Kernel/FileSystem/ISO9660FS/Inode.h +++ b/Kernel/FileSystem/ISO9660FS/Inode.h @@ -31,7 +31,7 @@ public: virtual ErrorOr replace_child(StringView name, Inode& child) override; virtual ErrorOr chmod(mode_t) override; virtual ErrorOr chown(UserID, GroupID) override; - virtual ErrorOr truncate(u64) override; + virtual ErrorOr truncate_locked(u64) override; virtual ErrorOr update_timestamps(Optional atime, Optional ctime, Optional mtime) override; private: diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp index 89760dd24c..9e9763fa2d 100644 --- a/Kernel/FileSystem/Inode.cpp +++ b/Kernel/FileSystem/Inode.cpp @@ -88,6 +88,12 @@ void Inode::will_be_destroyed() (void)flush_metadata(); } +ErrorOr Inode::truncate(u64 size) +{ + MutexLocker locker(m_inode_lock); + return truncate_locked(size); +} + ErrorOr Inode::write_bytes(off_t offset, size_t length, UserOrKernelBuffer const& target_buffer, OpenFileDescription* open_description) { MutexLocker locker(m_inode_lock); diff --git a/Kernel/FileSystem/Inode.h b/Kernel/FileSystem/Inode.h index be477cd1ca..75d795f8f8 100644 --- a/Kernel/FileSystem/Inode.h +++ b/Kernel/FileSystem/Inode.h @@ -56,6 +56,7 @@ public: ErrorOr write_bytes(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*); ErrorOr read_bytes(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const; ErrorOr read_until_filled_or_end(off_t, size_t, UserOrKernelBuffer buffer, OpenFileDescription*) const; + ErrorOr truncate(u64); virtual ErrorOr attach(OpenFileDescription&) { return {}; } virtual void detach(OpenFileDescription&) { } @@ -70,7 +71,6 @@ public: virtual ErrorOr replace_child(StringView name, Inode&) = 0; virtual ErrorOr chmod(mode_t) = 0; virtual ErrorOr chown(UserID, GroupID) = 0; - virtual ErrorOr truncate(u64) { return {}; } ErrorOr> resolve_as_link(Credentials const&, Custody& base, RefPtr* out_parent, int options, int symlink_recursion_level) const; @@ -123,6 +123,7 @@ protected: virtual ErrorOr write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*) = 0; virtual ErrorOr read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const = 0; + virtual ErrorOr truncate_locked(u64) { return {}; } private: ErrorOr try_apply_flock(Process const&, OpenFileDescription const&, flock const&); diff --git a/Kernel/FileSystem/Plan9FS/Inode.cpp b/Kernel/FileSystem/Plan9FS/Inode.cpp index aea2e628c1..e5df76b9ca 100644 --- a/Kernel/FileSystem/Plan9FS/Inode.cpp +++ b/Kernel/FileSystem/Plan9FS/Inode.cpp @@ -284,8 +284,9 @@ ErrorOr Plan9FSInode::chown(UserID, GroupID) return ENOTIMPL; } -ErrorOr Plan9FSInode::truncate(u64 new_size) +ErrorOr Plan9FSInode::truncate_locked(u64 new_size) { + VERIFY(m_inode_lock.is_locked()); if (fs().m_remote_protocol_version >= Plan9FS::ProtocolVersion::v9P2000L) { Plan9FSMessage message { fs(), Plan9FSMessage::Type::Tsetattr }; SetAttrMask valid = SetAttrMask::Size; diff --git a/Kernel/FileSystem/Plan9FS/Inode.h b/Kernel/FileSystem/Plan9FS/Inode.h index 14bd29e628..bb818c1bd2 100644 --- a/Kernel/FileSystem/Plan9FS/Inode.h +++ b/Kernel/FileSystem/Plan9FS/Inode.h @@ -33,7 +33,7 @@ public: virtual ErrorOr replace_child(StringView name, Inode& child) override; virtual ErrorOr chmod(mode_t) override; virtual ErrorOr chown(UserID, GroupID) override; - virtual ErrorOr truncate(u64) override; + virtual ErrorOr truncate_locked(u64) override; private: // ^Inode diff --git a/Kernel/FileSystem/ProcFS/Inode.h b/Kernel/FileSystem/ProcFS/Inode.h index 52889b9d62..408021fc86 100644 --- a/Kernel/FileSystem/ProcFS/Inode.h +++ b/Kernel/FileSystem/ProcFS/Inode.h @@ -50,7 +50,7 @@ private: virtual ErrorOr chmod(mode_t) override { return EROFS; } virtual ErrorOr chown(UserID, GroupID) override { return EROFS; } virtual ErrorOr write_bytes_locked(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) override { return EROFS; } - virtual ErrorOr truncate(u64) override { return EROFS; } + virtual ErrorOr truncate_locked(u64) override { return EROFS; } // ^Inode (Silent ignore handling) virtual ErrorOr flush_metadata() override { return {}; } diff --git a/Kernel/FileSystem/RAMFS/Inode.cpp b/Kernel/FileSystem/RAMFS/Inode.cpp index ae0ada01f6..ba8cdfd65a 100644 --- a/Kernel/FileSystem/RAMFS/Inode.cpp +++ b/Kernel/FileSystem/RAMFS/Inode.cpp @@ -361,9 +361,9 @@ ErrorOr RAMFSInode::remove_child(StringView name) return {}; } -ErrorOr RAMFSInode::truncate(u64 size) +ErrorOr RAMFSInode::truncate_locked(u64 size) { - MutexLocker locker(m_inode_lock); + VERIFY(m_inode_lock.is_locked()); VERIFY(!is_directory()); u64 block_index = size / DataBlock::block_size + ((size % DataBlock::block_size == 0) ? 0 : 1); diff --git a/Kernel/FileSystem/RAMFS/Inode.h b/Kernel/FileSystem/RAMFS/Inode.h index 84892044f6..3c24369cff 100644 --- a/Kernel/FileSystem/RAMFS/Inode.h +++ b/Kernel/FileSystem/RAMFS/Inode.h @@ -34,7 +34,7 @@ public: virtual ErrorOr replace_child(StringView name, Inode& child) override; virtual ErrorOr chmod(mode_t) override; virtual ErrorOr chown(UserID, GroupID) override; - virtual ErrorOr truncate(u64) override; + virtual ErrorOr truncate_locked(u64) override; virtual ErrorOr update_timestamps(Optional atime, Optional ctime, Optional mtime) override; private: diff --git a/Kernel/FileSystem/SysFS/Inode.cpp b/Kernel/FileSystem/SysFS/Inode.cpp index 970fcfd099..a19f668f13 100644 --- a/Kernel/FileSystem/SysFS/Inode.cpp +++ b/Kernel/FileSystem/SysFS/Inode.cpp @@ -105,8 +105,9 @@ ErrorOr SysFSInode::chown(UserID, GroupID) return EPERM; } -ErrorOr SysFSInode::truncate(u64 size) +ErrorOr SysFSInode::truncate_locked(u64 size) { + VERIFY(m_inode_lock.is_locked()); return m_associated_component->truncate(size); } diff --git a/Kernel/FileSystem/SysFS/Inode.h b/Kernel/FileSystem/SysFS/Inode.h index ea834f45b2..edcecdac0e 100644 --- a/Kernel/FileSystem/SysFS/Inode.h +++ b/Kernel/FileSystem/SysFS/Inode.h @@ -34,7 +34,7 @@ protected: virtual ErrorOr replace_child(StringView name, Inode& child) override; virtual ErrorOr chmod(mode_t) override; virtual ErrorOr chown(UserID, GroupID) override; - virtual ErrorOr truncate(u64) override; + virtual ErrorOr truncate_locked(u64) override; virtual ErrorOr update_timestamps(Optional atime, Optional ctime, Optional mtime) override; virtual ErrorOr attach(OpenFileDescription& description) override final;