[PATCH 3/3] ocfs2: handle invalid dinode in _ocfs2_free_suballoc_bits
From: ZhengYuan Huang
Date: Fri Apr 03 2026 - 02:33:08 EST
[BUG]
A crafted filesystem can feed an invalid dinode into
_ocfs2_free_suballoc_bits() and trip:
kernel BUG at fs/ocfs2/suballoc.c:2568
[CAUSE]
The free path trusts alloc_bh returned from locked allocator reads, but
JBD-managed buffers can bypass inode validation before that buffer is
handed to _ocfs2_free_suballoc_bits().
[FIX]
Handle an invalid dinode as filesystem corruption and exit through the
existing bail path before touching any allocator accounting. This keeps
all cleanup and rollback logic intact while avoiding BUG().
Fixes: 10995aa2451a ("ocfs2: Morph the haphazard OCFS2_IS_VALID_DINODE() checks.")
Signed-off-by: ZhengYuan Huang <gality369@xxxxxxxxx>
---
fs/ocfs2/suballoc.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index b99870aeaf88..34bdc18200f2 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -2868,13 +2868,14 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle,
struct ocfs2_group_desc *group;
struct ocfs2_chain_rec *rec;
__le16 old_bg_contig_free_bits = 0;
- /* The alloc_bh comes from ocfs2_free_dinode() or
- * ocfs2_free_clusters(). The callers have all locked the
- * allocator and gotten alloc_bh from the lock call. This
- * validates the dinode buffer. Any corruption that has happened
- * is a code bug. */
- BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
+ /* JBD-managed buffers can bypass inode validation. */
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ status = ocfs2_error(alloc_inode->i_sb,
+ "Invalid dinode #%llu\n",
+ (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno);
+ goto bail;
+ }
BUG_ON((count + start_bit) > ocfs2_bits_per_group(cl));
trace_ocfs2_free_suballoc_bits(
--
2.43.0