Commit 19c20c35 authored by Zizhi Wo's avatar Zizhi Wo
Browse files

xfs: Fix data overflow in xfs_mod_fdblocks()

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB7V02



--------------------------------

If the xfs reserve block related ioctl takes a large input value, the input
reserved size is still assigned to mp->m_resblks in xfs_reserve_blocks()
even if the requested size is larger than the total free size in the
filesystem. This is because the subsequent xfs_mod_fdblocks() will handle
the adjustment.

However, in the current code, xfs_mod_fdblocks() calculates mp->m_resblks
- mp->m_resblks_avail and casts the result to a long long type, while both
mp->m_resblks and mp->m_resblks_avail are of type unsigned long long. If
the difference between these two values is very large, and the most
significant bit (MSB) is set to 1 (indicating a large unsigned value), the
result of the cast becomes a large negative value. This causes
mp->m_fdblocks to be updated to a very large value. As a result, xfs will
incorrectly determine that there is always free space during foreground
writes, while background writebacks may fail due to lack of space.

Modify the relevant data types in xfs_mod_fdblocks() to address this issue.

Fixes: 0d485ada ("xfs: use generic percpu counters for free block counter")
Signed-off-by: default avatarZizhi Wo <wozizhi@huawei.com>
parent 930fc4e0
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1259,8 +1259,8 @@ xfs_mod_fdblocks(
	bool			rsvd)
{
	int64_t			lcounter;
	long long		res_used;
	s32			batch;
	uint64_t		res_used;
	uint64_t		set_aside;

	if (delta > 0) {
@@ -1274,7 +1274,7 @@ xfs_mod_fdblocks(
		}

		spin_lock(&mp->m_sb_lock);
		res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
		res_used = mp->m_resblks - mp->m_resblks_avail;

		if (res_used > delta) {
			mp->m_resblks_avail += delta;