mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] ntfs: fix u16 truncation of restart-area length check
@ 2026-06-06 10:26 Bryam Vargas
  2026-06-06 12:38 ` Namjae Jeon
  2026-06-06 14:09 ` David Laight
  0 siblings, 2 replies; 3+ messages in thread
From: Bryam Vargas @ 2026-06-06 10:26 UTC (permalink / raw)
  To: Namjae Jeon, Hyunchul Lee; +Cc: linux-fsdevel, linux-kernel

ntfs_check_restart_area() validates that the $LogFile restart area and
its trailing log client record array fit within the system page size:

	u16 ra_ofs, ra_len, ca_ofs;
	...
	ra_len = ca_ofs + le16_to_cpu(ra->log_clients) *
			sizeof(struct log_client_record);
	if (ra_ofs + ra_len > le32_to_cpu(rp->system_page_size) || ...)
		return false;

ra_len is u16, but the right-hand side is computed in size_t
(sizeof(struct log_client_record) == 160). Both ca_ofs and log_clients
come straight from the on-disk restart area. With an on-disk
log_clients of 410 the product 410 * 160 = 65600; adding ca_ofs and
storing into the u16 ra_len truncates modulo 65536 (e.g. ca_ofs 64
gives ra_len 128), so the "fits in the page" check passes even though
the client array described by log_clients extends far beyond the page.

ntfs_check_log_client_array() then walks the array bounded only by the
on-disk log_clients count:

	cr = ca + idx;
	if (cr->prev_client != LOGFILE_NO_CLIENT) ...

For log_clients 410 it dereferences records up to ca + 409 * 160,
~64 KiB past the kvzalloc(system_page_size) restart-page buffer -- an
out-of-bounds read of attacker-controlled extent, reachable when a
crafted NTFS image is mounted (load_and_check_logfile() at mount time).
This is the in-kernel analogue of CVE-2022-30789, fixed in the ntfs-3g
userspace driver but never in this revived classic driver.

Compute the restart-area length in a u32 so the existing bounds check
rejects an over-large client array instead of being defeated by the
truncation.

Fixes: 1e9ea7e04472 ("Revert \"fs: Remove NTFS classic\"")
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
---
Reproduced on a KASAN build (in-kernel ntfs, fresh-boot slab) by
mounting a crafted image whose $LogFile restart area sets
log_clients=410 (ra_len truncates to a value that passes the
system-page-size check):

  BUG: KASAN: slab-out-of-bounds in ntfs_check_logfile+0x1e52/0x2460 [ntfs]
  Read of size 2 ... by task mount
    (cr->prev_client, with ntfs_check_log_client_array() inlined)
    ntfs_fill_super -> ntfs_iget -> ntfs_check_logfile
  Allocated by task ...: __kasan_kmalloc -- the kvzalloc(system_page_size)
  restart-page buffer (the OOB read lands at buffer_base + system_page_size)

With this patch the same image is rejected by the existing
ntfs_check_restart_area() bound (ra_len is no longer truncated), so
ntfs_check_log_client_array() is never reached, no OOB access occurs,
and the mount fails over to read-only. A clean image is unaffected.
Full A/B logs available on request.

 fs/ntfs/logfile.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
--- a/fs/ntfs/logfile.c
+++ b/fs/ntfs/logfile.c
@@ -132,7 +132,8 @@ static bool ntfs_check_restart_area(struct inode *vi, struct restart_page_header *rp)
 {
 	u64 file_size;
 	struct restart_area *ra;
-	u16 ra_ofs, ra_len, ca_ofs;
+	u16 ra_ofs, ca_ofs;
+	u32 ra_len;
 	u8 fs_bits;

 	ntfs_debug("Entering.");
--
2.43.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] ntfs: fix u16 truncation of restart-area length check
  2026-06-06 10:26 [PATCH] ntfs: fix u16 truncation of restart-area length check Bryam Vargas
@ 2026-06-06 12:38 ` Namjae Jeon
  2026-06-06 14:09 ` David Laight
  1 sibling, 0 replies; 3+ messages in thread
From: Namjae Jeon @ 2026-06-06 12:38 UTC (permalink / raw)
  To: Bryam Vargas; +Cc: Hyunchul Lee, linux-fsdevel, linux-kernel

Hi Bryam,

It seems your email client is using Quoted-Printable encoding instead
of plain text mode. As a result, tabs are converted to =09, and lines
are broken with =, which corrupts the patch and makes it impossible to
apply via git am.
This issue affects all of your recent ntfs patches, so none of them
can be applied.
Please configure your email client to send messages in plain text mode
without any encoding, or preferably, use git send-email to resend the
patches.

diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
--- a/fs/ntfs/logfile.c
+++ b/fs/ntfs/logfile.c
@@ -132,7 +132,8 @@ static bool ntfs_check_restart_area(struct inode *vi, s=
truct restart_page_header *rp)
 {
 =09u64 file_size;
 =09struct restart_area *ra;
-=09u16 ra_ofs, ra_len, ca_ofs;
+=09u16 ra_ofs, ca_ofs;
+=09u32 ra_len;
 =09u8 fs_bits;

 =09ntfs_debug("Entering.");
--
2.43.0

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] ntfs: fix u16 truncation of restart-area length check
  2026-06-06 10:26 [PATCH] ntfs: fix u16 truncation of restart-area length check Bryam Vargas
  2026-06-06 12:38 ` Namjae Jeon
@ 2026-06-06 14:09 ` David Laight
  1 sibling, 0 replies; 3+ messages in thread
From: David Laight @ 2026-06-06 14:09 UTC (permalink / raw)
  To: Bryam Vargas; +Cc: Namjae Jeon, Hyunchul Lee, linux-fsdevel, linux-kernel

On Sat, 06 Jun 2026 10:26:10 +0000
Bryam Vargas <hexlabsecurity@proton.me> wrote:

> ntfs_check_restart_area() validates that the $LogFile restart area and
> its trailing log client record array fit within the system page size:
> 
> 	u16 ra_ofs, ra_len, ca_ofs;
> 	...
> 	ra_len = ca_ofs + le16_to_cpu(ra->log_clients) *
> 			sizeof(struct log_client_record);
> 	if (ra_ofs + ra_len > le32_to_cpu(rp->system_page_size) || ...)
> 		return false;
> 
> ra_len is u16, but the right-hand side is computed in size_t
> (sizeof(struct log_client_record) == 160). Both ca_ofs and log_clients
> come straight from the on-disk restart area. With an on-disk
> log_clients of 410 the product 410 * 160 = 65600; adding ca_ofs and
> storing into the u16 ra_len truncates modulo 65536 (e.g. ca_ofs 64
> gives ra_len 128), so the "fits in the page" check passes even though
> the client array described by log_clients extends far beyond the page.
> 
> ntfs_check_log_client_array() then walks the array bounded only by the
> on-disk log_clients count:
> 
> 	cr = ca + idx;
> 	if (cr->prev_client != LOGFILE_NO_CLIENT) ...
> 
> For log_clients 410 it dereferences records up to ca + 409 * 160,
> ~64 KiB past the kvzalloc(system_page_size) restart-page buffer -- an
> out-of-bounds read of attacker-controlled extent, reachable when a
> crafted NTFS image is mounted (load_and_check_logfile() at mount time).
> This is the in-kernel analogue of CVE-2022-30789, fixed in the ntfs-3g
> userspace driver but never in this revived classic driver.
> 
> Compute the restart-area length in a u32 so the existing bounds check
> rejects an over-large client array instead of being defeated by the
> truncation.
> 
> Fixes: 1e9ea7e04472 ("Revert \"fs: Remove NTFS classic\"")
> Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
> ---
> Reproduced on a KASAN build (in-kernel ntfs, fresh-boot slab) by
> mounting a crafted image whose $LogFile restart area sets
> log_clients=410 (ra_len truncates to a value that passes the
> system-page-size check):
> 
>   BUG: KASAN: slab-out-of-bounds in ntfs_check_logfile+0x1e52/0x2460 [ntfs]
>   Read of size 2 ... by task mount
>     (cr->prev_client, with ntfs_check_log_client_array() inlined)
>     ntfs_fill_super -> ntfs_iget -> ntfs_check_logfile
>   Allocated by task ...: __kasan_kmalloc -- the kvzalloc(system_page_size)
>   restart-page buffer (the OOB read lands at buffer_base + system_page_size)
> 
> With this patch the same image is rejected by the existing
> ntfs_check_restart_area() bound (ra_len is no longer truncated), so
> ntfs_check_log_client_array() is never reached, no OOB access occurs,
> and the mount fails over to read-only. A clean image is unaffected.
> Full A/B logs available on request.
> 
>  fs/ntfs/logfile.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
> --- a/fs/ntfs/logfile.c
> +++ b/fs/ntfs/logfile.c
> @@ -132,7 +132,8 @@ static bool ntfs_check_restart_area(struct inode *vi, struct restart_page_header *rp)
>  {
>  	u64 file_size;
>  	struct restart_area *ra;
> -	u16 ra_ofs, ra_len, ca_ofs;
> +	u16 ra_ofs, ca_ofs;
> +	u32 ra_len;

I'd change all of them to u32 (unless you actually need the 'mod 64k').

>  	u8 fs_bits;

Similarly, but look up ilog2().

-- David

> 
>  	ntfs_debug("Entering.");
> --
> 2.43.0
> 
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-06-06 14:09 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-06 10:26 [PATCH] ntfs: fix u16 truncation of restart-area length check Bryam Vargas
2026-06-06 12:38 ` Namjae Jeon
2026-06-06 14:09 ` David Laight

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®