lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240903054808.126799-1-sunjunchao2870@gmail.com>
Date: Tue,  3 Sep 2024 13:48:08 +0800
From: Julian Sun <sunjunchao2870@...il.com>
To: linux-xfs@...r.kernel.org,
	linux-fsdevel@...r.kernel.org,
	linux-ext4@...r.kernel.org
Cc: tytso@....edu,
	adilger.kernel@...ger.ca,
	jack@...e.cz,
	brauner@...nel.org,
	djwong@...nel.org,
	hch@....de,
	Julian Sun <sunjunchao2870@...il.com>,
	syzbot+296b1c84b9cbf306e5a0@...kaller.appspotmail.com
Subject: [PATCH] iomap: clean preallocated blocks in iomap_end() when 0 bytes was written.

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@...kaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=296b1c84b9cbf306e5a0
Fixes: f4b896c213f0 ("iomap: add the new iomap_iter model")
Signed-off-by: Julian Sun <sunjunchao2870@...il.com>
---
 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


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