[v2] fs/fuse kio: deny unavailable ioctl's in kio

Submitted by Pavel Butsykin on Dec. 26, 2018, 8:59 a.m.

Details

Message ID 20181226085944.29052-1-pbutsykin@virtuozzo.com
State New
Series "fs/fuse kio: deny unavailable ioctl's in kio"
Headers show

Commit Message

Pavel Butsykin Dec. 26, 2018, 8:59 a.m.
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>
---
 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)

Comments

Kirill Tkhai Dec. 26, 2018, 9:47 a.m.
On 26.12.2018 11:59, Pavel Butsykin wrote:
> 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(-)
> 
> 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)
>