fs/ocfs2/alloc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
[BUG]
A corrupted truncate log dinode can pass through mount initialization and
reach the delayed flush worker, where it triggers:
kernel BUG at fs/ocfs2/alloc.c:6019!
Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
RIP: 0010:__ocfs2_flush_truncate_log+0xa87/0xf10 fs/ocfs2/alloc.c:6019
Call Trace:
ocfs2_flush_truncate_log fs/ocfs2/alloc.c:6084 [inline]
ocfs2_truncate_log_worker+0xa9/0x180 fs/ocfs2/alloc.c:6097
process_one_work+0x8e0/0x1980 kernel/workqueue.c:3263
...
[CAUSE]
ocfs2_get_truncate_log_info() assumes that ocfs2_read_inode_block()
always validates the returned dinode. However, ocfs2_read_blocks() skips
the validation callback for JBD-managed buffers. The function then reads
truncate log fields and exposes the invalid buffer to callers, allowing
ocfs2_truncate_log_init() to retain it in osb->osb_tl_bh.
[FIX]
Check the dinode signature in ocfs2_get_truncate_log_info() immediately
after the inode read. Reject an invalid dinode as filesystem corruption
before reading truncate log fields or returning the inode and buffer to
the caller. This keeps invalid state out of the long-lived truncate log
cache and preserves the validated-buffer invariant in append, flush, and
recovery paths.
Fixes: 10995aa2451a ("ocfs2: Morph the haphazard OCFS2_IS_VALID_DINODE() checks.")
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: ZhengYuan Huang <gality369@gmail.com>
---
fs/ocfs2/alloc.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index be09e766ac1f..e36ae2e522d3 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -6192,6 +6192,19 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb,
}
di = (struct ocfs2_dinode *)bh->b_data;
+ /*
+ * A JBD-managed buffer may skip the read validation callback. Check
+ * the signature before exposing the truncate log to callers.
+ */
+ if (!OCFS2_IS_VALID_DINODE(di)) {
+ status = ocfs2_error(osb->sb,
+ "Invalid truncate log dinode #%llu\n",
+ (unsigned long long)bh->b_blocknr);
+ iput(inode);
+ brelse(bh);
+ goto bail;
+ }
+
tl = &di->id2.i_dealloc;
tl_count = le16_to_cpu(tl->tl_count);
tl_used = le16_to_cpu(tl->tl_used);
--
2.43.0
On 7/22/26 5:11 PM, ZhengYuan Huang wrote:
> [BUG]
> A corrupted truncate log dinode can pass through mount initialization and
> reach the delayed flush worker, where it triggers:
>
> kernel BUG at fs/ocfs2/alloc.c:6019!
> Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
> RIP: 0010:__ocfs2_flush_truncate_log+0xa87/0xf10 fs/ocfs2/alloc.c:6019
> Call Trace:
> ocfs2_flush_truncate_log fs/ocfs2/alloc.c:6084 [inline]
> ocfs2_truncate_log_worker+0xa9/0x180 fs/ocfs2/alloc.c:6097
> process_one_work+0x8e0/0x1980 kernel/workqueue.c:3263
> ...
>
I've encountered this BUG occasionality. But I don't see why it happens.
Do you have more clues on how to reproduce it?
Thanks,
Joseph
> [CAUSE]
> ocfs2_get_truncate_log_info() assumes that ocfs2_read_inode_block()
> always validates the returned dinode. However, ocfs2_read_blocks() skips
> the validation callback for JBD-managed buffers. The function then reads
> truncate log fields and exposes the invalid buffer to callers, allowing
> ocfs2_truncate_log_init() to retain it in osb->osb_tl_bh.
>
> [FIX]
> Check the dinode signature in ocfs2_get_truncate_log_info() immediately
> after the inode read. Reject an invalid dinode as filesystem corruption
> before reading truncate log fields or returning the inode and buffer to
> the caller. This keeps invalid state out of the long-lived truncate log
> cache and preserves the validated-buffer invariant in append, flush, and
> recovery paths.
>
> Fixes: 10995aa2451a ("ocfs2: Morph the haphazard OCFS2_IS_VALID_DINODE() checks.")
> Assisted-by: Codex:gpt-5.6-sol
> Signed-off-by: ZhengYuan Huang <gality369@gmail.com>
> ---
> fs/ocfs2/alloc.c | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> index be09e766ac1f..e36ae2e522d3 100644
> --- a/fs/ocfs2/alloc.c
> +++ b/fs/ocfs2/alloc.c
> @@ -6192,6 +6192,19 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb,
> }
>
> di = (struct ocfs2_dinode *)bh->b_data;
> + /*
> + * A JBD-managed buffer may skip the read validation callback. Check
> + * the signature before exposing the truncate log to callers.
> + */
> + if (!OCFS2_IS_VALID_DINODE(di)) {
> + status = ocfs2_error(osb->sb,
> + "Invalid truncate log dinode #%llu\n",
> + (unsigned long long)bh->b_blocknr);
> + iput(inode);
> + brelse(bh);
> + goto bail;
> + }
> +
> tl = &di->id2.i_dealloc;
> tl_count = le16_to_cpu(tl->tl_count);
> tl_used = le16_to_cpu(tl->tl_used);
On Wed, Jul 22, 2026 at 8:56 PM Joseph Qi <joseph.qi@linux.alibaba.com> wrote: > > > > On 7/22/26 5:11 PM, ZhengYuan Huang wrote: > > [BUG] > > A corrupted truncate log dinode can pass through mount initialization and > > reach the delayed flush worker, where it triggers: > > > > kernel BUG at fs/ocfs2/alloc.c:6019! > > Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI > > RIP: 0010:__ocfs2_flush_truncate_log+0xa87/0xf10 fs/ocfs2/alloc.c:6019 > > Call Trace: > > ocfs2_flush_truncate_log fs/ocfs2/alloc.c:6084 [inline] > > ocfs2_truncate_log_worker+0xa9/0x180 fs/ocfs2/alloc.c:6097 > > process_one_work+0x8e0/0x1980 kernel/workqueue.c:3263 > > ... > > > > I've encountered this BUG occasionality. But I don't see why it happens. > Do you have more clues on how to reproduce it? > > Thanks, > Joseph Thanks for looking into this. This bug was originally found by our fuzzing tool. We tried to reproduce it using the automatically saved disk image and syscall program, but so far we have been unable to reproduce the BUG in __ocfs2_flush_truncate_log directly. Instead, the same artifacts have triggered two other issues: KASAN: use-after-free Read in ocfs2_dx_dir_search kernel BUG in ocfs2_grow_tree For the use-after-free in ocfs2_dx_dir_search, I previously submitted a patch that addresses what I believe is its root cause: https://lore.kernel.org/all/20260416082105.1295887-1-gality369@gmail.com/ However, I have not received any feedback on the patch yet, and at this point we are not sure whether that issue is related to the truncate-log corruption reported here. We are continuing to investigate and will share any new findings. In the meantime, the original artifacts generated by our fuzzer are available here: https://drive.google.com/file/d/1zCJoUb2uwVqTrGIM4JFLbwkcHRz04TJo/view?usp=sharing The archive contains the disk image, the PoC program, and a kernel log. To run the reproducer, mount the supplied disk image and execute the PoC. Please note that, in our current tests, these artifacts can trigger the two issues mentioned above, but they do not reproduce the BUG in __ocfs2_flush_truncate_log. The archive also includes the kernel log captured when the original BUG occurred, which may help with further investigation. Thanks, ZhengYuan Huang
On 7/23/26 11:05 AM, ZhengYuan Huang wrote: > On Wed, Jul 22, 2026 at 8:56 PM Joseph Qi <joseph.qi@linux.alibaba.com> wrote: >> >> >> >> On 7/22/26 5:11 PM, ZhengYuan Huang wrote: >>> [BUG] >>> A corrupted truncate log dinode can pass through mount initialization and >>> reach the delayed flush worker, where it triggers: >>> >>> kernel BUG at fs/ocfs2/alloc.c:6019! >>> Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI >>> RIP: 0010:__ocfs2_flush_truncate_log+0xa87/0xf10 fs/ocfs2/alloc.c:6019 >>> Call Trace: >>> ocfs2_flush_truncate_log fs/ocfs2/alloc.c:6084 [inline] >>> ocfs2_truncate_log_worker+0xa9/0x180 fs/ocfs2/alloc.c:6097 >>> process_one_work+0x8e0/0x1980 kernel/workqueue.c:3263 >>> ... >>> >> >> I've encountered this BUG occasionality. But I don't see why it happens. >> Do you have more clues on how to reproduce it? >> >> Thanks, >> Joseph > > Thanks for looking into this. > > This bug was originally found by our fuzzing tool. We tried to > reproduce it using the automatically saved disk image and syscall > program, but so far we have been unable to reproduce the BUG in > __ocfs2_flush_truncate_log directly. Instead, the same artifacts have > triggered two other issues: > > KASAN: use-after-free Read in ocfs2_dx_dir_search > kernel BUG in ocfs2_grow_tree > > For the use-after-free in ocfs2_dx_dir_search, I previously submitted > a patch that addresses what I believe is its root cause: > > https://lore.kernel.org/all/20260416082105.1295887-1-gality369@gmail.com/ > > However, I have not received any feedback on the patch yet, and at > this point we are not sure whether that issue is related to the > truncate-log corruption reported here. > It seems I've missed the thread. And I've found a similar one in: https://lore.kernel.org/ocfs2-devel/20260713205625.92391-1-doruk@0sec.ai/ Could you please check if it fixes the same issue? Thanks, Joseph > We are continuing to investigate and will share any new findings. In > the meantime, the original artifacts generated by our fuzzer are > available here: > > https://drive.google.com/file/d/1zCJoUb2uwVqTrGIM4JFLbwkcHRz04TJo/view?usp=sharing > > The archive contains the disk image, the PoC program, and a kernel > log. To run the reproducer, mount the supplied disk image and execute > the PoC. Please note that, in our current tests, these artifacts can > trigger the two issues mentioned above, but they do not reproduce the > BUG in __ocfs2_flush_truncate_log. The archive also includes the > kernel log captured when the original BUG occurred, which may help > with further investigation. > > Thanks, > ZhengYuan Huang
© 2016 - 2026 Red Hat, Inc.