* + ocfs2-validate-suballoc-slot-and-bit-of-xattr-and-dir-index-blocks.patch added to mm-nonmm-unstable branch
@ 2026-09-01 17:22 Andrew Morton
0 siblings, 0 replies; only message in thread
From: Andrew Morton @ 2026-09-01 17:22 UTC (permalink / raw)
To: mm-commits, piaojun, mark, junxiao.bi, jlbec, heming.zhao,
gechangwei, joseph.qi, akpm
The patch titled
Subject: ocfs2: validate suballoc slot and bit of xattr and dir index blocks
has been added to the -mm mm-nonmm-unstable branch. Its filename is
ocfs2-validate-suballoc-slot-and-bit-of-xattr-and-dir-index-blocks.patch
This patch will shortly appear at
https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/ocfs2-validate-suballoc-slot-and-bit-of-xattr-and-dir-index-blocks.patch
This patch will later appear in the mm-nonmm-unstable branch at
git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Before you just go and hit "reply", please:
a) Consider who else should be cc'ed
b) Prefer to cc a suitable mailing list as well
c) Ideally: find the original patch on the mailing list and do a
reply-to-all to that, adding suitable additional cc's
*** Remember to use Documentation/process/submit-checklist.rst when testing your code ***
The -mm tree is included into linux-next via various
branches at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
and is updated there most days
------------------------------------------------------
From: Joseph Qi <joseph.qi@linux.alibaba.com>
Subject: ocfs2: validate suballoc slot and bit of xattr and dir index blocks
Date: Tue, 1 Sep 2026 20:52:20 +0800
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>
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>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
fs/ocfs2/dir.c | 35 +++++++++++++++++++++++++++++++++++
fs/ocfs2/xattr.c | 25 +++++++++++++++++++++++++
2 files changed, 60 insertions(+)
--- a/fs/ocfs2/dir.c~ocfs2-validate-suballoc-slot-and-bit-of-xattr-and-dir-index-blocks
+++ a/fs/ocfs2/dir.c
@@ -605,6 +605,41 @@ static int ocfs2_validate_dx_root(struct
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;
--- a/fs/ocfs2/xattr.c~ocfs2-validate-suballoc-slot-and-bit-of-xattr-and-dir-index-blocks
+++ a/fs/ocfs2/xattr.c
@@ -532,6 +532,31 @@ static int ocfs2_validate_xattr_block(st
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);
_
Patches currently in -mm which might be from joseph.qi@linux.alibaba.com are
ocfs2-fix-deadlock-in-inline-data-truncate-transactions.patch
ocfs2-exit-recovery-thread-on-mount-error-path.patch
ocfs2-free-replay-slots-in-ocfs2_recovery_exit.patch
ocfs2-defer-suballocator-block-group-reclaim-to-workqueue.patch
ocfs2-restrict-ocfs2_invalid_slot-suballoc-slot-to-system-inodes.patch
ocfs2-validate-suballoc-bit-during-inode-read.patch
ocfs2-validate-suballoc-slot-and-bit-of-xattr-and-dir-index-blocks.patch
ocfs2-validate-suballoc-slot-and-bit-of-extent-and-refcount-blocks.patch
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-01 17:22 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-01 17:22 + ocfs2-validate-suballoc-slot-and-bit-of-xattr-and-dir-index-blocks.patch added to mm-nonmm-unstable branch Andrew Morton
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.