[RHEL7,COMMIT] fs/fuse kio: deny unavailable ioctl's in kio

Submitted by Konstantin Khorenko on Jan. 10, 2019, 10:14 a.m.

Details

Message ID 201901101014.x0AAEe90004740@finist-ce7.sw.ru
State New
Series "fs/fuse kio: deny unavailable ioctl's in kio"
Headers show

Commit Message

Konstantin Khorenko Jan. 10, 2019, 10:14 a.m.
The commit is pushed to "branch-rh7-3.10.0-957.1.3.vz7.83.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.1.3.vz7.83.4
------>
commit 7cc0b6b04d1e5a9961d83c09e4676a61e954fb78
Author: Pavel Butsykin <pbutsykin@virtuozzo.com>
Date:   Thu Jan 10 13:14:40 2019 +0300

    fs/fuse kio: deny unavailable ioctl's in kio
    
    There are some ioctl's that were made to service the kio module, and they
    should not be available to user app.
    
    Also there are two ioctls PCS_IOC_NOCSUMONREAD and PCS_IOC_NOWRITEDELAY that
    must be handled in kio, otherwise they are meaningless. So let's return
    -EOPNOTSUPP unless we implement them in kio.
    
    Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
    Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 fs/fuse/fuse_i.h                   |  2 ++
 fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 27 ++++++++++++++++++++++++---
 fs/fuse/kio/pcs/pcs_ioctl.h        |  5 +++++
 3 files changed, 31 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index d7dd571c08f6..4c27bfa0e74d 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -301,6 +301,7 @@  struct fuse_io_priv {
  * FR_FINISHED:		request is finished
  * FR_PRIVATE:		request is on private list
  * FR_NONBLOCKING:	non-blocking request (only needed for KIO)
+ * FR_KIO_INTERNAL:	request initiated by KIO
  */
 enum fuse_req_flag {
 	FR_ISREPLY,
@@ -315,6 +316,7 @@  enum fuse_req_flag {
 	FR_FINISHED,
 	FR_PRIVATE,
 	FR_NONBLOCKING,
+	FR_KIO_INTERNAL,
 };
 
 /**
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index 89866370a341..cdd4fe578128 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -156,6 +156,7 @@  int kpcs_conn_init(struct fuse_conn *fc)
 	}
 
 	__set_bit(FR_BACKGROUND, &req->flags);
+	__set_bit(FR_KIO_INTERNAL, &req->flags);
 	memset(&req->misc.ioctl, 0, sizeof(req->misc.ioctl));
 	/* filehandle and nodeid are null, but this is OK */
 	inarg = &req->misc.ioctl.in;
@@ -218,6 +219,7 @@  static int fuse_pcs_getfileinfo(struct fuse_conn *fc, struct file *file,
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
+	__set_bit(FR_KIO_INTERNAL, &req->flags);
 	memset(&req->misc.ioctl, 0, sizeof(req->misc.ioctl));
 	inarg = &req->misc.ioctl.in;
 	outarg = &req->misc.ioctl.out;
@@ -269,6 +271,7 @@  static int fuse_pcs_kdirect_claim_op(struct fuse_conn *fc, struct file *file,
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
+	__set_bit(FR_KIO_INTERNAL, &req->flags);
 	memset(&req->misc.ioctl, 0, sizeof(req->misc.ioctl));
 	inarg = &req->misc.ioctl.in;
 	outarg = &req->misc.ioctl.out;
@@ -470,6 +473,7 @@  int fuse_map_resolve(struct pcs_map_entry *m, int direction)
 		return PTR_ERR(req);
 	}
 
+	__set_bit(FR_KIO_INTERNAL, &req->flags);
 	memset(&req->misc.ioctl, 0, sizeof(req->misc.ioctl));
 	inarg = &req->misc.ioctl.in;
 	outarg = &req->misc.ioctl.out;
@@ -601,6 +605,7 @@  int fuse_pcs_csconn_send(struct fuse_conn *fc, struct pcs_rpc *ep, int flags)
 		return PTR_ERR(req);
 	}
 
+	__set_bit(FR_KIO_INTERNAL, &req->flags);
 	memset(&req->misc.ioctl, 0, sizeof(req->misc.ioctl));
 	inarg = &req->misc.ioctl.in;
 	outarg = &req->misc.ioctl.out;
@@ -1084,6 +1089,9 @@  static int pcs_kio_classify_req(struct fuse_conn *fc, struct fuse_req *req, bool
 {
 	struct fuse_inode *fi = get_fuse_inode(req->io_inode);
 
+	if (test_bit(FR_KIO_INTERNAL, &req->flags))
+		return 1;
+
 	switch (req->in.h.opcode) {
 	case FUSE_READ:
 	case FUSE_WRITE:
@@ -1110,9 +1118,22 @@  static int pcs_kio_classify_req(struct fuse_conn *fc, struct fuse_req *req, bool
 	case FUSE_IOCTL: {
 		struct fuse_ioctl_in const *inarg = req->in.args[0].value;
 
-		if (inarg->cmd != FS_IOC_FIEMAP)
-			return 1;
-
+		switch (inarg->cmd) {
+			case FS_IOC_FIEMAP:
+				break;
+			case PCS_IOC_NOCSUMONREAD:
+			case PCS_IOC_NOWRITEDELAY:
+				return -EOPNOTSUPP;
+			case PCS_IOC_INIT_KDIRECT:
+			case PCS_IOC_CSCONN:
+			case PCS_IOC_GETFILEINFO:
+			case PCS_IOC_KDIRECT_CLAIM:
+			case PCS_IOC_KDIRECT_RELEASE:
+			case PCS_IOC_GETMAP:
+				return -EPERM;
+			default:
+				return 1;
+		}
 		break;
 	}
 	default:
diff --git a/fs/fuse/kio/pcs/pcs_ioctl.h b/fs/fuse/kio/pcs/pcs_ioctl.h
index 5cf40e35f881..8fe1aca9ef12 100644
--- a/fs/fuse/kio/pcs/pcs_ioctl.h
+++ b/fs/fuse/kio/pcs/pcs_ioctl.h
@@ -78,6 +78,11 @@  struct pcs_ioc_csconn
 #define PCS_IOC_CS_REOPEN	(PCS_IOC_CS_OPEN|PCS_IOC_CS_CLOSE)
 };
 
+#define PCS_IOC_NOCSUMONREAD	_IOW('V',3,u32)
+# define PCS_IOC_NOCSUMONREAD_DATA	1
+# define PCS_IOC_NOCSUMONREAD_METADATA	2
+#define PCS_IOC_NOWRITEDELAY	_IOW('V',4,u32)
+
 #define PCS_IOC_INIT_KDIRECT	_IOR('V',32, struct pcs_ioc_init_kdirect)
 #define PCS_IOC_CSCONN		_IOR('V',33, struct pcs_ioc_csconn)
 #define PCS_IOC_GETFILEINFO	_IOR('V',34, struct pcs_ioc_fileinfo)