diff mbox series

cifs: add IOCTL for QUERY_INFO passthrough to userspace

Message ID 20180913025713.21219-1-lsahlber@redhat.com (mailing list archive)
State New, archived
Headers show
Series cifs: add IOCTL for QUERY_INFO passthrough to userspace | expand

Commit Message

Ronnie Sahlberg Sept. 13, 2018, 2:57 a.m. UTC
This allows userspace tools to query the raw info levels for cifs files
and process the response in userspace.
In particular this is useful for many of those data where there is no
corresponding native data structure in linux.
For example querying the security descriptor for a file and extract the
SIDs.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/cifs_ioctl.h |  9 +++++++
 fs/cifs/cifsglob.h   |  4 ++++
 fs/cifs/ioctl.c      | 18 ++++++++++++++
 fs/cifs/smb2ops.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 98 insertions(+)

Comments

Ronnie Sahlberg Sept. 13, 2018, 2:59 a.m. UTC | #1
Steve,

Attached is a trivial program to query and partially decode the security descriptor from userspace
to illustrate how it can be used.



----- Original Message -----
From: "Ronnie Sahlberg" <lsahlber@redhat.com>
To: "linux-cifs" <linux-cifs@vger.kernel.org>
Cc: "Steve French" <smfrench@gmail.com>
Sent: Thursday, 13 September, 2018 12:57:13 PM
Subject: [PATCH] cifs: add IOCTL for QUERY_INFO passthrough to userspace

This allows userspace tools to query the raw info levels for cifs files
and process the response in userspace.
In particular this is useful for many of those data where there is no
corresponding native data structure in linux.
For example querying the security descriptor for a file and extract the
SIDs.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/cifs_ioctl.h |  9 +++++++
 fs/cifs/cifsglob.h   |  4 ++++
 fs/cifs/ioctl.c      | 18 ++++++++++++++
 fs/cifs/smb2ops.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 98 insertions(+)

diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
index 57ff0756e30c..d8b7353260f6 100644
--- a/fs/cifs/cifs_ioctl.h
+++ b/fs/cifs/cifs_ioctl.h
@@ -43,8 +43,17 @@ struct smb_snapshot_array {
 	/*	snapshots[]; */
 } __packed;
 
+struct smb_query_info {
+	__u32	buffer_length;
+	__u32   info_type;
+	__u32   file_info_class;
+	__u32   additional_information;
+	/* char buffer[]; */
+} __packed;
+
 #define CIFS_IOCTL_MAGIC	0xCF
 #define CIFS_IOC_COPYCHUNK_FILE	_IOW(CIFS_IOCTL_MAGIC, 3, int)
 #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
 #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
 #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
+#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 9dcaed031843..bb9e5b90923d 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -465,6 +465,10 @@ struct smb_version_operations {
 	enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
 			    enum securityEnum);
 	int (*next_header)(char *);
+	/* ioctl passthrough for query_info */
+	int (*ioctl_query_info)(const unsigned int xid,
+				struct cifsFileInfo *file,
+				unsigned long p);
 };
 
 struct smb_version_values {
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 54f32f9143a9..1e6b399ebb63 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -34,6 +34,21 @@
 #include "cifs_ioctl.h"
 #include <linux/btrfs.h>
 
+static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
+				  unsigned long p)
+{
+	struct cifsFileInfo *pSMBFile = filep->private_data;
+	struct cifs_tcon *tcon;
+
+	tcon = tlink_tcon(pSMBFile->tlink);
+
+	if (tcon->ses->server->ops->ioctl_query_info)
+		return tcon->ses->server->ops->ioctl_query_info(
+				xid, pSMBFile, p);
+	else
+		return -EOPNOTSUPP;
+}
+
 static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
 			unsigned long srcfd)
 {
@@ -196,6 +211,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
 		case CIFS_IOC_COPYCHUNK_FILE:
 			rc = cifs_ioctl_copychunk(xid, filep, arg);
 			break;
+		case CIFS_QUERY_INFO:
+			rc = cifs_ioctl_query_info(xid, filep, arg);
+			break;
 		case CIFS_IOC_SET_INTEGRITY:
 			if (pSMBFile == NULL)
 				break;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 23118b7a2bbc..8c9f1c638e0f 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1057,6 +1057,69 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
 	return rc;
 }
 
