[Devel] [PATCH RHEL7 COMMIT] fs/fuse kio_pcs: prevention of falling kio reqs to usermode
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Oct 9 12:19:02 MSK 2018
The commit is pushed to "branch-rh7-3.10.0-862.14.4.vz7.72.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.14.4.vz7.72.4
------>
commit 9e31b0f6c01f532cfedf72acbd67f1f0c50fa2bc
Author: Pavel Butsykin <pbutsykin at virtuozzo.com>
Date: Tue Oct 9 12:18:59 2018 +0300
fs/fuse kio_pcs: prevention of falling kio reqs to usermode
As it turned out, some requests may come without io_inode and is a valid request
for usermod, but not for kio. We can't pass kio requests in usermod which can
break consistency. Let's add check for the validation of this case.
Signed-off-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
Reviewed-by: Kirill Tkhai <ktkhai at virtuozzo.com>
=====================
Patchset description:
Fuse: Fix IOCB_CMD_UNMAP_ITER handling to prevent cache inconsistency
https://pmc.acronis.com/browse/VSTOR-15447
Ploop can asynchronously unmap regions by sending IOCB_CMD_UNMAP_ITER, but this
command isn't quite correctly interpreted in Fuse. Moreover, in Fast-path mode,
fallocate(FALLOC_FL_PUNCH_HOLE|FALLOC_FL_ZERO_RANGE) falls to fuse user daemon
and it can lead to data corruption.
Let's fix it.
Pavel Butsykin (4):
fs/fuse: fix mutually exclusive flags in fuse_send_unmap()
fs/fuse: initialize req->io_inode in fuse_send_unmap()
fs/fuse kio_pcs: split kpcs_req_send()
fs/fuse kio_pcs: prevention of falling kio reqs to usermode
---
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 29 ++++++++++++++++++++---------
1 file changed, 20 insertions(+), 9 deletions(-)
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index 3143d24d7544..d3a038e9921f 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -1028,9 +1028,8 @@ static void _pcs_grow_end(struct fuse_conn *fc, struct fuse_req *req)
kpcs_setattr_end(fc, req);
}
-static void pcs_kio_setattr_handle(struct fuse_req *req)
+static void pcs_kio_setattr_handle(struct fuse_inode *fi, struct fuse_req *req)
{
- struct fuse_inode *fi = get_fuse_inode(req->io_inode);
struct pcs_fuse_req *r = pcs_req_from_fuse(req);
struct fuse_setattr_in *inarg = (void*) req->in.args[0].value;
struct pcs_dentry_info *di;
@@ -1065,6 +1064,8 @@ static void pcs_kio_setattr_handle(struct fuse_req *req)
static int pcs_kio_classify_req(struct fuse_conn *fc, struct fuse_req *req)
{
+ struct fuse_inode *fi = get_fuse_inode(req->io_inode);
+
switch (req->in.h.opcode) {
case FUSE_READ:
case FUSE_WRITE:
@@ -1073,7 +1074,10 @@ static int pcs_kio_classify_req(struct fuse_conn *fc, struct fuse_req *req)
case FUSE_FALLOCATE:
break;
case FUSE_SETATTR:
- pcs_kio_setattr_handle(req);
+ if (unlikely(!fi || !fi->private))
+ goto fail;
+
+ pcs_kio_setattr_handle(fi, req);
return 1;
case FUSE_IOCTL: {
struct fuse_ioctl_in const *inarg = req->in.args[0].value;
@@ -1087,13 +1091,22 @@ static int pcs_kio_classify_req(struct fuse_conn *fc, struct fuse_req *req)
return 1;
}
+ if (unlikely(!fi || !fi->private))
+ goto fail;
+
return 0;
+
+fail:
+ WARN_ONCE(1, "Fuse kio: req cannot be processed w/o inode\n");
+ req->out.h.error = -EINVAL;
+ request_end(fc, req);
+ return -EINVAL;
}
static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bool lk)
{
struct pcs_fuse_cluster *pfc = (struct pcs_fuse_cluster*)fc->kio.ctx;
- struct fuse_inode *fi = get_fuse_inode(req->io_inode);
+ int ret;
if (!fc->initialized || fc->conn_error)
return 1;
@@ -1107,11 +1120,9 @@ static int kpcs_req_send(struct fuse_conn* fc, struct fuse_req *req, bool bg, bo
TRACE(" Enter req:%p op:%d end:%p bg:%d lk:%d\n", req, req->in.h.opcode, req->end, bg, lk);
- if (!fi || !fi->private)
- return 1;
-
- if (pcs_kio_classify_req(fc, req))
- return 1;
+ ret = pcs_kio_classify_req(fc, req);
+ if (ret)
+ return ret < 0 ? 0 : 1;
/* request_end below will do fuse_put_request() */
if (!bg)
More information about the Devel
mailing list