* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox