mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
exfat: advance valid_size to EOF for append writes
For an append write, the write position is recalculated by
generic_write_checks(). Therefore, the write position must be obtained
after generic_write_checks() returns.
Using the original write position to advance valid_size may cause the
valid_size update to be skipped, potentially exposing stale data.
Also move the truncate_pagecache() check below the recalculated
position, so that pos is never read before it is assigned.
Fixes: 11a347fb6c ("exfat: change to get file size from DataLength")
Cc: stable@vger.kernel.org
Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
1306c1e6b0
commit
b70ab40750
|
|
@ -854,8 +854,7 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
|
|||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
loff_t pos = iocb->ki_pos;
|
||||
loff_t valid_size;
|
||||
loff_t pos, valid_size;
|
||||
int err;
|
||||
|
||||
if (unlikely(exfat_forced_shutdown(inode->i_sb)))
|
||||
|
|
@ -863,11 +862,6 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
|
|||
|
||||
inode_lock(inode);
|
||||
|
||||
if (pos > i_size_read(inode))
|
||||
truncate_pagecache(inode, i_size_read(inode));
|
||||
|
||||
valid_size = ei->valid_size;
|
||||
|
||||
ret = generic_write_checks(iocb, iter);
|
||||
if (ret <= 0)
|
||||
goto unlock;
|
||||
|
|
@ -878,6 +872,11 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
pos = iocb->ki_pos;
|
||||
if (pos > i_size_read(inode))
|
||||
truncate_pagecache(inode, i_size_read(inode));
|
||||
|
||||
valid_size = ei->valid_size;
|
||||
if (pos > valid_size) {
|
||||
ret = exfat_extend_valid_size(inode, pos);
|
||||
if (ret < 0 && ret != -ENOSPC) {
|
||||
|
|
@ -887,6 +886,8 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
|
|||
}
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
|
||||
pos = valid_size;
|
||||
}
|
||||
|
||||
if (iocb->ki_flags & IOCB_DIRECT)
|
||||
|
|
@ -899,9 +900,6 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
|
|||
|
||||
inode_unlock(inode);
|
||||
|
||||
if (pos > valid_size)
|
||||
pos = valid_size;
|
||||
|
||||
if (iocb->ki_pos > pos) {
|
||||
ssize_t err = generic_write_sync(iocb, iocb->ki_pos - pos);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user