Offering: HULK
hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9DN5Z
--------------------------------
Since commit 7f6416dcd4a3f ("ext4: implement writeback iomap path"), the
order mode is removed in iomap framework, which lets ext4_mb_clear_bb()
free data blocks immediately. It may cause stale data read from truncated
file in power-cut case. Following is details:
P1 P2
vfs_truncate(file A)
ext4_setattr
EXT4_I(inode)->i_disksize = attr->ia_size // record in journal
ext4_truncate
ext4_mb_clear_bb
mb_free_blocks // free block i
vfs_write(file B) // get block i and writeback
>> powercut <<
In the next mount, inode size and extent tree is stale(before truncated),
the content in block i is file B.
Fix the problem by tracking free data blocks in journal for
iomap/non-writeback case.
Fixes: 7f6416dcd4a3 ("ext4: implement writeback iomap path")
Signed-off-by: Zhihao Cheng <chengzhihao1(a)huawei.com>
---
fs/ext4/ext4_jbd2.c | 9 ++-------
fs/ext4/ext4_jbd2.h | 7 +++++++
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index 94c8073b49e7..cac0eb5068d3 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -11,18 +11,13 @@ int ext4_inode_journal_mode(struct inode *inode)
{
if (EXT4_JOURNAL(inode) == NULL)
return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
- /*
- * Ordered mode is no longer needed for the inode that use the
- * iomap path, always use writeback mode.
- */
- if (ext4_test_inode_state(inode, EXT4_STATE_BUFFERED_IOMAP))
- return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
/* We do not support data journalling with delayed allocation */
if (!S_ISREG(inode->i_mode) ||
ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||
test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
(ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
- !test_opt(inode->i_sb, DELALLOC))) {
+ !test_opt(inode->i_sb, DELALLOC) &&
+ !ext4_test_inode_state(inode, EXT4_STATE_BUFFERED_IOMAP))) {
/* We do not support data journalling for encrypted data */
if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode))
return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 0c77697d5e90..c52d1caf6622 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -467,6 +467,13 @@ static inline int ext4_should_journal_data(struct inode *inode)
static inline int ext4_should_order_data(struct inode *inode)
{
+ /*
+ * Ordered mode is no longer needed for the inode that use the
+ * iomap path, always use writeback mode.
+ */
+ if (ext4_test_inode_state(inode, EXT4_STATE_BUFFERED_IOMAP))
+ return 0; /* writeback */
+
return ext4_inode_journal_mode(inode) & EXT4_INODE_ORDERED_DATA_MODE;
}
--
2.31.1
From: Jan Kara <jack(a)suse.cz>
stable inclusion
from stable-v5.10.222
commit 145faa3d03688cbb7bbaaecbd84c01539852942c
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAD6H2
CVE: CVE-2024-42102
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 30139c702048f1097342a31302cbd3d478f50c63 upstream.
Patch series "mm: Avoid possible overflows in dirty throttling".
Dirty throttling logic assumes dirty limits in page units fit into
32-bits. This patch series makes sure this is true (see patch 2/2 for
more details).
This patch (of 2):
This reverts commit 9319b647902cbd5cc884ac08a8a6d54ce111fc78.
The commit is broken in several ways. Firstly, the removed (u64) cast
from the multiplication will introduce a multiplication overflow on 32-bit
archs if wb_thresh * bg_thresh >= 1<<32 (which is actually common - the
default settings with 4GB of RAM will trigger this). Secondly, the
div64_u64() is unnecessarily expensive on 32-bit archs. We have
div64_ul() in case we want to be safe & cheap. Thirdly, if dirty
thresholds are larger than 1<<32 pages, then dirty balancing is going to
blow up in many other spectacular ways anyway so trying to fix one
possible overflow is just moot.
Link: https://lkml.kernel.org/r/20240621144017.30993-1-jack@suse.cz
Link: https://lkml.kernel.org/r/20240621144246.11148-1-jack@suse.cz
Fixes: 9319b647902c ("mm/writeback: fix possible divide-by-zero in wb_dirty_limits(), again")
Signed-off-by: Jan Kara <jack(a)suse.cz>
Reviewed-By: Zach O'Keefe <zokeefe(a)google.com>
Cc: <stable(a)vger.kernel.org>
Signed-off-by: Andrew Morton <akpm(a)linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Kaixiong Yu <yukaixiong(a)huawei.com>
---
mm/page-writeback.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 0d7cc65c6367..31bc5904bbf8 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1541,7 +1541,7 @@ static inline void wb_dirty_limits(struct dirty_throttle_control *dtc)
*/
dtc->wb_thresh = __wb_calc_thresh(dtc);
dtc->wb_bg_thresh = dtc->thresh ?
- div64_u64(dtc->wb_thresh * dtc->bg_thresh, dtc->thresh) : 0;
+ div_u64((u64)dtc->wb_thresh * dtc->bg_thresh, dtc->thresh) : 0;
/*
* In order to avoid the stacked BDI deadlock we need
--
2.25.1