Re: [BUG/RFC] ntfs: crafted image triggers WARN_ON in ntfs_map_runlist_nolock()

From: Namjae Jeon

Date: Wed Jul 01 2026 - 21:37:35 EST


On Thu, Jul 2, 2026 at 8:36 AM Namjae Jeon <linkinjeon@xxxxxxxxxx> wrote:
>
> On Thu, Jul 2, 2026 at 7:12 AM 이상호 <kudo3228@xxxxxxxxx> wrote:
> >
> > Hi,
> Hi Sangho,
> >
> > I found a crafted NTFS image that triggers the following warning during
> > mount-time NTFS logfile handling:
> >
> > WARNING: fs/ntfs/attrib.c:177 at ntfs_map_runlist_nolock+0x1275/0x17b0
> >
> > The observed stack is:
> >
> > ntfs_map_runlist_nolock
> > ntfs_empty_logfile
> > load_system_files
> > ntfs_fill_super
> > get_tree_bdev_flags
> > vfs_get_tree
> > do_new_mount
> > __se_sys_mount
> >
> > The warning site is:
> >
> > fs/ntfs/attrib.c:177
> > WARN_ON(!ctx->attr->non_resident);
> >
> > The caller path reaches this through:
> >
> > fs/ntfs/logfile.c:677
> > err = ntfs_map_runlist_nolock(log_ni, vcn, NULL);
> >
> > The current hypothesis is that a malformed image reaches the $LogFile cleanup
> > path and causes ntfs_map_runlist_nolock() to find a resident attribute where it
> > expects a non-resident one. Since the input is a crafted filesystem image, this
> > looks like it should be rejected through an ordinary mount error path rather
> > than tripping a kernel WARN_ON().
> >
> > The crash was found with syzkaller/SyzDirect on a recent local mainline build.
> > syz-repro reproduced the warning during minimization and reduced the syscall
> > sequence to syz_mount_image$ntfs. I also extracted the crashing program from
> > the syzkaller log and generated a standalone C reproducer from it. The generated
> > C reproducer compiles locally.
> >
> > I have not yet confirmed whether this has impact beyond a mount-time warning
> > from a crafted NTFS image. I can provide the full syzkaller/C reproducer and
> > kernel config if useful.
> I will check it and share the patch with you to get your confirmation.
> Thanks.
Please confirm if the attached patch fixes this issue.
thanks!
From 9969f7b5cba26d043b19e35c4a9759ae6cf7a51f Mon Sep 17 00:00:00 2001
From: Namjae Jeon <linkinjeon@xxxxxxxxxx>
Date: Thu, 2 Jul 2026 10:31:44 +0900
Subject: [PATCH] ntfs: fix WARN_ON for resident attribute in
ntfs_map_runlist_nolock()

When ntfs_map_runlist_nolock() needs to look up the attribute extent
containing a target VCN (ctx_needs_reset == true), it calls
ntfs_attr_lookup() and then expects the result to be a non-resident
attribute, since only non-resident attributes have a mapping pairs
array to decompress.

A crafted NTFS image can place a resident attribute where a non-resident
one is expected, causing ntfs_attr_lookup() to succeed but return a
resident attribute record. Previously this was caught only by a
WARN_ON(), which does not stop execution. The code then falls through to
read a->data.non_resident.highest_vcn from what is actually a resident
attribute, accessing the wrong union member and corrupting the VCN range
check.

The caller path triggering this warning during mount is:

ntfs_map_runlist_nolock
ntfs_empty_logfile
load_system_files
ntfs_fill_super

In this path ctx is NULL, so ntfs_map_runlist_nolock() allocates a
temporary search context internally and sets ctx_needs_reset = true.
The existing resident-attribute guard in the ctx != NULL branch already
returns -EIO silently for the same condition; make the ctx_needs_reset
path consistent by replacing the WARN_ON() with the same -EIO error
return.

This causes the crafted image to be rejected with a mount error instead
of triggering a kernel warning.

Reported-by: Sangho Lee <kudo3228@xxxxxxxxx>
Signed-off-by: Namjae Jeon <linkinjeon@xxxxxxxxxx>
---
fs/ntfs/attrib.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index a99b84751eb1..e5e3bc03ad49 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -175,7 +175,10 @@ int ntfs_map_runlist_nolock(struct ntfs_inode *ni, s64 vcn, struct ntfs_attr_sea
err = -EIO;
goto err_out;
}
- WARN_ON(!ctx->attr->non_resident);
+ if (unlikely(!ctx->attr->non_resident)) {
+ err = -EIO;
+ goto err_out;
+ }
}
a = ctx->attr;
/*
--
2.34.1