[PATCH] iomap: clean preallocated blocks in iomap_end() when 0 bytes was written.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi, all.

Recently, syzbot reported a issue as following:

WARNING: CPU: 1 PID: 5222 at fs/iomap/buffered-io.c:727 __iomap_write_begin fs/iomap/buffered-io.c:727 [inline]
WARNING: CPU: 1 PID: 5222 at fs/iomap/buffered-io.c:727 iomap_write_begin+0x13f0/0x16f0 fs/iomap/buffered-io.c:830
CPU: 1 UID: 0 PID: 5222 Comm: syz-executor247 Not tainted 6.11.0-rc2-syzkaller-00111-gee9a43b7cfe2 #0
RIP: 0010:__iomap_write_begin fs/iomap/buffered-io.c:727 [inline]
RIP: 0010:iomap_write_begin+0x13f0/0x16f0 fs/iomap/buffered-io.c:830
Call Trace:
 <TASK>
 iomap_unshare_iter fs/iomap/buffered-io.c:1351 [inline]
 iomap_file_unshare+0x460/0x780 fs/iomap/buffered-io.c:1391
 xfs_reflink_unshare+0x173/0x5f0 fs/xfs/xfs_reflink.c:1681
 xfs_file_fallocate+0x6be/0xa50 fs/xfs/xfs_file.c:997
 vfs_fallocate+0x553/0x6c0 fs/open.c:334
 ksys_fallocate fs/open.c:357 [inline]
 __do_sys_fallocate fs/open.c:365 [inline]
 __se_sys_fallocate fs/open.c:363 [inline]
 __x64_sys_fallocate+0xbd/0x110 fs/open.c:363
 do_syscall_x64 arch/x86/entry/common.c:52 [inline]
 do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f2d716a6899

syzbot constructed the following scenario: syzbot called the write()
system call, passed an illegal pointer, and attempted to write 0x1017
bytes, resulting in 0 bytes written and returning EFAULT to user
space. Then, it called the write() system call again, passed another
illegal pointer, and attempted to write 0xfea7 bytes, resulting in
0xe00 bytes written. Finally called copy_file_range() sys call and
fallocate() sys call with FALLOC_FL_UNSHARE_RANGE flag.

What happened here is: during the first write, xfs_buffered_write_iomap_begin()
used preallocated 512 blocks, inserted an extent with a length of 512 and
reserved 512 blocks in the quota, with the iomap length being 1M.
However, when the write failed(0 byte was written), only 0x1017 bytes were
passed to iomap_end() instead of the preallocated 1M bytes/512 blocks.
This caused only 3 blocks to be unreserved for the quota in iomap_end(),
instead of 512, and the corresponding extent information also only removed
3 blocks instead of 512.

As a result, during the second write, the iomap length was 3 blocks
instead of the expected 512 blocks, which ultimately triggered the
issue reported by syzbot in the fallocate() system call.

To resolve this issue, when a write fails, we should pass
iomap.length to iomap_end() to indicate it to clean up all
the resources, rather than just the length requested by the user.

This patch has already passed xfstests -g quick test on both xfs
and ext4 without causing additional failures.

Reported-and-tested-by: syzbot+296b1c84b9cbf306e5a0@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=296b1c84b9cbf306e5a0
Fixes: f4b896c213f0 ("iomap: add the new iomap_iter model")
Signed-off-by: Julian Sun <sunjunchao2870@xxxxxxxxx>
---
 fs/iomap/iter.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/iomap/iter.c b/fs/iomap/iter.c
index 79a0614eaab7..6e3f6109cac5 100644
--- a/fs/iomap/iter.c
+++ b/fs/iomap/iter.c
@@ -76,7 +76,8 @@ int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops)
 	int ret;
 
 	if (iter->iomap.length && ops->iomap_end) {
-		ret = ops->iomap_end(iter->inode, iter->pos, iomap_length(iter),
+		ret = ops->iomap_end(iter->inode, iter->pos,
+				iter->processed > 0 ? iomap_length(iter) : iter->iomap.length,
 				iter->processed > 0 ? iter->processed : 0,
 				iter->flags, &iter->iomap);
 		if (ret < 0 && !iter->processed)
-- 
2.39.2





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux