Re:Re: [PATCH] ocfs2: validate non-coherent freefrag bitmap inode

From: jiale yao

Date: Tue Oct 20 2026 - 03:58:52 EST


Hi Joseph,

At 2026-10-20 15:43:21, "Joseph Qi" <joseph.qi@xxxxxxxxxxxxxxxxx> wrote:
>
>
>On 10/18/26 7:41 PM, Jiale Yao wrote:
>> The non-coherent freefrag ioctl path reads the global bitmap inode
>> directly and trusts its chain list. A malformed cl_next_free_rec value
>> can therefore index beyond cl_recs while scanning chains.
>>
>
>Could you provide the detailed bug report?


The normal UP/non-RT path usually runs the tasklet from irq_exit().
However, if the DMA IRQ raises TASKLET_SOFTIRQ after that vector has
already been processed in the current softirq pass, need_resched() or
the softirq time/restart limits can defer it to ksoftirqd. Process
context may then release the channel before the tasklet runs.

A similar teardown issue was fixed by commit 0ca79979384f
("RDMA/erdma: Fix CEQ tasklet use-after-free on removal"). There too,
free_irq() stops the hard IRQ but does not drain an already queued
tasklet, so tasklet_kill() is placed before releasing its resources.

For mxs-dma, the deferred operation is the completion callback rather
than direct access to the coherent command buffer. The tasklet can
therefore invoke the callback after its client data has been released,
even on a UP/non-RT system.


>
>> Validate the inode block before consuming its bitmap and chain metadata.
>>
>> Fixes: d24a10b9f8ed ("Ocfs2: Add a new code 'OCFS2_INFO_FREEFRAG' for o2info ioctl.")
>> Signed-off-by: Jiale Yao <yaojiale02@xxxxxxx>
>> ---
>> fs/ocfs2/ioctl.c | 6 ++++++
>> 1 file changed, 6 insertions(+)
>>
>> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
>> index cbe59d231666..8383f900c847 100644
>> --- a/fs/ocfs2/ioctl.c
>> +++ b/fs/ocfs2/ioctl.c
>> @@ -575,6 +575,12 @@ static int ocfs2_info_freefrag_scan_bitmap(struct ocfs2_super *osb,
>> mlog_errno(status);
>> goto bail;
>> }
>> +
>> + status = ocfs2_validate_inode_block(osb->sb, bh);
>> + if (status < 0) {
>> + mlog_errno(status);
>> + goto bail;
>> + }
>
>ocfs2_validate_inode_block() only validates cl_next_free_rec when
>on-disk dinode has OCFS2_CHAIN_FL set. So a crafted global bitmap block
>without that flag still lets the freefrag chain walk index past cl_recs[]
>and read out of bounds from the buffer_head.

I will fix the bug in v2.

>
>Thanks,
>Joseph
>
>> }
>>
>> gb_dinode = (struct ocfs2_dinode *)bh->b_data;

Jiale