Offering: HULK hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB5WC2 CVE: NA
--------------------------------
Since we do not order the data, it is essential to write out zeroed data before the i_disksize update transaction is committed. Otherwise, stale data may left over in the last block, which could be exposed during the next expand truncate operation. After we write 0, we need to perform a sync operation. So we do filemap_write_and_wait_range in the new path.
Signed-off-by: Yongjian Sun sunyongjian1@huawei.com --- fs/ext4/inode.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index bbf0258062a7..51927bbe4350 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4318,10 +4318,10 @@ static int __ext4_block_zero_page_range(handle_t *handle, return err; }
-static int ext4_iomap_zero_range(struct inode *inode, - loff_t from, loff_t length) +static int ext4_iomap_zero_range(struct inode *inode, loff_t from, + loff_t length, bool *did_zero) { - return iomap_zero_range(inode, from, length, NULL, + return iomap_zero_range(inode, from, length, did_zero, &ext4_iomap_buffered_read_ops); }
@@ -4353,7 +4353,7 @@ static int ext4_block_zero_page_range(handle_t *handle, return dax_zero_range(inode, from, length, NULL, &ext4_iomap_ops); } else if (ext4_test_inode_state(inode, EXT4_STATE_BUFFERED_IOMAP)) { - return ext4_iomap_zero_range(inode, from, length); + return ext4_iomap_zero_range(inode, from, length, did_zero); } return __ext4_block_zero_page_range(handle, mapping, from, length, did_zero); @@ -4769,6 +4769,23 @@ int ext4_truncate(struct inode *inode) ext4_block_truncate_page(handle, mapping, inode->i_size, &zero_len);
+ /* + * inode with an iomap buffered I/O path does not order data, + * so it is necessary to write out zeroed data before the + * updating i_disksize transaction is committed. Otherwise, + * stale data may remain in the last block, which could be + * exposed during the next expand truncate operation. + */ + if (zero_len && ext4_test_inode_state(inode, + EXT4_STATE_BUFFERED_IOMAP)) { + loff_t zero_end = inode->i_size + zero_len; + + err = filemap_write_and_wait_range(mapping, + inode->i_size, zero_end - 1); + if (err) + goto out_stop; + } + if (zero_len && ext4_should_order_data(inode)) { err = ext4_jbd2_inode_add_write(handle, inode, inode->i_size, zero_len);