diff options
author | Yuezhang Mo <Yuezhang.Mo@sony.com> | 2024-10-17 03:25:06 +0200 |
---|---|---|
committer | Namjae Jeon <linkinjeon@kernel.org> | 2024-11-25 09:08:21 +0100 |
commit | 2e94e5bb94a3e641a25716a560bf474225fda83c (patch) | |
tree | 64be23a3cde0912aab6fdd267c208e9dc22d6cbb /fs/exfat | |
parent | exfat: fix uninit-value in __exfat_get_dentry_set (diff) | |
download | linux-2e94e5bb94a3e641a25716a560bf474225fda83c.tar.xz linux-2e94e5bb94a3e641a25716a560bf474225fda83c.zip |
exfat: fix file being changed by unaligned direct write
Unaligned direct writes are invalid and should return an error
without making any changes, rather than extending ->valid_size
and then returning an error. Therefore, alignment checking is
required before extending ->valid_size.
Fixes: 11a347fb6cef ("exfat: change to get file size from DataLength")
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Co-developed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Diffstat (limited to 'fs/exfat')
-rw-r--r-- | fs/exfat/file.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/exfat/file.c b/fs/exfat/file.c index a25d7eb789f4..fb38769c3e39 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -584,6 +584,16 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) if (ret < 0) goto unlock; + if (iocb->ki_flags & IOCB_DIRECT) { + unsigned long align = pos | iov_iter_alignment(iter); + + if (!IS_ALIGNED(align, i_blocksize(inode)) && + !IS_ALIGNED(align, bdev_logical_block_size(inode->i_sb->s_bdev))) { + ret = -EINVAL; + goto unlock; + } + } + if (pos > valid_size) { ret = exfat_extend_valid_size(file, pos); if (ret < 0 && ret != -ENOSPC) { |