On Wed, Sep 22, 2021 at 04:00:47PM +0200, Miklos Szeredi wrote: > First let's fix the oops: ovl_read_iter()/ovl_write_iter() must check > real file's ->direct_IO if IOCB_DIRECT is set in iocb->ki_flags and > return -EINVAL if not. And here's that fix. Please test. Thanks, Miklos --- From: Miklos Szeredi <mszeredi@xxxxxxxxxx> Subject: ovl: fix IOCB_DIRECT if underlying fs doesn't support direct IO Normally the check at open time suffices, but e.g loop device does set IOCB_DIRECT after doing its own checks (which are not sufficent for overlayfs). Make sure we don't call the underlying filesystem read/write method with the IOCB_DIRECT if it's not supported. Reported-by: Huang Jianan <huangjianan@xxxxxxxx> Fixes: 16914e6fc7e1 ("ovl: add ovl_read_iter()") Cc: <stable@xxxxxxxxxxxxxxx> # v4.19 Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxxxxx> --- fs/overlayfs/file.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -296,6 +296,12 @@ static ssize_t ovl_read_iter(struct kioc if (ret) return ret; + ret = -EINVAL; + if (iocb->ki_flags & IOCB_DIRECT && + (!real.file->f_mapping->a_ops || + !real.file->f_mapping->a_ops->direct_IO)) + goto out_fdput; + old_cred = ovl_override_creds(file_inode(file)->i_sb); if (is_sync_kiocb(iocb)) { ret = vfs_iter_read(real.file, iter, &iocb->ki_pos, @@ -320,7 +326,7 @@ static ssize_t ovl_read_iter(struct kioc out: revert_creds(old_cred); ovl_file_accessed(file); - +out_fdput: fdput(real); return ret; @@ -349,6 +355,12 @@ static ssize_t ovl_write_iter(struct kio if (ret) goto out_unlock; + ret = -EINVAL; + if (iocb->ki_flags & IOCB_DIRECT && + (!real.file->f_mapping->a_ops || + !real.file->f_mapping->a_ops->direct_IO)) + goto out_fdput; + if (!ovl_should_sync(OVL_FS(inode->i_sb))) ifl &= ~(IOCB_DSYNC | IOCB_SYNC); @@ -384,6 +396,7 @@ static ssize_t ovl_write_iter(struct kio } out: revert_creds(old_cred); +out_fdput: fdput(real); out_unlock: