Skip to content

Commit 7de554c

Browse files
bharambetejasakpm00
authored andcommitted
ocfs2: fix use-after-free in ocfs2_fault() when VM_FAULT_RETRY
filemap_fault() may drop the mmap_lock before returning VM_FAULT_RETRY, as documented in mm/filemap.c: "If our return value has VM_FAULT_RETRY set, it's because the mmap_lock may be dropped before doing I/O or by lock_folio_maybe_drop_mmap()." When this happens, a concurrent munmap() can call remove_vma() and free the vm_area_struct via RCU. The saved 'vma' pointer in ocfs2_fault() then becomes a dangling pointer, and the subsequent trace_ocfs2_fault() call dereferences it -- a use-after-free. Fix this by saving ip_blkno as a plain integer before calling filemap_fault(), and removing vma from the trace event. Since ip_blkno is copied by value before the lock can be dropped, it remains valid regardless of what happens to the vma or inode afterward. Link: https://lkml.kernel.org/r/20260410083816.34951-1-tejas.bharambe@outlook.com Fixes: 614a9e8 ("ocfs2: Remove FILE_IO from masklog.") Signed-off-by: Tejas Bharambe <tejas.bharambe@outlook.com> Reported-by: syzbot+a49010a0e8fcdeea075f@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=a49010a0e8fcdeea075f Suggested-by: Joseph Qi <joseph.qi@linux.alibaba.com> Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com> Cc: Mark Fasheh <mark@fasheh.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Junxiao Bi <junxiao.bi@oracle.com> Cc: Changwei Ge <gechangwei@live.cn> Cc: Jun Piao <piaojun@huawei.com> Cc: Heming Zhao <heming.zhao@suse.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 4a1c0dd commit 7de554c

2 files changed

Lines changed: 7 additions & 10 deletions

File tree

fs/ocfs2/mmap.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,18 @@
3030

3131
static vm_fault_t ocfs2_fault(struct vm_fault *vmf)
3232
{
33-
struct vm_area_struct *vma = vmf->vma;
33+
unsigned long long ip_blkno =
34+
OCFS2_I(file_inode(vmf->vma->vm_file))->ip_blkno;
3435
sigset_t oldset;
3536
vm_fault_t ret;
3637

3738
ocfs2_block_signals(&oldset);
3839
ret = filemap_fault(vmf);
3940
ocfs2_unblock_signals(&oldset);
4041

41-
trace_ocfs2_fault(OCFS2_I(vma->vm_file->f_mapping->host)->ip_blkno,
42-
vma, vmf->page, vmf->pgoff);
42+
trace_ocfs2_fault(ip_blkno, vmf->page, vmf->pgoff);
4343
return ret;
4444
}
45-
4645
static vm_fault_t __ocfs2_page_mkwrite(struct file *file,
4746
struct buffer_head *di_bh, struct folio *folio)
4847
{

fs/ocfs2/ocfs2_trace.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,22 +1246,20 @@ TRACE_EVENT(ocfs2_write_end_inline,
12461246

12471247
TRACE_EVENT(ocfs2_fault,
12481248
TP_PROTO(unsigned long long ino,
1249-
void *area, void *page, unsigned long pgoff),
1250-
TP_ARGS(ino, area, page, pgoff),
1249+
void *page, unsigned long pgoff),
1250+
TP_ARGS(ino, page, pgoff),
12511251
TP_STRUCT__entry(
12521252
__field(unsigned long long, ino)
1253-
__field(void *, area)
12541253
__field(void *, page)
12551254
__field(unsigned long, pgoff)
12561255
),
12571256
TP_fast_assign(
12581257
__entry->ino = ino;
1259-
__entry->area = area;
12601258
__entry->page = page;
12611259
__entry->pgoff = pgoff;
12621260
),
1263-
TP_printk("%llu %p %p %lu",
1264-
__entry->ino, __entry->area, __entry->page, __entry->pgoff)
1261+
TP_printk("%llu %p %lu",
1262+
__entry->ino, __entry->page, __entry->pgoff)
12651263
);
12661264

12671265
/* End of trace events for fs/ocfs2/mmap.c. */

0 commit comments

Comments
 (0)