ntfs3: Use after free race condition in ntfs_read_folio()?
Dirk Behme <[email protected]> Wed, 27 May 2026 06:34:30 +0200
| Newsgroups | dev.linux.lists.ntfs3 |
|---|---|
| Message-ID | <[email protected]> |
Hi,
on a custom ARM64 board with kernel 6.1.157 we got a report about a data
abort Oops [1] in ntfs_read_folio() [2]. The disassembly is [3].
Analysing this the failing instruction is
385f82e8 ldurb w8, [x23, #-8]
with x23: ffff8d623ef35800 - 8 matching the fault address ffff8d623ef357f8.
Matching this to the C code we think the compiler summarises
struct ntfs_inode *ni = ntfs_i(inode);
if (is_resident(ni)) {
to one assembly instruction to access the ni_flags in struct ntfs_inode
via the inode [4].
Getting a data abort trying to access the ni_flags, we assume that the
whole struct ntfs_inode has been freed, already. While missing to reset
/ clear some reference to it. What in sum looks like a use after free
race condition accessing struct ntfs_inode in ntfs_read_folio().
We have searched for something obvious in more recent commits but
couldn't find anything what looks related. Have we missed anything?
What do you think? Any idea?
Thanks
Dirk
[1]
Unable to handle kernel paging request at virtual address ffff8d623ef357f8
Mem abort info:
ESR = 0x0000000096000004
EC = 0x25: DABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
FSC = 0x04: level 0 translation fault
Data abort info:
ISV = 0, ISS = 0x00000004
CM = 0, WnR = 0
[ffff8d623ef357f8] address between user and kernel address ranges
Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
Modules linked in: ... ntfs3 ...
CPU: 3 PID: 9611 Comm: binder:529_A Tainted: G O 6.1.157 #1
Hardware name: ARM64 custom board
pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : ntfs_read_folio+0x24/0xe0 [ntfs3]
lr : filemap_read_folio+0x6c/0x15c
sp : ffffffc01c05bad0
x29: ffffffc01c05bad0 x28: 00000000fffffa00 x27: 0000000000080001
x26: 00000000ffffffff x25: ff00000000000000 x24: ffffff8d623ef4e8
x23: ffff8d623ef35800 x22: 0000000000000000 x21: ffffffc001591414
x20: fffffffe378c42c0 x19: fffffffe378c42c0 x18: ffffffc0109a0080
x17: 000000001b98ee9a x16: 000000001b98ee9a x15: ffffffc00158ed90
x14: 0000000000000007 x13: 000000000001d3a2 x12: ffffffce57fbe000
x11: 0000000000000001 x10: 0000000000000001 x9 : 0000000000000100
x8 : ffffff8d623ef4e7 x7 : 0000000000000000 x6 : 0000000000000000
x5 : ffffff8ca937808c x4 : ffffffc01c05bb50 x3 : 0000000006100cca
x2 : fffffffe378c42c0 x1 : fffffffe378c42c0 x0 : 0000000000000000
Call trace:
ntfs_read_folio+0x24/0xe0 [ntfs3]
filemap_read_folio+0x6c/0x15c
do_read_cache_folio+0x144/0x338
read_cache_page+0x1c/0x58
ntfs_fill_super+0xde8/0xf20 [ntfs3]
get_tree_bdev+0x1c4/0x258
ntfs_fs_get_tree+0x18/0x28 [ntfs3]
vfs_get_tree+0x48/0xfc
do_new_mount+0x154/0x36c
path_mount+0x270/0x4e4
__arm64_sys_mount+0x1b4/0x3dc
invoke_syscall+0x58/0x118
el0_svc_common+0xb4/0xf4
do_el0_svc+0x24/0x80
el0_svc+0x2c/0x90
el0t_64_sync_handler+0x68/0xb4
el0t_64_sync+0x1a4/0x1a8
Code: 910003fd f9400c28 aa0103f3 f9400117 (385f82e8)
---[ end trace 0000000000000000 ]---
Kernel panic - not syncing: Oops: Fatal exception
SMP: stopping secondary CPUs
[2]
static int ntfs_read_folio(struct file *file, struct folio *folio)
{
struct page *page = &folio->page;
int err;
struct address_space *mapping = page->mapping;
struct inode *inode = mapping->host;
struct ntfs_inode *ni = ntfs_i(inode);
if (is_resident(ni)) {
ni_lock(ni);
err = attr_data_read_resident(ni, page);
ni_unlock(ni);
if (err != E_NTFS_NONRESIDENT) {
unlock_page(page);
return err;
}
}
if (is_compressed(ni)) {
ni_lock(ni);
err = ni_readpage_cmpr(ni, page);
ni_unlock(ni);
return err;
}
/* Normal + sparse files. */
return mpage_read_folio(folio, ntfs_get_block);
}
[3]
000000000001e934 <ntfs_read_folio>:
1e934: d503233f paciasp
1e938: a9bc7bfd stp x29, x30, [sp, #-64]!
1e93c: f9000bf7 str x23, [sp, #16]
1e940: a90257f6 stp x22, x21, [sp, #32]
1e944: a9034ff4 stp x20, x19, [sp, #48]
1e948: 910003fd mov x29, sp
1e94c: f9400c28 ldr x8, [x1, #24]
1e950: aa0103f3 mov x19, x1
1e954: f9400117 ldr x23, [x8]
1e958: 385f82e8 ldurb w8, [x23, #-8]
[4]
struct ntfs_inode {
....
size_t ni_flags; // NI_FLAG_XXX
struct inode vfs_inode;
};