1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 04:48:14 +00:00

Ext2FS: Fail with EMFILE if we would overflow i_links_count

This commit is contained in:
Andreas Kling 2020-02-08 02:26:33 +01:00
parent 88ea152b24
commit cb97ef5589
4 changed files with 22 additions and 16 deletions

View file

@ -36,6 +36,7 @@
//#define EXT2_DEBUG //#define EXT2_DEBUG
static const size_t max_link_count = 65535;
static const size_t max_block_size = 4096; static const size_t max_block_size = 4096;
static const ssize_t max_inline_symlink_length = 60; 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); auto child_inode = fs().get_inode(child_id);
if (child_inode) if (child_inode) {
child_inode->increment_link_count(); 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)); entries.empend(name.characters_without_null_termination(), name.length(), child_id, to_ext2_file_type(mode));
bool success = write_directory(entries); bool success = write_directory(entries);
@ -1539,27 +1543,29 @@ int Ext2FSInode::set_mtime(time_t t)
return 0; return 0;
} }
int Ext2FSInode::increment_link_count() KResult Ext2FSInode::increment_link_count()
{ {
LOCKER(m_lock); LOCKER(m_lock);
if (fs().is_readonly()) 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; ++m_raw_inode.i_links_count;
set_metadata_dirty(true); set_metadata_dirty(true);
return 0; return KSuccess;
} }
int Ext2FSInode::decrement_link_count() KResult Ext2FSInode::decrement_link_count()
{ {
LOCKER(m_lock); LOCKER(m_lock);
if (fs().is_readonly()) if (fs().is_readonly())
return -EROFS; return KResult(-EROFS);
ASSERT(m_raw_inode.i_links_count); ASSERT(m_raw_inode.i_links_count);
--m_raw_inode.i_links_count; --m_raw_inode.i_links_count;
if (ref_count() == 1 && m_raw_inode.i_links_count == 0) if (ref_count() == 1 && m_raw_inode.i_links_count == 0)
fs().uncache_inode(index()); fs().uncache_inode(index());
set_metadata_dirty(true); set_metadata_dirty(true);
return 0; return KSuccess;
} }
void Ext2FS::uncache_inode(InodeIndex index) void Ext2FS::uncache_inode(InodeIndex index)

View file

@ -65,8 +65,8 @@ private:
virtual int set_atime(time_t) override; virtual int set_atime(time_t) override;
virtual int set_ctime(time_t) override; virtual int set_ctime(time_t) override;
virtual int set_mtime(time_t) override; virtual int set_mtime(time_t) override;
virtual int increment_link_count() override; virtual KResult increment_link_count() override;
virtual int decrement_link_count() override; virtual KResult decrement_link_count() override;
virtual size_t directory_entry_count() const override; virtual size_t directory_entry_count() const override;
virtual KResult chmod(mode_t) override; virtual KResult chmod(mode_t) override;
virtual KResult chown(uid_t, gid_t) override; virtual KResult chown(uid_t, gid_t) override;

View file

@ -151,14 +151,14 @@ int Inode::set_mtime(time_t)
return -ENOTIMPL; 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) void Inode::set_vmobject(VMObject& vmobject)

View file

@ -94,8 +94,8 @@ public:
virtual int set_atime(time_t); virtual int set_atime(time_t);
virtual int set_ctime(time_t); virtual int set_ctime(time_t);
virtual int set_mtime(time_t); virtual int set_mtime(time_t);
virtual int increment_link_count(); virtual KResult increment_link_count();
virtual int decrement_link_count(); virtual KResult decrement_link_count();
virtual void flush_metadata() = 0; virtual void flush_metadata() = 0;