mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ocfs2: validate suballoc slot and bit of xattr and dir index blocks
ocfs2_validate_xattr_block() and ocfs2_validate_dx_root() do not validate xb_suballoc_slot, xb_suballoc_bit, dr_suballoc_slot and dr_suballoc_bit at all. Since xattr blocks and dir index root blocks are allocated from a per-slot suballocator at runtime, their suballoc slots must be within range and their suballoc bits must fit in a block group bitmap. Otherwise a corrupted image can carry an out-of-range slot. When the xattr block or dir index is removed, ocfs2_xattr_block_remove() or ocfs2_dx_dir_remove_index() passes the unvalidated slot to ocfs2_get_system_file_inode() and get_local_system_inode() will either hit BUG_ON(slot == OCFS2_INVALID_SLOT) or compute an out-of-bounds index into the local_system_inodes array. Similarly an oversized suballoc bit will error out the filesystem in _ocfs2_free_suballoc_bits(). Furthermore ocfs2_validate_dx_root() does not verify dr_blkno against the physical block number like the extent and xattr block validators do, so a misplaced dir index root block can pass validation. Reject misplaced dir index root blocks, out-of-range suballoc slots and oversized suballoc bits during validation. Link: https://lore.kernel.org/20260901125221.1634686-4-joseph.qi@linux.alibaba.com Signed-off-by: Joseph Qi <joseph.qi@linux.alibaba.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Cc: Changwei Ge <gechangwei@live.cn> Cc: Heming Zhao <heming.zhao@suse.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Jun Piao <piaojun@huawei.com> Cc: Junxiao Bi <junxiao.bi@oracle.com> Cc: Mark Fasheh <mark@fasheh.com>
This commit is contained in:
parent
e706b89c6a
commit
268fcde857
|
|
@ -605,6 +605,41 @@ static int ocfs2_validate_dx_root(struct super_block *sb,
|
|||
goto bail;
|
||||
}
|
||||
|
||||
if (le64_to_cpu(dx_root->dr_blkno) != bh->b_blocknr) {
|
||||
ret = ocfs2_error(sb,
|
||||
"Dir Index Root # %llu has an invalid dr_blkno of %llu\n",
|
||||
(unsigned long long)bh->b_blocknr,
|
||||
(unsigned long long)le64_to_cpu(dx_root->dr_blkno));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dir index root blocks are allocated from a per-slot suballocator,
|
||||
* so the slot must be in range. Otherwise removing the index passes
|
||||
* it to get_local_system_inode(), which hits BUG_ON() for
|
||||
* OCFS2_INVALID_SLOT or computes an out-of-bounds index otherwise.
|
||||
*/
|
||||
if ((u32)le16_to_cpu(dx_root->dr_suballoc_slot) >= OCFS2_SB(sb)->max_slots) {
|
||||
ret = ocfs2_error(sb,
|
||||
"Dir Index Root # %llu has invalid dr_suballoc_slot %u\n",
|
||||
(unsigned long long)le64_to_cpu(dx_root->dr_blkno),
|
||||
le16_to_cpu(dx_root->dr_suballoc_slot));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Similarly the suballoc bit must fit in a block group bitmap.
|
||||
* Otherwise removing the index will pass the oversized bit to
|
||||
* _ocfs2_free_suballoc_bits() and trigger ocfs2_error() there.
|
||||
*/
|
||||
if (le16_to_cpu(dx_root->dr_suballoc_bit) >= ocfs2_suballoc_bits_per_block(sb)) {
|
||||
ret = ocfs2_error(sb,
|
||||
"Dir Index Root # %llu has invalid dr_suballoc_bit %u\n",
|
||||
(unsigned long long)le64_to_cpu(dx_root->dr_blkno),
|
||||
le16_to_cpu(dx_root->dr_suballoc_bit));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (!(dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)) {
|
||||
struct ocfs2_extent_list *el = &dx_root->dr_list;
|
||||
|
||||
|
|
|
|||
|
|
@ -532,6 +532,31 @@ static int ocfs2_validate_xattr_block(struct super_block *sb,
|
|||
le32_to_cpu(xb->xb_fs_generation));
|
||||
}
|
||||
|
||||
/*
|
||||
* Xattr blocks are allocated from a per-slot suballocator, so the
|
||||
* slot must be in range. Otherwise freeing the block passes it to
|
||||
* get_local_system_inode(), which hits BUG_ON() for
|
||||
* OCFS2_INVALID_SLOT or computes an out-of-bounds index otherwise.
|
||||
*/
|
||||
if ((u32)le16_to_cpu(xb->xb_suballoc_slot) >= OCFS2_SB(sb)->max_slots) {
|
||||
return ocfs2_error(sb,
|
||||
"Extended attribute block #%llu has an invalid xb_suballoc_slot of %u\n",
|
||||
(unsigned long long)bh->b_blocknr,
|
||||
le16_to_cpu(xb->xb_suballoc_slot));
|
||||
}
|
||||
|
||||
/*
|
||||
* Similarly the suballoc bit must fit in a block group bitmap.
|
||||
* Otherwise freeing the block will pass the oversized bit to
|
||||
* _ocfs2_free_suballoc_bits() and trigger ocfs2_error() there.
|
||||
*/
|
||||
if (le16_to_cpu(xb->xb_suballoc_bit) >= ocfs2_suballoc_bits_per_block(sb)) {
|
||||
return ocfs2_error(sb,
|
||||
"Extended attribute block #%llu has an invalid xb_suballoc_bit of %u\n",
|
||||
(unsigned long long)bh->b_blocknr,
|
||||
le16_to_cpu(xb->xb_suballoc_bit));
|
||||
}
|
||||
|
||||
if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
|
||||
size_t region_offset =
|
||||
offsetof(struct ocfs2_xattr_block, xb_attrs.xb_header);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user