* [PATCH] fuse: fix copy_file_range reply handling race
@ 2026-10-13 9:04 Chengfeng Ye
0 siblings, 0 replies; only message in thread
From: Chengfeng Ye @ 2026-10-13 9:04 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: fuse-devel, linux-kernel, Chengfeng Ye, stable
__fuse_copy_file_range() selects its request opcode and output buffer
using fc->no_copy_file_range_64, then reads the flag again to handle the
reply. Copies to different destination inodes can run concurrently on
the same connection, so the flag may change while a request is pending.
For example, task A submits FUSE_COPY_FILE_RANGE_64 and waits for its
reply. Task B submits the same opcode, receives -ENOSYS and sets
no_copy_file_range_64. When A receives a successful reply, it reads the
uninitialized outarg.size instead of outarg_64.bytes_copied. This can
produce an incorrect return value, page cache invalidation range and
inode size update, and disclose stack contents if automatic stack
initialization is disabled.
If A also receives -ENOSYS, it instead mistakes that reply for rejection
of the legacy opcode and sets no_copy_file_range, skipping the legacy
fallback and unnecessarily disabling copy offload for the connection.
KCSAN reported the conflicting accesses:
BUG: KCSAN: data-race in __fuse_copy_file_range / __fuse_copy_file_range
read to 0xffff8881014a4d4d of 1 bytes by task 123 on cpu 4:
__fuse_copy_file_range+0x1a7/0x6e0
fuse_copy_file_range+0x54/0xd0
vfs_copy_file_range+0x290/0x9d0
__do_sys_copy_file_range+0x10f/0x2f0
write to 0xffff8881014a4d4d of 8 bytes by task 119 on cpu 0:
__fuse_copy_file_range+0x633/0x6e0
fuse_copy_file_range+0x54/0xd0
vfs_copy_file_range+0x290/0x9d0
__do_sys_copy_file_range+0x10f/0x2f0
The bug can lead to leak kernel base address for KASLR bypass, the
corresponding reproducer can be provided per request.
Use args.opcode for both -ENOSYS handling and output buffer selection.
It records the opcode actually sent and is updated on fallback, keeping
each reply tied to its request regardless of concurrent flag updates.
Fixes: 7a37f55af7af ("fuse: add COPY_FILE_RANGE_64 that allows large copies")
Cc: stable@vger.kernel.org
Assisted-by: GPT-6 Astra
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
---
fs/fuse/file.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 9a36d0329e221..939391b48cc9b 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -3019,7 +3019,7 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in,
}
err = fuse_simple_request(fm, &args);
if (err == -ENOSYS) {
- if (fc->no_copy_file_range_64) {
+ if (args.opcode == FUSE_COPY_FILE_RANGE) {
fc->no_copy_file_range = 1;
err = -EOPNOTSUPP;
} else {
@@ -3030,7 +3030,7 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in,
if (err)
goto out;
- bytes_copied = fc->no_copy_file_range_64 ?
+ bytes_copied = args.opcode == FUSE_COPY_FILE_RANGE ?
outarg.size : outarg_64.bytes_copied;
if (bytes_copied > len) {
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-13 9:04 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13 9:04 [PATCH] fuse: fix copy_file_range reply handling race Chengfeng Ye
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.