From cb97ef5589e8e6bf8ecf7974960a0f7635d95f87 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 8 Feb 2020 02:26:33 +0100 Subject: [PATCH] Ext2FS: Fail with EMFILE if we would overflow i_links_count --- Kernel/FileSystem/Ext2FileSystem.cpp | 22 ++++++++++++++-------- Kernel/FileSystem/Ext2FileSystem.h | 4 ++-- Kernel/FileSystem/Inode.cpp | 8 ++++---- Kernel/FileSystem/Inode.h | 4 ++-- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp index bd7d52519c2..b400d357584 100644 --- a/Kernel/FileSystem/Ext2FileSystem.cpp +++ b/Kernel/FileSystem/Ext2FileSystem.cpp @@ -36,6 +36,7 @@ //#define EXT2_DEBUG +static const size_t max_link_count = 65535; static const size_t max_block_size = 4096; static const ssize_t max_inline_symlink_length = 60; @@ -950,8 +951,11 @@ KResult Ext2FSInode::add_child(InodeIdentifier child_id, const StringView& name, } auto child_inode = fs().get_inode(child_id); - if (child_inode) - child_inode->increment_link_count(); + if (child_inode) { + auto result = child_inode->increment_link_count(); + if (result.is_error()) + return result; + } entries.empend(name.characters_without_null_termination(), name.length(), child_id, to_ext2_file_type(mode)); bool success = write_directory(entries); @@ -1539,27 +1543,29 @@ int Ext2FSInode::set_mtime(time_t t) return 0; } -int Ext2FSInode::increment_link_count() +KResult Ext2FSInode::increment_link_count() { LOCKER(m_lock); if (fs().is_readonly()) - return -EROFS; + return KResult(-EROFS); + if (m_raw_inode.i_links_count == max_link_count) + return KResult(-EMLINK); ++m_raw_inode.i_links_count; set_metadata_dirty(true); - return 0; + return KSuccess; } -int Ext2FSInode::decrement_link_count() +KResult Ext2FSInode::decrement_link_count() { LOCKER(m_lock); if (fs().is_readonly()) - return -EROFS; + return KResult(-EROFS); ASSERT(m_raw_inode.i_links_count); --m_raw_inode.i_links_count; if (ref_count() == 1 && m_raw_inode.i_links_count == 0) fs().uncache_inode(index()); set_metadata_dirty(true); - return 0; + return KSuccess; } void Ext2FS::uncache_inode(InodeIndex index) diff --git a/Kernel/FileSystem/Ext2FileSystem.h b/Kernel/FileSystem/Ext2FileSystem.h index 7a629ae2600..7b8168e11fb 100644 --- a/Kernel/FileSystem/Ext2FileSystem.h +++ b/Kernel/FileSystem/Ext2FileSystem.h @@ -65,8 +65,8 @@ private: virtual int set_atime(time_t) override; virtual int set_ctime(time_t) override; virtual int set_mtime(time_t) override; - virtual int increment_link_count() override; - virtual int decrement_link_count() override; + virtual KResult increment_link_count() override; + virtual KResult decrement_link_count() override; virtual size_t directory_entry_count() const override; virtual KResult chmod(mode_t) override; virtual KResult chown(uid_t, gid_t) override; diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp index 5b813ecc9eb..8b745b9f382 100644 --- a/Kernel/FileSystem/Inode.cpp +++ b/Kernel/FileSystem/Inode.cpp @@ -151,14 +151,14 @@ int Inode::set_mtime(time_t) return -ENOTIMPL; } -int Inode::increment_link_count() +KResult Inode::increment_link_count() { - return -ENOTIMPL; + return KResult(-ENOTIMPL); } -int Inode::decrement_link_count() +KResult Inode::decrement_link_count() { - return -ENOTIMPL; + return KResult(-ENOTIMPL); } void Inode::set_vmobject(VMObject& vmobject) diff --git a/Kernel/FileSystem/Inode.h b/Kernel/FileSystem/Inode.h index 1390b4dc5f7..23ec6616f23 100644 --- a/Kernel/FileSystem/Inode.h +++ b/Kernel/FileSystem/Inode.h @@ -94,8 +94,8 @@ public: virtual int set_atime(time_t); virtual int set_ctime(time_t); virtual int set_mtime(time_t); - virtual int increment_link_count(); - virtual int decrement_link_count(); + virtual KResult increment_link_count(); + virtual KResult decrement_link_count(); virtual void flush_metadata() = 0;