mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
copy_file_range: limit size if in compat mode
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@redhat.com> Closes: https://lore.kernel.org/all/lhuh5ynl8z5.fsf@oldenburg.str.redhat.com/ Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Link: https://lore.kernel.org/20250813151107.99856-1-mszeredi@redhat.com Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
committed by
Christian Brauner
parent
15769d9478
commit
f8f59a2c05
@@ -1576,6 +1576,13 @@ 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. Also
|
||||
* limit the size for all cases except when calling ->copy_file_range().
|
||||
*/
|
||||
if (splice || !file_out->f_op->copy_file_range || in_compat_syscall())
|
||||
len = min_t(size_t, MAX_RW_COUNT, len);
|
||||
|
||||
file_start_write(file_out);
|
||||
|
||||
/*
|
||||
@@ -1589,9 +1596,7 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
|
||||
len, flags);
|
||||
} else if (!splice && file_in->f_op->remap_file_range && samesb) {
|
||||
ret = file_in->f_op->remap_file_range(file_in, pos_in,
|
||||
file_out, pos_out,
|
||||
min_t(loff_t, MAX_RW_COUNT, len),
|
||||
REMAP_FILE_CAN_SHORTEN);
|
||||
file_out, pos_out, len, REMAP_FILE_CAN_SHORTEN);
|
||||
/* fallback to splice */
|
||||
if (ret <= 0)
|
||||
splice = true;
|
||||
@@ -1624,8 +1629,7 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
|
||||
* to splicing from input file, while file_start_write() is held on
|
||||
* the output file on a different sb.
|
||||
*/
|
||||
ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out,
|
||||
min_t(size_t, len, MAX_RW_COUNT), 0);
|
||||
ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out, len, 0);
|
||||
done:
|
||||
if (ret > 0) {
|
||||
fsnotify_access(file_in);
|
||||
|
||||
Reference in New Issue
Block a user