]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
exfat: fix file being changed by unaligned direct write
authorYuezhang Mo <Yuezhang.Mo@sony.com>
Thu, 17 Oct 2024 01:25:06 +0000 (09:25 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Dec 2024 12:53:58 +0000 (13:53 +0100)
[ Upstream commit 2e94e5bb94a3e641a25716a560bf474225fda83c ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/exfat/file.c

index 64c31867bc7615b55f8d9c524b8fb13a9b99f706..525c3ad411ea33d8c7a4509f54e5853fe26ee12e 100644 (file)
@@ -578,6 +578,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_file_zeroed_range(file, valid_size, pos);
                if (ret < 0 && ret != -ENOSPC) {