linux-stable/fs/netfs
David Howells f08c80af3c netfs: Fix unbuffered write error handling
[ Upstream commit a3de58b12c ]

If all the subrequests in an unbuffered write stream fail, the subrequest
collector doesn't update the stream->transferred value and it retains its
initial LONG_MAX value.  Unfortunately, if all active streams fail, then we
take the smallest value of { LONG_MAX, LONG_MAX, ... } as the value to set
in wreq->transferred - which is then returned from ->write_iter().

LONG_MAX was chosen as the initial value so that all the streams can be
quickly assessed by taking the smallest value of all stream->transferred -
but this only works if we've set any of them.

Fix this by adding a flag to indicate whether the value in
stream->transferred is valid and checking that when we integrate the
values.  stream->transferred can then be initialised to zero.

This was found by running the generic/750 xfstest against cifs with
cache=none.  It splices data to the target file.  Once (if) it has used up
all the available scratch space, the writes start failing with ENOSPC.
This causes ->write_iter() to fail.  However, it was returning
wreq->transferred, i.e. LONG_MAX, rather than an error (because it thought
the amount transferred was non-zero) and iter_file_splice_write() would
then try to clean up that amount of pipe bufferage - leading to an oops
when it overran.  The kernel log showed:

    CIFS: VFS: Send error in write = -28

followed by:

    BUG: kernel NULL pointer dereference, address: 0000000000000008

with:

    RIP: 0010:iter_file_splice_write+0x3a4/0x520
    do_splice+0x197/0x4e0

or:

    RIP: 0010:pipe_buf_release (include/linux/pipe_fs_i.h:282)
    iter_file_splice_write (fs/splice.c:755)

Also put a warning check into splice to announce if ->write_iter() returned
that it had written more than it was asked to.

Fixes: 288ace2f57 ("netfs: New writeback implementation")
Reported-by: Xiaoli Feng <fengxiaoli0714@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220445
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/915443.1755207950@warthog.procyon.org.uk
cc: Paulo Alcantara <pc@manguebit.org>
cc: Steve French <sfrench@samba.org>
cc: Shyam Prasad N <sprasad@microsoft.com>
cc: netfs@lists.linux.dev
cc: linux-cifs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
cc: stable@vger.kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
[ Dropped read_collect.c hunk ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-08-28 16:31:04 +02:00
..
buffered_read.c
buffered_write.c netfs: Fix i_size updating 2025-07-10 16:04:52 +02:00
direct_read.c netfs: Fix netfs_unbuffered_read() to return ssize_t rather than int 2025-04-10 14:39:31 +02:00
direct_write.c netfs: Fix i_size updating 2025-07-10 16:04:52 +02:00
fscache_cache.c
fscache_cookie.c
fscache_internal.h
fscache_io.c
fscache_main.c
fscache_proc.c
fscache_stats.c
fscache_volume.c
internal.h
iterator.c
Kconfig
locking.c
main.c netfs: Only create /proc/fs/netfs with CONFIG_PROC_FS 2025-05-02 07:59:26 +02:00
Makefile
misc.c
objects.c
read_collect.c fs/netfs/read_collect: add to next->prev_donated 2025-03-22 12:54:28 -07:00
read_pgpriv2.c
read_retry.c
stats.c
write_collect.c netfs: Fix unbuffered write error handling 2025-08-28 16:31:04 +02:00
write_issue.c netfs: Fix unbuffered write error handling 2025-08-28 16:31:04 +02:00