From 5637b8602b55ebcfab32f468bfe9abeb07af4832 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 11 Jan 2026 03:58:48 +0200 Subject: [PATCH] Kernel: Fix setting ext2 symbolic link target If a link was >= 60 bytes but got shrinked to 60 bytes, reading it would rebort garbage and unlinking it would leak blocks --- kernel/include/kernel/FS/Ext2/Inode.h | 1 + kernel/kernel/FS/Ext2/Inode.cpp | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/kernel/include/kernel/FS/Ext2/Inode.h b/kernel/include/kernel/FS/Ext2/Inode.h index ec663752..a80fa5eb 100644 --- a/kernel/include/kernel/FS/Ext2/Inode.h +++ b/kernel/include/kernel/FS/Ext2/Inode.h @@ -70,6 +70,7 @@ namespace Kernel BAN::ErrorOr cleanup_indirect_block(uint32_t block, uint32_t depth); BAN::ErrorOr cleanup_default_links(); + BAN::ErrorOr cleanup_data_blocks(); BAN::ErrorOr cleanup_from_fs(); BAN::ErrorOr sync(); diff --git a/kernel/kernel/FS/Ext2/Inode.cpp b/kernel/kernel/FS/Ext2/Inode.cpp index 83861bdd..45b545b5 100644 --- a/kernel/kernel/FS/Ext2/Inode.cpp +++ b/kernel/kernel/FS/Ext2/Inode.cpp @@ -171,8 +171,10 @@ namespace Kernel BAN::ErrorOr Ext2Inode::set_link_target_impl(BAN::StringView target) { ASSERT(mode().iflnk()); - if (m_inode.size < sizeof(m_inode.block) && target.size() < sizeof(m_inode.block)) + if (target.size() < sizeof(m_inode.block)) { + if (m_inode.size >= sizeof(m_inode.block)) + TRY(cleanup_data_blocks()); memset(m_inode.block, 0, sizeof(m_inode.block)); memcpy(m_inode.block, target.data(), target.size()); m_inode.size = target.size(); @@ -412,10 +414,8 @@ namespace Kernel return {}; } - BAN::ErrorOr Ext2Inode::cleanup_from_fs() + BAN::ErrorOr Ext2Inode::cleanup_data_blocks() { - ASSERT(m_inode.links_count == 0); - if (mode().iflnk() && (size_t)size() < sizeof(m_inode.block)) goto done; @@ -436,12 +436,16 @@ done: // mark blocks as deleted memset(m_inode.block, 0x00, sizeof(m_inode.block)); - // FIXME: this is only required since fs does not get - // deleting inode from its cache TRY(sync()); - TRY(m_fs.delete_inode(ino())); + return {}; + } + BAN::ErrorOr Ext2Inode::cleanup_from_fs() + { + ASSERT(m_inode.links_count == 0); + TRY(cleanup_data_blocks()); + TRY(m_fs.delete_inode(ino())); return {}; }