+static int
+smb2_ioctl_query_info(const unsigned int xid,
+		      struct cifsFileInfo *file,
+		      unsigned long p)
+{
+	struct cifs_tcon *tcon = tlink_tcon(file->tlink);
+	struct cifs_ses *ses = tcon->ses;
+	void __user *arg = (void __user *)p;
+	struct smb_query_info qi, *pqi;
+	int rc = 0;
+	int flags = 0;
+	struct smb_rqst rqst;
+	struct kvec iov[1];
+	struct kvec rsp_iov;
+	int resp_buftype;
+	struct smb2_query_info_rsp *rsp = NULL;
+
+	if (copy_from_user(&qi, arg, sizeof(struct smb_query_info)))
+		return -EFAULT;
+
+	if (!ses || !(ses->server))
+		return -EIO;
+
+	if (smb3_encryption_required(tcon))
+		flags |= CIFS_TRANSFORM_REQ;
+
+	memset(&rqst, 0, sizeof(struct smb_rqst));
+	memset(&iov, 0, sizeof(iov));
+	rqst.rq_iov = iov;
+	rqst.rq_nvec = 1;
+
+	rc = SMB2_query_info_init(tcon, &rqst, file->fid.persistent_fid,
+				  file->fid.volatile_fid,
+				  qi.file_info_class, qi.info_type,
+				  qi.additional_information,
+				  qi.buffer_length);
+	if (rc)
+		goto iqinf_exit;
+
+	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
+	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
+	if (rc)
+		goto iqinf_exit;
+
+	pqi = arg;
+	if (le32_to_cpu(rsp->OutputBufferLength) < qi.buffer_length)
+		qi.buffer_length = le32_to_cpu(rsp->OutputBufferLength);
+	if (copy_to_user(&pqi->buffer_length, &qi.buffer_length,
+			 sizeof(qi.buffer_length))) {
+		rc = -EFAULT;
+		goto iqinf_exit;
+	}
+	if (copy_to_user(pqi + 1, rsp->Buffer, qi.buffer_length)) {
+		rc = -EFAULT;
+		goto iqinf_exit;
+	}
+
+ iqinf_exit:
+	SMB2_query_info_free(&rqst);
+	free_rsp_buf(resp_buftype, rsp);
+	return rc;
+}
+
 static ssize_t
 smb2_copychunk_range(const unsigned int xid,
 			struct cifsFileInfo *srcfile,
@@ -3303,6 +3366,7 @@ struct smb_version_operations smb20_operations = {
 	.set_acl = set_smb2_acl,
 #endif /* CIFS_ACL */
 	.next_header = smb2_next_header,
+	.ioctl_query_info = smb2_ioctl_query_info,
 };
 
 struct smb_version_operations smb21_operations = {
@@ -3398,6 +3462,7 @@ struct smb_version_operations smb21_operations = {
 	.set_acl = set_smb2_acl,
 #endif /* CIFS_ACL */
 	.next_header = smb2_next_header,
+	.ioctl_query_info = smb2_ioctl_query_info,
 };
 
 struct smb_version_operations smb30_operations = {
@@ -3502,6 +3567,7 @@ struct smb_version_operations smb30_operations = {
 	.set_acl = set_smb2_acl,
 #endif /* CIFS_ACL */
 	.next_header = smb2_next_header,
+	.ioctl_query_info = smb2_ioctl_query_info,
 };
 
 struct smb_version_operations smb311_operations = {
@@ -3607,6 +3673,7 @@ struct smb_version_operations smb311_operations = {
 	.set_acl = set_smb2_acl,
 #endif /* CIFS_ACL */
 	.next_header = smb2_next_header,
+	.ioctl_query_info = smb2_ioctl_query_info,
 };
 
 struct smb_version_values smb20_values = {
Steve French Sept. 16, 2018, 4:43 a.m. UTC | #2
This is really cool - here is sample output run against a file on a Samba mount:

sfrench@smf-Thinkpad-P51:~$ ./querysd /mnt/file4
Revision:1
Control: 0490
Owner: S-1-5-21--1258851229--573074714-1715408553-1000
Group: S-1-22-2-1000
DACL:
Type:00 Flags:00
ff011e000105000000000005150000006374f7b4e692d7dda90e3f66e803000000001800
Type:00 Flags:00 9f011200010200000000001602000000e803000000001400
Type:00 Flags:00 9f01120001010000000000010000000000000000
On Wed, Sep 12, 2018 at 9:59 PM Ronnie Sahlberg <lsahlber@redhat.com> wrote:
>
> Steve,
>
> Attached is a trivial program to query and partially decode the security descriptor from userspace
> to illustrate how it can be used.
>
>
>
> ----- Original Message -----
> From: "Ronnie Sahlberg" <lsahlber@redhat.com>
> To: "linux-cifs" <linux-cifs@vger.kernel.org>
> Cc: "Steve French" <smfrench@gmail.com>
> Sent: Thursday, 13 September, 2018 12:57:13 PM
> Subject: [PATCH] cifs: add IOCTL for QUERY_INFO passthrough to userspace
>
> This allows userspace tools to query the raw info levels for cifs files
> and process the response in userspace.
> In particular this is useful for many of those data where there is no
> corresponding native data structure in linux.
> For example querying the security descriptor for a file and extract the
> SIDs.
>
> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> ---
>  fs/cifs/cifs_ioctl.h |  9 +++++++
>  fs/cifs/cifsglob.h   |  4 ++++
>  fs/cifs/ioctl.c      | 18 ++++++++++++++
>  fs/cifs/smb2ops.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 98 insertions(+)
>
> diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
> index 57ff0756e30c..d8b7353260f6 100644
> --- a/fs/cifs/cifs_ioctl.h
> +++ b/fs/cifs/cifs_ioctl.h
> @@ -43,8 +43,17 @@ struct smb_snapshot_array {
>         /*      snapshots[]; */
>  } __packed;
>
> +struct smb_query_info {
> +       __u32   buffer_length;
> +       __u32   info_type;
> +       __u32   file_info_class;
> +       __u32   additional_information;
> +       /* char buffer[]; */
> +} __packed;
> +
>  #define CIFS_IOCTL_MAGIC       0xCF
>  #define CIFS_IOC_COPYCHUNK_FILE        _IOW(CIFS_IOCTL_MAGIC, 3, int)
>  #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
>  #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
>  #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
> +#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 9dcaed031843..bb9e5b90923d 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -465,6 +465,10 @@ struct smb_version_operations {
>         enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
>                             enum securityEnum);
>         int (*next_header)(char *);
> +       /* ioctl passthrough for query_info */
> +       int (*ioctl_query_info)(const unsigned int xid,
> +                               struct cifsFileInfo *file,
> +                               unsigned long p);
>  };
>
>  struct smb_version_values {
> diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
> index 54f32f9143a9..1e6b399ebb63 100644
> --- a/fs/cifs/ioctl.c
> +++ b/fs/cifs/ioctl.c
> @@ -34,6 +34,21 @@
>  #include "cifs_ioctl.h"
>  #include <linux/btrfs.h>
>
> +static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
> +                                 unsigned long p)
> +{
> +       struct cifsFileInfo *pSMBFile = filep->private_data;
> +       struct cifs_tcon *tcon;
> +
> +       tcon = tlink_tcon(pSMBFile->tlink);
> +
> +       if (tcon->ses->server->ops->ioctl_query_info)
> +               return tcon->ses->server->ops->ioctl_query_info(
> +                               xid, pSMBFile, p);
> +       else
> +               return -EOPNOTSUPP;
> +}
> +
>  static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
>                         unsigned long srcfd)
>  {
> @@ -196,6 +211,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
>                 case CIFS_IOC_COPYCHUNK_FILE:
>                         rc = cifs_ioctl_copychunk(xid, filep, arg);
>                         break;
> +               case CIFS_QUERY_INFO:
> +                       rc = cifs_ioctl_query_info(xid, filep, arg);
> +                       break;
>                 case CIFS_IOC_SET_INTEGRITY:
>                         if (pSMBFile == NULL)
>                                 break;
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index 23118b7a2bbc..8c9f1c638e0f 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -1057,6 +1057,69 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
>         return rc;
>  }
>
> +static int
> +smb2_ioctl_query_info(const unsigned int xid,
> +                     struct cifsFileInfo *file,
> +                     unsigned long p)
> +{
> +       struct cifs_tcon *tcon = tlink_tcon(file->tlink);
> +       struct cifs_ses *ses = tcon->ses;
> +       void __user *arg = (void __user *)p;
> +       struct smb_query_info qi, *pqi;
> +       int rc = 0;
> +       int flags = 0;
> +       struct smb_rqst rqst;
> +       struct kvec iov[1];
> +       struct kvec rsp_iov;
> +       int resp_buftype;
> +       struct smb2_query_info_rsp *rsp = NULL;
> +
> +       if (copy_from_user(&qi, arg, sizeof(struct smb_query_info)))
> +               return -EFAULT;
> +
> +       if (!ses || !(ses->server))
> +               return -EIO;
> +
> +       if (smb3_encryption_required(tcon))
> +               flags |= CIFS_TRANSFORM_REQ;
> +
> +       memset(&rqst, 0, sizeof(struct smb_rqst));
> +       memset(&iov, 0, sizeof(iov));
> +       rqst.rq_iov = iov;
> +       rqst.rq_nvec = 1;
> +
> +       rc = SMB2_query_info_init(tcon, &rqst, file->fid.persistent_fid,
> +                                 file->fid.volatile_fid,
> +                                 qi.file_info_class, qi.info_type,
> +                                 qi.additional_information,
> +                                 qi.buffer_length);
> +       if (rc)
> +               goto iqinf_exit;
> +
> +       rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
> +       rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
> +       if (rc)
> +               goto iqinf_exit;
> +
> +       pqi = arg;
> +       if (le32_to_cpu(rsp->OutputBufferLength) < qi.buffer_length)
> +               qi.buffer_length = le32_to_cpu(rsp->OutputBufferLength);
> +       if (copy_to_user(&pqi->buffer_length, &qi.buffer_length,
> +                        sizeof(qi.buffer_length))) {
> +               rc = -EFAULT;
> +               goto iqinf_exit;
> +       }
> +       if (copy_to_user(pqi + 1, rsp->Buffer, qi.buffer_length)) {
> +               rc = -EFAULT;
> +               goto iqinf_exit;
> +       }
> +
> + iqinf_exit:
> +       SMB2_query_info_free(&rqst);
> +       free_rsp_buf(resp_buftype, rsp);
> +       return rc;
> +}
> +
>  static ssize_t
>  smb2_copychunk_range(const unsigned int xid,
>                         struct cifsFileInfo *srcfile,
> @@ -3303,6 +3366,7 @@ struct smb_version_operations smb20_operations = {
>         .set_acl = set_smb2_acl,
>  #endif /* CIFS_ACL */
>         .next_header = smb2_next_header,
> +       .ioctl_query_info = smb2_ioctl_query_info,
>  };
>
>  struct smb_version_operations smb21_operations = {
> @@ -3398,6 +3462,7 @@ struct smb_version_operations smb21_operations = {
>         .set_acl = set_smb2_acl,
>  #endif /* CIFS_ACL */
>         .next_header = smb2_next_header,
> +       .ioctl_query_info = smb2_ioctl_query_info,
>  };
>
>  struct smb_version_operations smb30_operations = {
> @@ -3502,6 +3567,7 @@ struct smb_version_operations smb30_operations = {
>         .set_acl = set_smb2_acl,
>  #endif /* CIFS_ACL */
>         .next_header = smb2_next_header,
> +       .ioctl_query_info = smb2_ioctl_query_info,
>  };
>
>  struct smb_version_operations smb311_operations = {
> @@ -3607,6 +3673,7 @@ struct smb_version_operations smb311_operations = {
>         .set_acl = set_smb2_acl,
>  #endif /* CIFS_ACL */
>         .next_header = smb2_next_header,
> +       .ioctl_query_info = smb2_ioctl_query_info,
>  };
>
>  struct smb_version_values smb20_values = {
> --
> 2.13.3
>
Aurélien Aptel Sept. 16, 2018, 5:47 p.m. UTC | #3
Hi Ronnie,

Ronnie Sahlberg <lsahlber@redhat.com> writes:
> This allows userspace tools to query the raw info levels for cifs files
> and process the response in userspace.
> In particular this is useful for many of those data where there is no
> corresponding native data structure in linux.
> For example querying the security descriptor for a file and extract the
> SIDs.

Does this overlap with the extended attributes thing we already have for
DOS attributes, SID, and ACL (setcifsacl/getcifsacl from cifs-utils)? I
have never used it so I cannot say for sure.

>
> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> ---
>  fs/cifs/cifs_ioctl.h |  9 +++++++
>  fs/cifs/cifsglob.h   |  4 ++++
>  fs/cifs/ioctl.c      | 18 ++++++++++++++
>  fs/cifs/smb2ops.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 98 insertions(+)
>
> diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
> index 57ff0756e30c..d8b7353260f6 100644
> --- a/fs/cifs/cifs_ioctl.h
> +++ b/fs/cifs/cifs_ioctl.h
> @@ -43,8 +43,17 @@ struct smb_snapshot_array {
>  	/*	snapshots[]; */
>  } __packed;
>  
> +struct smb_query_info {
> +	__u32	buffer_length;
> +	__u32   info_type;
> +	__u32   file_info_class;
> +	__u32   additional_information;
> +	/* char buffer[]; */
> +} __packed;
> +
>  #define CIFS_IOCTL_MAGIC	0xCF
>  #define CIFS_IOC_COPYCHUNK_FILE	_IOW(CIFS_IOCTL_MAGIC, 3, int)
>  #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
>  #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
>  #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
> +#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 9dcaed031843..bb9e5b90923d 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -465,6 +465,10 @@ struct smb_version_operations {
>  	enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
>  			    enum securityEnum);
>  	int (*next_header)(char *);
> +	/* ioctl passthrough for query_info */
> +	int (*ioctl_query_info)(const unsigned int xid,
> +				struct cifsFileInfo *file,
> +				unsigned long p);

Shouldnt we put the void* __user thingy directly in the prototype or is
unsigned long the type already picked by the kernel ioctl code?

Otherwise looks good. If Christoph Hellwig doesn't object to this new
ioctl we can use it in cifs-utils.

I've made a little patch for cifs-utils (will send next to this) that
adds a cifsfileinfo utility. It's a slightly modified version of your
program (use defines for some constants, printf formats, getopt, -v
option, ...) and a man page. I wonder if it could/should be merged in
getcifsacl.

The man page has a XXX part that needs to be replaced with the kernel
version if this makes it into a kernel release. Please speak up if you
think of a better name and feel free to complete the man page.

Cheers,
Tom Talpey Sept. 16, 2018, 6:20 p.m. UTC | #4
> -----Original Message-----
> From: linux-cifs-owner@vger.kernel.org <linux-cifs-owner@vger.kernel.org> On
> Behalf Of Aurélien Aptel
> Sent: Sunday, September 16, 2018 1:47 PM
> To: Ronnie Sahlberg <lsahlber@redhat.com>; linux-cifs <linux-
> cifs@vger.kernel.org>
> Cc: Steve French <smfrench@gmail.com>
> Subject: Re: [PATCH] cifs: add IOCTL for QUERY_INFO passthrough to userspace
> ...
> adds a cifsfileinfo utility.
> ...
> Please speak up if you think of a better name ...

I think it's a mistake to name anything beginning with "cifs" in
today's world. I suggest "smbfileinfo". But isn't this really just
an extended version of stat(1)? Would a name in line with that
usage be more appropriate?
Aurélien Aptel Sept. 16, 2018, 6:42 p.m. UTC | #5
Tom Talpey <ttalpey@microsoft.com> writes:
> I think it's a mistake to name anything beginning with "cifs" in
> today's world. I suggest "smbfileinfo". But isn't this really just
> an extended version of stat(1)? Would a name in line with that
> usage be more appropriate?

Yes cifsstat or smbstat sounds a lot better indeed.

As for cifs vs smb, unfortunately "cifs" is used *everywhere* in the
cifs-utils package. The name, the utilities name, the man pages,
configure options, etc. I've tried to use SMB in the man page but it
makes the package a bit inconsistent. Ideally we should rename
everything but that's going to break a lot of stuff downstream.

Cheers,
Tom Talpey Sept. 16, 2018, 7:18 p.m. UTC | #6
> -----Original Message-----
> From: Aurélien Aptel <aaptel@suse.com>
> Sent: Sunday, September 16, 2018 2:43 PM
> To: Tom Talpey <ttalpey@microsoft.com>; Ronnie Sahlberg
> <lsahlber@redhat.com>; linux-cifs <linux-cifs@vger.kernel.org>
> Cc: Steve French <smfrench@gmail.com>
> Subject: RE: [PATCH] cifs: add IOCTL for QUERY_INFO passthrough to userspace
> ...
> As for cifs vs smb, unfortunately "cifs" is used *everywhere* in the
> cifs-utils package. The name, the utilities name, the man pages,
> configure options, etc. 

It's time. I don’t think the name should get one more new use.
"CIFS" is literally 1995 terminology.

The name change for the kmod is already in place. Aliases can be
used to solve shell script compatibility. Configure options, likewise.

Tom.
Aurélien Aptel Sept. 17, 2018, 12:46 a.m. UTC | #7
There's an issue with the ioctl against directories as Steve might have
told you:

Ronnie Sahlberg <lsahlber@redhat.com> writes:
>  
> +static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
> +				  unsigned long p)
> +{
> +	struct cifsFileInfo *pSMBFile = filep->private_data;

private_data is NULL for directories so we get an Oops.

It turns out neither cifs_open() nor cifs_atomic_open() is called when
we call open(dir) from userspace...

> +	struct cifs_tcon *tcon;
> +
> +	tcon = tlink_tcon(pSMBFile->tlink);
> +
> +	if (tcon->ses->server->ops->ioctl_query_info)
> +		return tcon->ses->server->ops->ioctl_query_info(
> +				xid, pSMBFile, p);
> +	else
> +		return -EOPNOTSUPP;
> +}
> +
ronnie sahlberg Sept. 17, 2018, 3:46 a.m. UTC | #8
On Mon, Sep 17, 2018 at 3:47 AM, Aurélien Aptel <aaptel@suse.com> wrote:
> Hi Ronnie,
>
> Ronnie Sahlberg <lsahlber@redhat.com> writes:
>> This allows userspace tools to query the raw info levels for cifs files
>> and process the response in userspace.
>> In particular this is useful for many of those data where there is no
>> corresponding native data structure in linux.
>> For example querying the security descriptor for a file and extract the
>> SIDs.
>
> Does this overlap with the extended attributes thing we already have for
> DOS attributes, SID, and ACL (setcifsacl/getcifsacl from cifs-utils)? I
> have never used it so I cannot say for sure.

Yeah, it is the same thing as that magic xattr.

>
>>
>> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
>> ---
>>  fs/cifs/cifs_ioctl.h |  9 +++++++
>>  fs/cifs/cifsglob.h   |  4 ++++
>>  fs/cifs/ioctl.c      | 18 ++++++++++++++
>>  fs/cifs/smb2ops.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 98 insertions(+)
>>
>> diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
>> index 57ff0756e30c..d8b7353260f6 100644
>> --- a/fs/cifs/cifs_ioctl.h
>> +++ b/fs/cifs/cifs_ioctl.h
>> @@ -43,8 +43,17 @@ struct smb_snapshot_array {
>>       /*      snapshots[]; */
>>  } __packed;
>>
>> +struct smb_query_info {
>> +     __u32   buffer_length;
>> +     __u32   info_type;
>> +     __u32   file_info_class;
>> +     __u32   additional_information;
>> +     /* char buffer[]; */
>> +} __packed;
>> +
>>  #define CIFS_IOCTL_MAGIC     0xCF
>>  #define CIFS_IOC_COPYCHUNK_FILE      _IOW(CIFS_IOCTL_MAGIC, 3, int)
>>  #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
>>  #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
>>  #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
>> +#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
>> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
>> index 9dcaed031843..bb9e5b90923d 100644
>> --- a/fs/cifs/cifsglob.h
>> +++ b/fs/cifs/cifsglob.h
>> @@ -465,6 +465,10 @@ struct smb_version_operations {
>>       enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
>>                           enum securityEnum);
>>       int (*next_header)(char *);
>> +     /* ioctl passthrough for query_info */
>> +     int (*ioctl_query_info)(const unsigned int xid,
>> +                             struct cifsFileInfo *file,
>> +                             unsigned long p);
>
> Shouldnt we put the void* __user thingy directly in the prototype or is
> unsigned long the type already picked by the kernel ioctl code?
>
> Otherwise looks good. If Christoph Hellwig doesn't object to this new
> ioctl we can use it in cifs-utils.
>
> I've made a little patch for cifs-utils (will send next to this) that
> adds a cifsfileinfo utility. It's a slightly modified version of your
> program (use defines for some constants, printf formats, getopt, -v
> option, ...) and a man page. I wonder if it could/should be merged in
> getcifsacl.
>
> The man page has a XXX part that needs to be replaced with the kernel
> version if this makes it into a kernel release. Please speak up if you
> think of a better name and feel free to complete the man page.
>
> Cheers,
> --
> Aurélien Aptel / SUSE Labs Samba Team
> GPG: 1839 CB5F 9F5B FB9B AA97  8C99 03C8 A49B 521B D5D3
> SUSE Linux GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
> GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
ronnie sahlberg Sept. 17, 2018, 3:48 a.m. UTC | #9
On Mon, Sep 17, 2018 at 4:42 AM, Aurélien Aptel <aaptel@suse.com> wrote:
> Tom Talpey <ttalpey@microsoft.com> writes:
>> I think it's a mistake to name anything beginning with "cifs" in
>> today's world. I suggest "smbfileinfo". But isn't this really just
>> an extended version of stat(1)? Would a name in line with that
>> usage be more appropriate?
>
> Yes cifsstat or smbstat sounds a lot better indeed.
>
> As for cifs vs smb, unfortunately "cifs" is used *everywhere* in the
> cifs-utils package. The name, the utilities name, the man pages,
> configure options, etc. I've tried to use SMB in the man page but it
> makes the package a bit inconsistent. Ideally we should rename
> everything but that's going to break a lot of stuff downstream.

smbstat would be really nice.  And have it implement all the info levels that
QUERY_INFO supports.


>
> Cheers,
> --
> Aurélien Aptel / SUSE Labs Samba Team
> GPG: 1839 CB5F 9F5B FB9B AA97  8C99 03C8 A49B 521B D5D3
> SUSE Linux GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
> GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
ronnie sahlberg Sept. 17, 2018, 6:51 a.m. UTC | #10
Would be really nice to do the plumbing to get SMB2_QUERY_QUOTA_INFO
working too so that we can surface the quota info to userspace.
Displaying true quota to userspace I think is still one of the larger
gaps we have.

On Mon, Sep 17, 2018 at 1:48 PM, ronnie sahlberg
<ronniesahlberg@gmail.com> wrote:
> On Mon, Sep 17, 2018 at 4:42 AM, Aurélien Aptel <aaptel@suse.com> wrote:
>> Tom Talpey <ttalpey@microsoft.com> writes:
>>> I think it's a mistake to name anything beginning with "cifs" in
>>> today's world. I suggest "smbfileinfo". But isn't this really just
>>> an extended version of stat(1)? Would a name in line with that
>>> usage be more appropriate?
>>
>> Yes cifsstat or smbstat sounds a lot better indeed.
>>
>> As for cifs vs smb, unfortunately "cifs" is used *everywhere* in the
>> cifs-utils package. The name, the utilities name, the man pages,
>> configure options, etc. I've tried to use SMB in the man page but it
>> makes the package a bit inconsistent. Ideally we should rename
>> everything but that's going to break a lot of stuff downstream.
>
> smbstat would be really nice.  And have it implement all the info levels that
> QUERY_INFO supports.
>
>
>>
>> Cheers,
>> --
>> Aurélien Aptel / SUSE Labs Samba Team
>> GPG: 1839 CB5F 9F5B FB9B AA97  8C99 03C8 A49B 521B D5D3
>> SUSE Linux GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
>> GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
Steve French Sept. 17, 2018, 6:52 a.m. UTC | #11
Quotas, SACLs, Claims based ACLs, and even auditing info (and streams
info) - all useful potentially for backup, debugging, misc. tools
On Mon, Sep 17, 2018 at 1:51 AM ronnie sahlberg
<ronniesahlberg@gmail.com> wrote:
>
> Would be really nice to do the plumbing to get SMB2_QUERY_QUOTA_INFO
> working too so that we can surface the quota info to userspace.
> Displaying true quota to userspace I think is still one of the larger
> gaps we have.
>
> On Mon, Sep 17, 2018 at 1:48 PM, ronnie sahlberg
> <ronniesahlberg@gmail.com> wrote:
> > On Mon, Sep 17, 2018 at 4:42 AM, Aurélien Aptel <aaptel@suse.com> wrote:
> >> Tom Talpey <ttalpey@microsoft.com> writes:
> >>> I think it's a mistake to name anything beginning with "cifs" in
> >>> today's world. I suggest "smbfileinfo". But isn't this really just
> >>> an extended version of stat(1)? Would a name in line with that
> >>> usage be more appropriate?
> >>
> >> Yes cifsstat or smbstat sounds a lot better indeed.
> >>
> >> As for cifs vs smb, unfortunately "cifs" is used *everywhere* in the
> >> cifs-utils package. The name, the utilities name, the man pages,
> >> configure options, etc. I've tried to use SMB in the man page but it
> >> makes the package a bit inconsistent. Ideally we should rename
> >> everything but that's going to break a lot of stuff downstream.
> >
> > smbstat would be really nice.  And have it implement all the info levels that
> > QUERY_INFO supports.
> >
> >
> >>
> >> Cheers,
> >> --
> >> Aurélien Aptel / SUSE Labs Samba Team
> >> GPG: 1839 CB5F 9F5B FB9B AA97  8C99 03C8 A49B 521B D5D3
> >> SUSE Linux GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
> >> GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
ronnie sahlberg Sept. 17, 2018, 6:56 a.m. UTC | #12
For this there will be a whole bunch of defines and some structure
definitions that cifs-utils could share with the kernel.
Maybe we can split some of those, just structs and #defines for flags
and such into separate header files in cifs.ko that we
can share with userspace?

I might want to share those files and use them in libsmb2 too since we
are getting too many re-implementations of the same
 structures and fields already :-)


ronnie

On Mon, Sep 17, 2018 at 4:52 PM, Steve French <smfrench@gmail.com> wrote:
> Quotas, SACLs, Claims based ACLs, and even auditing info (and streams
> info) - all useful potentially for backup, debugging, misc. tools
> On Mon, Sep 17, 2018 at 1:51 AM ronnie sahlberg
> <ronniesahlberg@gmail.com> wrote:
>>
>> Would be really nice to do the plumbing to get SMB2_QUERY_QUOTA_INFO
>> working too so that we can surface the quota info to userspace.
>> Displaying true quota to userspace I think is still one of the larger
>> gaps we have.
>>
>> On Mon, Sep 17, 2018 at 1:48 PM, ronnie sahlberg
>> <ronniesahlberg@gmail.com> wrote:
>> > On Mon, Sep 17, 2018 at 4:42 AM, Aurélien Aptel <aaptel@suse.com> wrote:
>> >> Tom Talpey <ttalpey@microsoft.com> writes:
>> >>> I think it's a mistake to name anything beginning with "cifs" in
>> >>> today's world. I suggest "smbfileinfo". But isn't this really just
>> >>> an extended version of stat(1)? Would a name in line with that
>> >>> usage be more appropriate?
>> >>
>> >> Yes cifsstat or smbstat sounds a lot better indeed.
>> >>
>> >> As for cifs vs smb, unfortunately "cifs" is used *everywhere* in the
>> >> cifs-utils package. The name, the utilities name, the man pages,
>> >> configure options, etc. I've tried to use SMB in the man page but it
>> >> makes the package a bit inconsistent. Ideally we should rename
>> >> everything but that's going to break a lot of stuff downstream.
>> >
>> > smbstat would be really nice.  And have it implement all the info levels that
>> > QUERY_INFO supports.
>> >
>> >
>> >>
>> >> Cheers,
>> >> --
>> >> Aurélien Aptel / SUSE Labs Samba Team
>> >> GPG: 1839 CB5F 9F5B FB9B AA97  8C99 03C8 A49B 521B D5D3
>> >> SUSE Linux GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
>> >> GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
>
>
>
> --
> Thanks,
>
> Steve
Steve French Sept. 17, 2018, 6:56 a.m. UTC | #13
Sounds fine to me
On Sun, Sep 16, 2018 at 10:46 PM ronnie sahlberg
<ronniesahlberg@gmail.com> wrote:
>
> On Mon, Sep 17, 2018 at 3:47 AM, Aurélien Aptel <aaptel@suse.com> wrote:
> > Hi Ronnie,
> >
> > Ronnie Sahlberg <lsahlber@redhat.com> writes:
> >> This allows userspace tools to query the raw info levels for cifs files
> >> and process the response in userspace.
> >> In particular this is useful for many of those data where there is no
> >> corresponding native data structure in linux.
> >> For example querying the security descriptor for a file and extract the
> >> SIDs.
> >
> > Does this overlap with the extended attributes thing we already have for
> > DOS attributes, SID, and ACL (setcifsacl/getcifsacl from cifs-utils)? I
> > have never used it so I cannot say for sure.
>
> Yeah, it is the same thing as that magic xattr.
>
> >
> >>
> >> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
> >> ---
> >>  fs/cifs/cifs_ioctl.h |  9 +++++++
> >>  fs/cifs/cifsglob.h   |  4 ++++
> >>  fs/cifs/ioctl.c      | 18 ++++++++++++++
> >>  fs/cifs/smb2ops.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  4 files changed, 98 insertions(+)
> >>
> >> diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
> >> index 57ff0756e30c..d8b7353260f6 100644
> >> --- a/fs/cifs/cifs_ioctl.h
> >> +++ b/fs/cifs/cifs_ioctl.h
> >> @@ -43,8 +43,17 @@ struct smb_snapshot_array {
> >>       /*      snapshots[]; */
> >>  } __packed;
> >>
> >> +struct smb_query_info {
> >> +     __u32   buffer_length;
> >> +     __u32   info_type;
> >> +     __u32   file_info_class;
> >> +     __u32   additional_information;
> >> +     /* char buffer[]; */
> >> +} __packed;
> >> +
> >>  #define CIFS_IOCTL_MAGIC     0xCF
> >>  #define CIFS_IOC_COPYCHUNK_FILE      _IOW(CIFS_IOCTL_MAGIC, 3, int)
> >>  #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
> >>  #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
> >>  #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
> >> +#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
> >> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> >> index 9dcaed031843..bb9e5b90923d 100644
> >> --- a/fs/cifs/cifsglob.h
> >> +++ b/fs/cifs/cifsglob.h
> >> @@ -465,6 +465,10 @@ struct smb_version_operations {
> >>       enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
> >>                           enum securityEnum);
> >>       int (*next_header)(char *);
> >> +     /* ioctl passthrough for query_info */
> >> +     int (*ioctl_query_info)(const unsigned int xid,
> >> +                             struct cifsFileInfo *file,
> >> +                             unsigned long p);
> >
> > Shouldnt we put the void* __user thingy directly in the prototype or is
> > unsigned long the type already picked by the kernel ioctl code?
> >
> > Otherwise looks good. If Christoph Hellwig doesn't object to this new
> > ioctl we can use it in cifs-utils.
> >
> > I've made a little patch for cifs-utils (will send next to this) that
> > adds a cifsfileinfo utility. It's a slightly modified version of your
> > program (use defines for some constants, printf formats, getopt, -v
> > option, ...) and a man page. I wonder if it could/should be merged in
> > getcifsacl.
> >
> > The man page has a XXX part that needs to be replaced with the kernel
> > version if this makes it into a kernel release. Please speak up if you
> > think of a better name and feel free to complete the man page.
> >
> > Cheers,
> > --
> > Aurélien Aptel / SUSE Labs Samba Team
> > GPG: 1839 CB5F 9F5B FB9B AA97  8C99 03C8 A49B 521B D5D3
> > SUSE Linux GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
> > GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
diff mbox series

Patch

diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
index 57ff0756e30c..d8b7353260f6 100644
--- a/fs/cifs/cifs_ioctl.h
+++ b/fs/cifs/cifs_ioctl.h
@@ -43,8 +43,17 @@  struct smb_snapshot_array {
 	/*	snapshots[]; */
 } __packed;
 
+struct smb_query_info {
+	__u32	buffer_length;
+	__u32   info_type;
+	__u32   file_info_class;
+	__u32   additional_information;
+	/* char buffer[]; */
+} __packed;
+
 #define CIFS_IOCTL_MAGIC	0xCF
 #define CIFS_IOC_COPYCHUNK_FILE	_IOW(CIFS_IOCTL_MAGIC, 3, int)
 #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
 #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
 #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
+#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 9dcaed031843..bb9e5b90923d 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -465,6 +465,10 @@  struct smb_version_operations {
 	enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
 			    enum securityEnum);
 	int (*next_header)(char *);
+	/* ioctl passthrough for query_info */
+	int (*ioctl_query_info)(const unsigned int xid,
+				struct cifsFileInfo *file,
+				unsigned long p);
 };
 
 struct smb_version_values {
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 54f32f9143a9..1e6b399ebb63 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -34,6 +34,21 @@ 
 #include "cifs_ioctl.h"
 #include <linux/btrfs.h>
 
+static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
+				  unsigned long p)
+{
+	struct cifsFileInfo *pSMBFile = filep->private_data;
+	struct cifs_tcon *tcon;
+
+	tcon = tlink_tcon(pSMBFile->tlink);
+
+	if (tcon->ses->server->ops->ioctl_query_info)
+		return tcon->ses->server->ops->ioctl_query_info(
+				xid, pSMBFile, p);
+	else
+		return -EOPNOTSUPP;
+}
+
 static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
 			unsigned long srcfd)
 {
@@ -196,6 +211,9 @@  long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
 		case CIFS_IOC_COPYCHUNK_FILE:
 			rc = cifs_ioctl_copychunk(xid, filep, arg);
 			break;
+		case CIFS_QUERY_INFO:
+			rc = cifs_ioctl_query_info(xid, filep, arg);
+			break;
 		case CIFS_IOC_SET_INTEGRITY:
 			if (pSMBFile == NULL)
 				break;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 23118b7a2bbc..8c9f1c638e0f 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1057,6 +1057,69 @@  SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
 	return rc;
 }
 
+static int
+smb2_ioctl_query_info(const unsigned int xid,
+		      struct cifsFileInfo *file,
+		      unsigned long p)
+{
+	struct cifs_tcon *tcon = tlink_tcon(file->tlink);
+	struct cifs_ses *ses = tcon->ses;
+	void __user *arg = (void __user *)p;
+	struct smb_query_info qi, *pqi;
+	int rc = 0;
+	int flags = 0;
+	struct smb_rqst rqst;
+	struct kvec iov[1];
+	struct kvec rsp_iov;
+	int resp_buftype;
+	struct smb2_query_info_rsp *rsp = NULL;
+
+	if (copy_from_user(&qi, arg, sizeof(struct smb_query_info)))
+		return -EFAULT;
+
+	if (!ses || !(ses->server))
+		return -EIO;
+
+	if (smb3_encryption_required(tcon))
+		flags |= CIFS_TRANSFORM_REQ;
+
+	memset(&rqst, 0, sizeof(struct smb_rqst));
+	memset(&iov, 0, sizeof(iov));
+	rqst.rq_iov = iov;
+	rqst.rq_nvec = 1;
+
+	rc = SMB2_query_info_init(tcon, &rqst, file->fid.persistent_fid,
+				  file->fid.volatile_fid,
+				  qi.file_info_class, qi.info_type,
+				  qi.additional_information,
+				  qi.buffer_length);
+	if (rc)
+		goto iqinf_exit;
+
+	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
+	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
+	if (rc)
+		goto iqinf_exit;
+
+	pqi = arg;
+	if (le32_to_cpu(rsp->OutputBufferLength) < qi.buffer_length)
+		qi.buffer_length = le32_to_cpu(rsp->OutputBufferLength);
+	if (copy_to_user(&pqi->buffer_length, &qi.buffer_length,
+			 sizeof(qi.buffer_length))) {
+		rc = -EFAULT;
+		goto iqinf_exit;
+	}
+	if (copy_to_user(pqi + 1, rsp->Buffer, qi.buffer_length)) {
+		rc = -EFAULT;
+		goto iqinf_exit;
+	}
+
+ iqinf_exit:
+	SMB2_query_info_free(&rqst);
+	free_rsp_buf(resp_buftype, rsp);
+	return rc;
+}
+
 static ssize_t
 smb2_copychunk_range(const unsigned int xid,
 			struct cifsFileInfo *srcfile,
@@ -3303,6 +3366,7 @@  struct smb_version_operations smb20_operations = {
 	.set_acl = set_smb2_acl,
 #endif /* CIFS_ACL */
 	.next_header = smb2_next_header,
+	.ioctl_query_info = smb2_ioctl_query_info,
 };
 
 struct smb_version_operations smb21_operations = {
@@ -3398,6 +3462,7 @@  struct smb_version_operations smb21_operations = {
 	.set_acl = set_smb2_acl,
 #endif /* CIFS_ACL */
 	.next_header = smb2_next_header,
+	.ioctl_query_info = smb2_ioctl_query_info,
 };
 
 struct smb_version_operations smb30_operations = {
@@ -3502,6 +3567,7 @@  struct smb_version_operations smb30_operations = {
 	.set_acl = set_smb2_acl,
 #endif /* CIFS_ACL */
 	.next_header = smb2_next_header,
+	.ioctl_query_info = smb2_ioctl_query_info,
 };
 
 struct smb_version_operations smb311_operations = {
@@ -3607,6 +3673,7 @@  struct smb_version_operations smb311_operations = {
 	.set_acl = set_smb2_acl,
 #endif /* CIFS_ACL */
 	.next_header = smb2_next_header,
+	.ioctl_query_info = smb2_ioctl_query_info,
 };
 
 struct smb_version_values smb20_values = {