On Tue, Aug 5, 2025 at 8:30 PM Miklos Szeredi <mszeredi@xxxxxxxxxx> wrote: > > If the process runs in 32-bit compat mode, copy_file_range results can be > in the in-band error range. In this case limit copy length to MAX_RW_COUNT > to prevent a signed overflow. > > Reported-by: Florian Weimer <fweimer@xxxxxxxxxx> > Closes: https://lore.kernel.org/all/lhuh5ynl8z5.fsf@xxxxxxxxxxxxxxxxxxxxxxxx/ > Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxxxxx> > --- > fs/read_write.c | 4 ++++ > 1 file changed, 4 insertions(+) > > diff --git a/fs/read_write.c b/fs/read_write.c > index 0ef70e128c4a..e2ccc44d96e6 100644 > --- a/fs/read_write.c > +++ b/fs/read_write.c > @@ -1576,6 +1576,10 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, > if (len == 0) > return 0; > > + /* Make sure return value doesn't overflow in 32bit compat mode */ > + if (in_compat_syscall() && len > MAX_RW_COUNT) > + len = MAX_RW_COUNT; > + 1. Note that generic_copy_file_checks() can already shorten len, so maybe this should also be done there?? not sure.. 2. Both ->remap_file_range() and splice cases already trim to MAX_RW_COUNT so the only remaining case for len > MAX_RW_COUNT are filesystems that implement ->copy_file_range() and actually support copying ranges larger than 2MB (don't know if they actually exist) IOW, if we do: if (splice || !file_out->f_op->copy_file_range || in_compat_syscall()) len = min_t(loff_t, MAX_RW_COUNT, len); We will not need to repeat the same trim of len in 3 different places in this function. Thanks, Amir.