Re: [ocfs2?] KASAN: use-after-free Read in __ocfs2_flush_truncate_log

From: Lizhi Xu
Date: Sun Sep 29 2024 - 00:48:34 EST


When the truncate log is initialized, it got a too big tl_used in truncate
log inode, tl_used is 64512 and tl_count is 39.

So, when the condition tl_used > tl_count holds, use the value of tl_count
to tl_used.

#syz test

diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index ea9127ba3208..a309920fecd1 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -6326,6 +6326,25 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb)
}
}

+void ocfs2_bh_valid(struct buffer_head *bh)
+{
+ struct ocfs2_dinode *di;
+ struct ocfs2_truncate_log *tl;
+
+ if (IS_ERR_OR_NULL(bh))
+ return;
+
+ di = (struct ocfs2_dinode *) bh->b_data;
+ tl = &di->id2.i_dealloc;
+
+ if (tl->tl_used > tl->tl_count) {
+ mlog(ML_NOTICE, "tl_used [%d] is greater than tl_count [%d], "
+ "set it to tl_count.\n", le16_to_cpu(tl->tl_used),
+ le16_to_cpu(tl->tl_count));
+ tl->tl_used = cpu_to_le16(tl->tl_count);
+ }
+}
+
int ocfs2_truncate_log_init(struct ocfs2_super *osb)
{
int status;
@@ -6339,6 +6358,8 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)
if (status < 0)
mlog_errno(status);

+ ocfs2_bh_valid(tl_bh);
+
/* ocfs2_truncate_log_shutdown keys on the existence of
* osb->osb_tl_inode so we don't set any of the osb variables
* until we're sure all is well. */