OSDN Git Service

cifs: Parse owner/group for stat in smb311 posix extensions
authorVolker Lendecke <vl@samba.org>
Fri, 25 Nov 2022 11:37:44 +0000 (12:37 +0100)
committerSteve French <stfrench@microsoft.com>
Thu, 8 Dec 2022 15:51:53 +0000 (09:51 -0600)
stat was returning default owner and group (unlike readdir)
for SMB3.1.1 POSIX extensions

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/inode.c
fs/cifs/smb2inode.c
fs/cifs/smb2proto.h

index 4e2ca3c..286a540 100644 (file)
@@ -632,6 +632,8 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
 
 /* Fill a cifs_fattr struct with info from POSIX info struct */
 static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data,
+                                      struct cifs_sid *owner,
+                                      struct cifs_sid *group,
                                       struct super_block *sb, bool adjust_tz, bool symlink)
 {
        struct smb311_posix_qinfo *info = &data->posix_fi;
@@ -680,8 +682,8 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_ope
        }
        /* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */
 
-       fattr->cf_uid = cifs_sb->ctx->linux_uid; /* TODO: map uid and gid from SID */
-       fattr->cf_gid = cifs_sb->ctx->linux_gid;
+       sid_to_id(cifs_sb, owner, fattr, SIDOWNER);
+       sid_to_id(cifs_sb, group, fattr, SIDGROUP);
 
        cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
                fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
@@ -1175,6 +1177,7 @@ smb311_posix_get_inode_info(struct inode **inode,
        struct cifs_fattr fattr = {0};
        bool symlink = false;
        struct cifs_open_info_data data = {};
+       struct cifs_sid owner, group;
        int rc = 0;
        int tmprc = 0;
 
@@ -1192,7 +1195,8 @@ smb311_posix_get_inode_info(struct inode **inode,
                goto out;
        }
 
-       rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, full_path, &data, &adjust_tz,
+       rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, full_path, &data,
+                                         &owner, &group, &adjust_tz,
                                          &symlink);
 
        /*
@@ -1201,7 +1205,8 @@ smb311_posix_get_inode_info(struct inode **inode,
 
        switch (rc) {
        case 0:
-               smb311_posix_info_to_fattr(&fattr, &data, sb, adjust_tz, symlink);
+               smb311_posix_info_to_fattr(&fattr, &data, &owner, &group,
+                                          sb, adjust_tz, symlink);
                break;
        case -EREMOTE:
                /* DFS link, no metadata available on this server */
index 1be86ba..fbd46db 100644 (file)
@@ -431,6 +431,21 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                                &rsp_iov[1], sizeof(idata->posix_fi) /* add SIDs */,
                                (char *)&idata->posix_fi);
                }
+               if (rc == 0) {
+                       unsigned int length = le32_to_cpu(qi_rsp->OutputBufferLength);
+
+                       if (length > sizeof(idata->posix_fi)) {
+                               char *base = (char *)rsp_iov[1].iov_base +
+                                       le16_to_cpu(qi_rsp->OutputBufferOffset) +
+                                       sizeof(idata->posix_fi);
+                               *extbuflen = length - sizeof(idata->posix_fi);
+                               *extbuf = kmemdup(base, *extbuflen, GFP_KERNEL);
+                               if (!*extbuf)
+                                       rc = -ENOMEM;
+                       } else {
+                               rc = -EINVAL;
+                       }
+               }
                if (rqst[1].rq_iov)
                        SMB2_query_info_free(&rqst[1]);
                if (rqst[2].rq_iov)
@@ -569,13 +584,20 @@ out:
 
 int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
                                 struct cifs_sb_info *cifs_sb, const char *full_path,
-                                struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse)
+                                struct cifs_open_info_data *data,
+                                struct cifs_sid *owner,
+                                struct cifs_sid *group,
+                                bool *adjust_tz, bool *reparse)
 {
        int rc;
        __u32 create_options = 0;
        struct cifsFileInfo *cfile;
        struct kvec err_iov[3] = {};
        int err_buftype[3] = {};
+       __u8 *sidsbuf = NULL;
+       __u8 *sidsbuf_end = NULL;
+       size_t sidsbuflen = 0;
+       size_t owner_len, group_len;
 
        *adjust_tz = false;
        *reparse = false;
@@ -590,7 +612,7 @@ int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
        cifs_get_readable_path(tcon, full_path, &cfile);
        rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
                              create_options, ACL_NO_MODE, data, SMB2_OP_POSIX_QUERY_INFO, cfile,
-                             NULL, NULL, err_iov, err_buftype);
+                             &sidsbuf, &sidsbuflen, err_iov, err_buftype);
        if (rc == -EOPNOTSUPP) {
                /* BB TODO: When support for special files added to Samba re-verify this path */
                if (err_iov[0].iov_base && err_buftype[0] != CIFS_NO_BUFFER &&
@@ -607,10 +629,31 @@ int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
                cifs_get_readable_path(tcon, full_path, &cfile);
                rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES,
                                      FILE_OPEN, create_options, ACL_NO_MODE, data,
-                                     SMB2_OP_POSIX_QUERY_INFO, cfile, NULL, NULL, NULL, NULL);
+                                     SMB2_OP_POSIX_QUERY_INFO, cfile,
+                                     &sidsbuf, &sidsbuflen, NULL, NULL);
+       }
+
+       if (rc == 0) {
+               sidsbuf_end = sidsbuf + sidsbuflen;
+
+               owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end);
+               if (owner_len == -1) {
+                       rc = -EINVAL;
+                       goto out;
+               }
+               memcpy(owner, sidsbuf, owner_len);
+
+               group_len = posix_info_sid_size(
+                       sidsbuf + owner_len, sidsbuf_end);
+               if (group_len == -1) {
+                       rc = -EINVAL;
+                       goto out;
+               }
+               memcpy(group, sidsbuf + owner_len, group_len);
        }
 
 out:
+       kfree(sidsbuf);
        free_rsp_buf(err_buftype[0], err_iov[0].iov_base);
        free_rsp_buf(err_buftype[1], err_iov[1].iov_base);
        free_rsp_buf(err_buftype[2], err_iov[2].iov_base);
index be21b5d..d5d7ffb 100644 (file)
@@ -277,7 +277,10 @@ extern int smb2_query_info_compound(const unsigned int xid,
 /* query path info from the server using SMB311 POSIX extensions*/
 int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
                                 struct cifs_sb_info *cifs_sb, const char *full_path,
-                                struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);
+                                struct cifs_open_info_data *data,
+                                struct cifs_sid *owner,
+                                struct cifs_sid *group,
+                                bool *adjust_tz, bool *reparse);
 int posix_info_parse(const void *beg, const void *end,
                     struct smb2_posix_info_parsed *out);
 int posix_info_sid_size(const void *beg, const void *end);