]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfs: Fix early put of sink folio in netfs_read_gaps()
authorDavid Howells <dhowells@redhat.com>
Tue, 12 May 2026 12:33:54 +0000 (13:33 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Jun 2026 15:46:27 +0000 (17:46 +0200)
[ Upstream commit 3e5dd91b87a8b1450217b56a336bee315f40da7d ]

Fix netfs_read_gaps() to release the sink page it uses after waiting for
the request to complete.  The way the sink page is used is that an
ITER_BVEC-class iterator is created that has the gaps from the target folio
at either end, but has the sink page tiled over the middle so that a single
read op can fill in both gaps.

The bug was found by KASAN detecting a UAF on the generic/075 xfstest in
the cifsd kernel thread that handles reception of data from the TCP socket:

 BUG: KASAN: use-after-free in _copy_to_iter+0x48a/0xa20
 Write of size 885 at addr ffff888107f92000 by task cifsd/1285
 CPU: 2 UID: 0 PID: 1285 Comm: cifsd Not tainted 7.0.0 #6 PREEMPT(lazy)
 Call Trace:
  dump_stack_lvl+0x5d/0x80
  print_report+0x17f/0x4f1
  kasan_report+0x100/0x1e0
  kasan_check_range+0x10f/0x1e0
  __asan_memcpy+0x3c/0x60
  _copy_to_iter+0x48a/0xa20
  __skb_datagram_iter+0x2c9/0x430
  skb_copy_datagram_iter+0x6e/0x160
  tcp_recvmsg_locked+0xce0/0x1130
  tcp_recvmsg+0xeb/0x300
  inet_recvmsg+0xcf/0x3a0
  sock_recvmsg+0xea/0x100
  cifs_readv_from_socket+0x3a6/0x4d0 [cifs]
  cifs_read_iter_from_socket+0xdd/0x130 [cifs]
  cifs_readv_receive+0xaad/0xb10 [cifs]
  cifs_demultiplex_thread+0x1148/0x1740 [cifs]
  kthread+0x1cf/0x210

Fixes: ee4cdf7ba857 ("netfs: Speed up buffered reading")
Reported-by: Steve French <sfrench@samba.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://patch.msgid.link/20260512123404.719402-18-dhowells@redhat.com
Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
cc: Paulo Alcantara <pc@manguebit.org>
cc: Matthew Wilcox <willy@infradead.org>
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/netfs/buffered_read.c

index 2dd2260352dbf8c1f6121e37165dffa2f4b97f0b..1c906035fef02f593e938524204f4e06f7bfe234 100644 (file)
@@ -525,14 +525,14 @@ static int netfs_read_gaps(struct file *file, struct folio *folio)
 
        netfs_read_to_pagecache(rreq);
 
-       if (sink)
-               folio_put(sink);
-
        ret = netfs_wait_for_read(rreq);
        if (ret == 0) {
                flush_dcache_folio(folio);
                folio_mark_uptodate(folio);
        }
+
+       if (sink)
+               folio_put(sink);
        folio_unlock(folio);
        netfs_put_request(rreq, false, netfs_rreq_trace_put_return);
        return ret < 0 ? ret : 0;