diff mbox series

[v2] exfat: fix file being changed by unaligned direct write

Message ID PUZPR04MB631627C059803D3D4609D1C581592@PUZPR04MB6316.apcprd04.prod.outlook.com (mailing list archive)
State New
Headers show
Series [v2] exfat: fix file being changed by unaligned direct write | expand

Commit Message

Yuezhang.Mo@sony.com Nov. 12, 2024, 3:59 a.m. UTC
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>
---

v2 changes:
  - Fix alignment checking for devices with logical sector size
    smaller than physical sector size.

 fs/exfat/file.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Namjae Jeon Nov. 13, 2024, 12:54 p.m. UTC | #1
On Tue, Nov 12, 2024 at 1:00 PM Yuezhang.Mo@sony.com
<Yuezhang.Mo@sony.com> wrote:
>
> 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>
Applied it to #dev.
Thanks!
diff mbox series

Patch

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) {