Re: [PATCH] cifs: add IOCTL for QUERY_INFO passthrough to userspace

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx> 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@xxxxxxxxxx>
> To: "linux-cifs" <linux-cifs@xxxxxxxxxxxxxxx>
> Cc: "Steve French" <smfrench@xxxxxxxxx>
> 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@xxxxxxxxxx>
> ---
>  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
>


-- 
Thanks,

Steve



[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux