diff mbox

[CIFS] Fix SMB2 mounts so they don't try to set or get xattrs via cifs

Message ID CAH2r5mtpwr_huqivzVXotQaOA_GHPsz_rrn1QvX+m8QYhskv9A@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Steve French Jan. 27, 2014, 5:59 a.m. UTC
commit 666753c3ef8fc88b0ddd5be4865d0aa66428ac35
Author: Steve French <smfrench@gmail.com>
Date:   Sun Jan 26 23:53:43 2014 -0600

    [CIFS] Fix SMB2 mounts so they don't try to set or get xattrs via cifs

    When mounting with smb2 (or smb2.1 or smb3) we need to check to make
    sure that attempts to query or set extended attributes do not
    attempt to send the request with the older cifs protocol instead
    (eventually we also need to add the support in SMB2
    to query/set extended attributes but this patch prevents us from
    using the wrong protocol for extended attribute operations).

    Signed-off-by: Steve French <smfrench@gmail.com>

     kfree(full_path);
@@ -149,18 +151,22 @@ int cifs_setxattr(struct dentry *direntry, const
char *ea_name,
             cifs_dbg(FYI, "attempt to set cifs inode metadata\n");

         ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
-        rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
-            (__u16)value_size, cifs_sb->local_nls,
-            cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+        if (pTcon->ses->server->ops->set_EA)
+            rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
+                full_path, ea_name, ea_value, (__u16)value_size,
+                cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                    CIFS_MOUNT_MAP_SPECIAL_CHR);
     } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)
            == 0) {
         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
             goto set_ea_exit;

         ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
-        rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
-            (__u16)value_size, cifs_sb->local_nls,
-            cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+        if (pTcon->ses->server->ops->set_EA)
+            rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
+                full_path, ea_name, ea_value, (__u16)value_size,
+                cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                    CIFS_MOUNT_MAP_SPECIAL_CHR);
     } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
             strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
 #ifdef CONFIG_CIFS_ACL
@@ -272,17 +278,21 @@ ssize_t cifs_getxattr(struct dentry *direntry,
const char *ea_name,
             /* revalidate/getattr then populate from inode */
         } /* BB add else when above is implemented */
         ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
-        rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
-            buf_size, cifs_sb->local_nls,
-            cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+        if (pTcon->ses->server->ops->query_all_EAs)
+            rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
+                full_path, ea_name, ea_value, buf_size,
+                cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                    CIFS_MOUNT_MAP_SPECIAL_CHR);
     } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
             goto get_ea_exit;

         ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
-        rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
-            buf_size, cifs_sb->local_nls,
-            cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+        if (pTcon->ses->server->ops->query_all_EAs)
+            rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
+                full_path, ea_name, ea_value, buf_size,
+                cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                    CIFS_MOUNT_MAP_SPECIAL_CHR);
     } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
               strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
 #ifdef CONFIG_CIFS_POSIX
@@ -400,11 +410,12 @@ ssize_t cifs_listxattr(struct dentry *direntry,
char *data, size_t buf_size)
     /* if proc/fs/cifs/streamstoxattr is set then
         search server for EAs or streams to
         returns as xattrs */
-    rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data,
-                buf_size, cifs_sb->local_nls,
-                cifs_sb->mnt_cifs_flags &
-                    CIFS_MOUNT_MAP_SPECIAL_CHR);

+    if (pTcon->ses->server->ops->query_all_EAs)
+        rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
+                full_path, NULL, data, buf_size,
+                cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                    CIFS_MOUNT_MAP_SPECIAL_CHR);
 list_ea_exit:
     kfree(full_path);
     free_xid(xid);
diff mbox

Patch

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 61228b7..a245d18 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -389,6 +389,12 @@  struct smb_version_operations {
             struct cifsFileInfo *target_file, u64 src_off, u64 len,
             u64 dest_off);
     int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
+    ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *,
+            const unsigned char *, const unsigned char *, char *,
+            size_t, const struct nls_table *, int);
+    int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
+            const char *, const void *, const __u16,
+            const struct nls_table *, int);
 };

 struct smb_version_values {
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 09afda4..95c43bb 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -82,9 +82,11 @@  int cifs_removexattr(struct dentry *direntry, const
char *ea_name)
             goto remove_ea_exit;

         ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
-        rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,
-            (__u16)0, cifs_sb->local_nls,
-            cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+        if (pTcon->ses->server->ops->set_EA)
+            rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
+                full_path, ea_name, NULL, (__u16)0,
+                cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+                    CIFS_MOUNT_MAP_SPECIAL_CHR);
     }
 remove_ea_exit: