* [PATCH] ocfs2: validate dx entry list counts on read
@ 2026-04-16 8:21 ZhengYuan Huang
0 siblings, 0 replies; only message in thread
From: ZhengYuan Huang @ 2026-04-16 8:21 UTC (permalink / raw)
To: mark, jlbec, joseph.qi
Cc: ocfs2-devel, linux-kernel, baijiaju1990, r33s3n6, zzzccc427,
ZhengYuan Huang
[BUG]
A corrupt indexed directory block can carry de_num_used larger than
de_count. When create() needs to rebalance the directory index, that
corrupt count reaches ocfs2_dx_dir_transfer_leaf() and trips fortify:
kernel BUG at lib/string_helpers.c:1043!
RIP: 0010:__fortify_panic+0x24/0x30 lib/string_helpers.c:1043
Call Trace:
fortify_memset_chk include/linux/fortify-string.h:497 [inline]
ocfs2_dx_dir_transfer_leaf fs/ocfs2/dir.c:3677 [inline]
ocfs2_dx_dir_rebalance.isra.0+0x231a/0x24c0 fs/ocfs2/dir.c:3873
ocfs2_find_dir_space_dx.isra.0+0x32c/0x5f0 fs/ocfs2/dir.c:3950
ocfs2_prepare_dx_dir_for_insert.isra.0+0x750/0xf20 fs/ocfs2/dir.c:4207
ocfs2_prepare_dir_for_insert+0xe79/0x1630 fs/ocfs2/dir.c:4288
ocfs2_mknod+0x81c/0x2400 fs/ocfs2/namei.c:297
ocfs2_create+0x158/0x390 fs/ocfs2/namei.c:676
lookup_open.isra.0+0x10a1/0x1460 fs/namei.c:3796
open_last_lookups fs/namei.c:3895 [inline]
path_openat+0x11fe/0x2ce0 fs/namei.c:4131
do_filp_open+0x1f6/0x430 fs/namei.c:4161
do_sys_openat2+0x117/0x1c0 fs/open.c:1437
do_sys_open fs/open.c:1452 [inline]
__do_sys_openat fs/open.c:1468 [inline]
__se_sys_openat fs/open.c:1463 [inline]
__x64_sys_openat+0x15b/0x220 fs/open.c:1463
...
[CAUSE]
DX leaf and inline dx root blocks validate signatures and ECC, but they
do not validate the geometry of struct ocfs2_dx_entry_list. Corrupt
de_count/de_num_used values therefore survive block read and are later
used as traversal bounds and memset lengths in lookup, delete and
rebalance paths.
[FIX]
Validate dx entry-list geometry in the metadata read callbacks. de_count
must match the block layout for the current superblock, and de_num_used
must not exceed de_count. Do this for both dx leaves and inline dx
roots so corrupted metadata is rejected before any caller walks or
rewrites de_entries[].
Signed-off-by: ZhengYuan Huang <gality369@gmail.com>
---
No Fixes tag is included because this is a missing metadata validation
check, not a regression attributable to a single introducing commit.
---
fs/ocfs2/dir.c | 40 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 8e6b03238327..a89634e20b32 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -578,6 +578,29 @@ static int ocfs2_read_dir_block_direct(struct inode *dir, u64 phys,
return ret;
}
+static int ocfs2_validate_dx_entry_list(struct super_block *sb, u64 blkno,
+ struct ocfs2_dx_entry_list *entry_list,
+ unsigned int expected,
+ const char *owner)
+{
+ unsigned int count = le16_to_cpu(entry_list->de_count);
+ unsigned int num_used = le16_to_cpu(entry_list->de_num_used);
+
+ if (count != expected)
+ return ocfs2_error(sb,
+ "%s # %llu has invalid de_count %u (expected %u)\n",
+ owner, (unsigned long long)blkno, count,
+ expected);
+
+ if (num_used > count)
+ return ocfs2_error(sb,
+ "%s # %llu has invalid de_num_used %u (de_count %u)\n",
+ owner, (unsigned long long)blkno, num_used,
+ count);
+
+ return 0;
+}
+
static int ocfs2_validate_dx_root(struct super_block *sb,
struct buffer_head *bh)
{
@@ -604,7 +625,14 @@ static int ocfs2_validate_dx_root(struct super_block *sb,
goto bail;
}
- if (!(dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)) {
+ if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE) {
+ ret = ocfs2_validate_dx_entry_list(sb, bh->b_blocknr,
+ &dx_root->dr_entries,
+ ocfs2_dx_entries_per_root(sb),
+ "Dir Index Root");
+ if (ret)
+ goto bail;
+ } else {
struct ocfs2_extent_list *el = &dx_root->dr_list;
if (le16_to_cpu(el->l_count) != ocfs2_extent_recs_per_dx_root(sb)) {
@@ -660,13 +688,21 @@ static int ocfs2_validate_dx_leaf(struct super_block *sb,
mlog(ML_ERROR,
"Checksum failed for dir index leaf block %llu\n",
(unsigned long long)bh->b_blocknr);
- return ret;
+ goto bail;
}
if (!OCFS2_IS_VALID_DX_LEAF(dx_leaf)) {
ret = ocfs2_error(sb, "Dir Index Leaf has bad signature %.*s\n",
7, dx_leaf->dl_signature);
+ goto bail;
}
+ ret = ocfs2_validate_dx_entry_list(sb, bh->b_blocknr,
+ &dx_leaf->dl_list,
+ ocfs2_dx_entries_per_leaf(sb),
+ "Dir Index Leaf");
+
+bail:
+
return ret;
}
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-04-16 8:21 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-16 8:21 [PATCH] ocfs2: validate dx entry list counts on read ZhengYuan Huang
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.