Kernel: Set unused block pointers in ext2 inodes to zero

e2fsck considers all blocks reachable through any of the pointers in
m_raw_inode.i_block as part of this inode regardless of the value in
m_raw_inode.i_size. When it finds more blocks than the amount that
is indicated by i_size or i_blocks it offers to repair the filesystem
by changing those values. That will actually cause further corruption.
So we must zero all pointers to blocks that are now unused.
This commit is contained in:
Mart G 2021-05-07 18:43:59 +02:00 committed by Andreas Kling
parent 09ea57031f
commit bfce328ade
Notes: sideshowbarker 2024-07-18 18:35:57 +09:00

View file

@ -426,6 +426,15 @@ KResult Ext2FSInode::flush_block_list()
++output_block_index;
--remaining_blocks;
}
// e2fsck considers all blocks reachable through any of the pointers in
// m_raw_inode.i_block as part of this inode regardless of the value in
// m_raw_inode.i_size. When it finds more blocks than the amount that
// is indicated by i_size or i_blocks it offers to repair the filesystem
// by changing those values. That will actually cause further corruption.
// So we must zero all pointers to blocks that are now unused.
for (unsigned i = new_shape.direct_blocks; i < EXT2_NDIR_BLOCKS; ++i) {
m_raw_inode.i_block[i] = 0;
}
if (inode_dirty) {
if constexpr (EXT2_DEBUG) {
dbgln("Ext2FSInode[{}]::flush_block_list(): Writing {} direct block(s) to i_block array of inode {}", identifier(), min((size_t)EXT2_NDIR_BLOCKS, m_block_list.size()), index());
@ -454,6 +463,7 @@ KResult Ext2FSInode::flush_block_list()
if (auto result = fs().set_block_allocation_state(m_raw_inode.i_block[EXT2_IND_BLOCK], false); result.is_error())
return result;
old_shape.meta_blocks--;
m_raw_inode.i_block[EXT2_IND_BLOCK] = 0;
}
}
@ -475,6 +485,8 @@ KResult Ext2FSInode::flush_block_list()
} else {
if (auto result = shrink_doubly_indirect_block(m_raw_inode.i_block[EXT2_DIND_BLOCK], old_shape.doubly_indirect_blocks, new_shape.doubly_indirect_blocks, old_shape.meta_blocks); result.is_error())
return result;
if (new_shape.doubly_indirect_blocks == 0)
m_raw_inode.i_block[EXT2_DIND_BLOCK] = 0;
}
}
@ -496,6 +508,8 @@ KResult Ext2FSInode::flush_block_list()
} else {
if (auto result = shrink_triply_indirect_block(m_raw_inode.i_block[EXT2_TIND_BLOCK], old_shape.triply_indirect_blocks, new_shape.triply_indirect_blocks, old_shape.meta_blocks); result.is_error())
return result;
if (new_shape.triply_indirect_blocks == 0)
m_raw_inode.i_block[EXT2_TIND_BLOCK] = 0;
}
}