exfat: fix zero the unwritten part for dio read
authorYuezhang Mo <Yuezhang.Mo@sony.com>
Thu, 18 Jan 2024 01:52:52 +0000 (09:52 +0800)
committerNamjae Jeon <linkinjeon@kernel.org>
Thu, 18 Jan 2024 14:01:51 +0000 (23:01 +0900)
For dio read, bio will be leave in flight when a successful partial
aio read have been setup, blockdev_direct_IO() will return
-EIOCBQUEUED. In the case, iter->iov_offset will be not advanced,
the oops reported by syzbot will occur if revert iter->iov_offset
with iov_iter_revert(). The unwritten part had been zeroed by aio
read, so there is no need to zero it in dio read.

Reported-by: syzbot+fd404f6b03a58e8bc403@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=fd404f6b03a58e8bc403
Fixes: 11a347fb6cef ("exfat: change to get file size from DataLength")
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
fs/exfat/inode.c

index 522edcbb2ce4d17a7f219e6016bff31f5d466fdd..0687f952956c34b6d85e785ee13f231d49679e64 100644 (file)
@@ -501,7 +501,7 @@ static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        struct inode *inode = mapping->host;
        struct exfat_inode_info *ei = EXFAT_I(inode);
        loff_t pos = iocb->ki_pos;
-       loff_t size = iocb->ki_pos + iov_iter_count(iter);
+       loff_t size = pos + iov_iter_count(iter);
        int rw = iov_iter_rw(iter);
        ssize_t ret;
 
@@ -525,11 +525,10 @@ static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
         */
        ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block);
        if (ret < 0) {
-               if (rw == WRITE)
+               if (rw == WRITE && ret != -EIOCBQUEUED)
                        exfat_write_failed(mapping, size);
 
-               if (ret != -EIOCBQUEUED)
-                       return ret;
+               return ret;
        } else
                size = pos + ret;