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
This commit is contained in:
Bananymous 2026-01-11 03:58:48 +02:00
parent 4af9699b22
commit 5637b8602b
2 changed files with 12 additions and 7 deletions

View File

@ -70,6 +70,7 @@ namespace Kernel
BAN::ErrorOr<void> cleanup_indirect_block(uint32_t block, uint32_t depth); BAN::ErrorOr<void> cleanup_indirect_block(uint32_t block, uint32_t depth);
BAN::ErrorOr<void> cleanup_default_links(); BAN::ErrorOr<void> cleanup_default_links();
BAN::ErrorOr<void> cleanup_data_blocks();
BAN::ErrorOr<void> cleanup_from_fs(); BAN::ErrorOr<void> cleanup_from_fs();
BAN::ErrorOr<void> sync(); BAN::ErrorOr<void> sync();

View File

@ -171,8 +171,10 @@ namespace Kernel
BAN::ErrorOr<void> Ext2Inode::set_link_target_impl(BAN::StringView target) BAN::ErrorOr<void> Ext2Inode::set_link_target_impl(BAN::StringView target)
{ {
ASSERT(mode().iflnk()); 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)); memset(m_inode.block, 0, sizeof(m_inode.block));
memcpy(m_inode.block, target.data(), target.size()); memcpy(m_inode.block, target.data(), target.size());
m_inode.size = target.size(); m_inode.size = target.size();
@ -412,10 +414,8 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> Ext2Inode::cleanup_from_fs() BAN::ErrorOr<void> Ext2Inode::cleanup_data_blocks()
{ {
ASSERT(m_inode.links_count == 0);
if (mode().iflnk() && (size_t)size() < sizeof(m_inode.block)) if (mode().iflnk() && (size_t)size() < sizeof(m_inode.block))
goto done; goto done;
@ -436,12 +436,16 @@ done:
// mark blocks as deleted // mark blocks as deleted
memset(m_inode.block, 0x00, sizeof(m_inode.block)); 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(sync());
TRY(m_fs.delete_inode(ino())); return {};
}
BAN::ErrorOr<void> Ext2Inode::cleanup_from_fs()
{
ASSERT(m_inode.links_count == 0);
TRY(cleanup_data_blocks());
TRY(m_fs.delete_inode(ino()));
return {}; return {};
} }