Skip to content

Commit 03dec28

Browse files
Miklos Szeredigregkh
authored andcommitted
copy_file_range: limit size if in compat mode
[ Upstream commit f8f59a2c05dc16d19432e3154a9ac7bc385f4b92 ] 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 <[email protected]> Closes: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Miklos Szeredi <[email protected]> Link: https://lore.kernel.org/[email protected] Reviewed-by: Amir Goldstein <[email protected]> Signed-off-by: Christian Brauner <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 9d0ac18 commit 03dec28

1 file changed

Lines changed: 9 additions & 5 deletions

File tree

fs/read_write.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,13 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
15761576
if (len == 0)
15771577
return 0;
15781578

1579+
/*
1580+
* Make sure return value doesn't overflow in 32bit compat mode. Also
1581+
* limit the size for all cases except when calling ->copy_file_range().
1582+
*/
1583+
if (splice || !file_out->f_op->copy_file_range || in_compat_syscall())
1584+
len = min_t(size_t, MAX_RW_COUNT, len);
1585+
15791586
file_start_write(file_out);
15801587

15811588
/*
@@ -1589,9 +1596,7 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
15891596
len, flags);
15901597
} else if (!splice && file_in->f_op->remap_file_range && samesb) {
15911598
ret = file_in->f_op->remap_file_range(file_in, pos_in,
1592-
file_out, pos_out,
1593-
min_t(loff_t, MAX_RW_COUNT, len),
1594-
REMAP_FILE_CAN_SHORTEN);
1599+
file_out, pos_out, len, REMAP_FILE_CAN_SHORTEN);
15951600
/* fallback to splice */
15961601
if (ret <= 0)
15971602
splice = true;
@@ -1624,8 +1629,7 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
16241629
* to splicing from input file, while file_start_write() is held on
16251630
* the output file on a different sb.
16261631
*/
1627-
ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out,
1628-
min_t(size_t, len, MAX_RW_COUNT), 0);
1632+
ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out, len, 0);
16291633
done:
16301634
if (ret > 0) {
16311635
fsnotify_access(file_in);

0 commit comments

Comments
 (0)