Merge tag '4.3-rc-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 18 Jul 2019 18:11:51 +0000 (11:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 18 Jul 2019 18:11:51 +0000 (11:11 -0700)
Pull cifs updates from Steve French:
 "Fixes (three for stable) and improvements including much faster
  encryption (SMB3.1.1 GCM)"

* tag '4.3-rc-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: (27 commits)
  smb3: smbdirect no longer experimental
  cifs: fix crash in smb2_compound_op()/smb2_set_next_command()
  cifs: fix crash in cifs_dfs_do_automount
  cifs: fix parsing of symbolic link error response
  cifs: refactor and clean up arguments in the reparse point parsing
  SMB3: query inode number on open via create context
  smb3: Send netname context during negotiate protocol
  smb3: do not send compression info by default
  smb3: add new mount option to retrieve mode from special ACE
  smb3: Allow query of symlinks stored as reparse points
  cifs: Fix a race condition with cifs_echo_request
  cifs: always add credits back for unsolicited PDUs
  fs: cifs: cifsssmb: Change return type of convert_ace_to_cifs_ace
  add some missing definitions
  cifs: fix typo in debug message with struct field ia_valid
  smb3: minor cleanup of compound_send_recv
  CIFS: Fix module dependency
  cifs: simplify code by removing CONFIG_CIFS_ACL ifdef
  cifs: Fix check for matching with existing mount
  cifs: Properly handle auto disabling of serverino option
  ...

19 files changed:
fs/cifs/Kconfig
fs/cifs/Makefile
fs/cifs/cifs_debug.c
fs/cifs/cifs_fs_sb.h
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dfs_cache.c
fs/cifs/inode.c
fs/cifs/misc.c
fs/cifs/smb1ops.c
fs/cifs/smb2inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/smb2transport.c
fs/cifs/transport.c
fs/cifs/xattr.c

index 523e9ea78a285361bc23a17852e3579c9811c847..b16219e5dac91b2e26fbb98e5c8afb238de47ec4 100644 (file)
@@ -13,9 +13,11 @@ config CIFS
        select CRYPTO_LIB_ARC4
        select CRYPTO_AEAD2
        select CRYPTO_CCM
+       select CRYPTO_GCM
        select CRYPTO_ECB
        select CRYPTO_AES
        select CRYPTO_DES
+       select KEYS
        help
          This is the client VFS module for the SMB3 family of NAS protocols,
          (including support for the most recent, most secure dialect SMB3.1.1)
@@ -109,7 +111,7 @@ config CIFS_WEAK_PW_HASH
 
 config CIFS_UPCALL
        bool "Kerberos/SPNEGO advanced session setup"
-       depends on CIFS && KEYS
+       depends on CIFS
        select DNS_RESOLVER
        help
          Enables an upcall mechanism for CIFS which accesses userspace helper
@@ -144,14 +146,6 @@ config CIFS_POSIX
          (such as Samba 3.10 and later) which can negotiate
          CIFS POSIX ACL support.  If unsure, say N.
 
-config CIFS_ACL
-       bool "Provide CIFS ACL support"
-       depends on CIFS_XATTR && KEYS
-       help
-         Allows fetching CIFS/NTFS ACL from the server.  The DACL blob
-         is handed over to the application/caller.  See the man
-         page for getcifsacl for more information.  If unsure, say Y.
-
 config CIFS_DEBUG
        bool "Enable CIFS debugging routines"
        default y
@@ -184,7 +178,7 @@ config CIFS_DEBUG_DUMP_KEYS
 
 config CIFS_DFS_UPCALL
        bool "DFS feature support"
-       depends on CIFS && KEYS
+       depends on CIFS
        select DNS_RESOLVER
        help
          Distributed File System (DFS) support is used to access shares
@@ -203,10 +197,10 @@ config CIFS_NFSD_EXPORT
          Allows NFS server to export a CIFS mounted share (nfsd over cifs)
 
 config CIFS_SMB_DIRECT
-       bool "SMB Direct support (Experimental)"
+       bool "SMB Direct support"
        depends on CIFS=m && INFINIBAND && INFINIBAND_ADDR_TRANS || CIFS=y && INFINIBAND=y && INFINIBAND_ADDR_TRANS=y
        help
-         Enables SMB Direct experimental support for SMB 3.0, 3.02 and 3.1.1.
+         Enables SMB Direct support for SMB 3.0, 3.02 and 3.1.1.
          SMB Direct allows transferring SMB packets over RDMA. If unsure,
          say N.
 
index 51af69a1a3286f036758af53c92cbd7373334d33..41332f20055b852bbac6453f6660cae371cba385 100644 (file)
@@ -10,10 +10,9 @@ cifs-y := trace.o cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o \
          cifs_unicode.o nterr.o cifsencrypt.o \
          readdir.o ioctl.o sess.o export.o smb1ops.o winucase.o \
          smb2ops.o smb2maperror.o smb2transport.o \
-         smb2misc.o smb2pdu.o smb2inode.o smb2file.o
+         smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o
 
 cifs-$(CONFIG_CIFS_XATTR) += xattr.o
-cifs-$(CONFIG_CIFS_ACL) += cifsacl.o
 
 cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
 
index ec933fb0b36e652e5bf1e307e8330f998602c134..a38d796f5ffeee838d912fd3201a0fa83d424d2c 100644 (file)
@@ -240,9 +240,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
 #ifdef CONFIG_CIFS_XATTR
        seq_printf(m, ",XATTR");
 #endif
-#ifdef CONFIG_CIFS_ACL
        seq_printf(m, ",ACL");
-#endif
        seq_putc(m, '\n');
        seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
        seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
index ed49222abecb467f9b4a7a8b7e68e06aa6fa46ac..b326d2ca3765784c95d7a54faf06b72365675923 100644 (file)
@@ -52,6 +52,7 @@
 #define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */
 #define CIFS_MOUNT_NO_HANDLE_CACHE 0x4000000 /* disable caching dir handles */
 #define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */
+#define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */
 
 struct cifs_sb_info {
        struct rb_root tlink_tree;
@@ -83,5 +84,10 @@ struct cifs_sb_info {
         * failover properly.
         */
        char *origin_fullpath; /* \\HOST\SHARE\[OPTIONAL PATH] */
+       /*
+        * Indicate whether serverino option was turned off later
+        * (cifs_autodisable_serverino) in order to match new mounts.
+        */
+       bool mnt_cifs_serverino_autodisabled;
 };
 #endif                         /* _CIFS_FS_SB_H */
index 24635b65effa7848005c815a955ea029270c6f5f..270d3c58fb3b2ac0917d3d40f6083d2d8558b6a0 100644 (file)
@@ -526,6 +526,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
                seq_puts(s, ",nobrl");
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_HANDLE_CACHE)
                seq_puts(s, ",nohandlecache");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
+               seq_puts(s, ",modefromsid");
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
                seq_puts(s, ",cifsacl");
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
@@ -554,6 +556,11 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
        seq_printf(s, ",bsize=%u", cifs_sb->bsize);
        seq_printf(s, ",echo_interval=%lu",
                        tcon->ses->server->echo_interval / HZ);
+
+       /* Only display max_credits if it was overridden on mount */
+       if (tcon->ses->server->max_credits != SMB2_MAX_CREDITS_AVAILABLE)
+               seq_printf(s, ",max_credits=%u", tcon->ses->server->max_credits);
+
        if (tcon->snapshot_time)
                seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
        if (tcon->handle_timeout)
@@ -1517,11 +1524,9 @@ init_cifs(void)
                goto out_destroy_dfs_cache;
 #endif /* CONFIG_CIFS_UPCALL */
 
-#ifdef CONFIG_CIFS_ACL
        rc = init_cifs_idmap();
        if (rc)
                goto out_register_key_type;
-#endif /* CONFIG_CIFS_ACL */
 
        rc = register_filesystem(&cifs_fs_type);
        if (rc)
@@ -1536,10 +1541,8 @@ init_cifs(void)
        return 0;
 
 out_init_cifs_idmap:
-#ifdef CONFIG_CIFS_ACL
        exit_cifs_idmap();
 out_register_key_type:
-#endif
 #ifdef CONFIG_CIFS_UPCALL
        exit_cifs_spnego();
 out_destroy_dfs_cache:
@@ -1571,9 +1574,7 @@ exit_cifs(void)
        unregister_filesystem(&cifs_fs_type);
        unregister_filesystem(&smb3_fs_type);
        cifs_dfs_release_automount_timer();
-#ifdef CONFIG_CIFS_ACL
        exit_cifs_idmap();
-#endif
 #ifdef CONFIG_CIFS_UPCALL
        exit_cifs_spnego();
 #endif
@@ -1607,5 +1608,6 @@ MODULE_SOFTDEP("pre: sha256");
 MODULE_SOFTDEP("pre: sha512");
 MODULE_SOFTDEP("pre: aead2");
 MODULE_SOFTDEP("pre: ccm");
+MODULE_SOFTDEP("pre: gcm");
 module_init(init_cifs)
 module_exit(exit_cifs)
index 4777b3c4a92c41f53330a603a810041c367e05df..fe610e7e3670ff3fd57ccbdbf6c396cc21a0610f 100644 (file)
@@ -550,6 +550,7 @@ struct smb_vol {
        bool override_gid:1;
        bool dynperm:1;
        bool noperm:1;
+       bool mode_ace:1;
        bool no_psx_acl:1; /* set if posix acl support should be disabled */
        bool cifs_acl:1;
        bool backupuid_specified; /* mount option  backupuid  is specified */
@@ -600,6 +601,7 @@ struct smb_vol {
        __u64 snapshot_time; /* needed for timewarp tokens */
        __u32 handle_timeout; /* persistent and durable handle timeout in ms */
        unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
+       __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
 };
 
 /**
@@ -617,7 +619,8 @@ struct smb_vol {
                         CIFS_MOUNT_FSCACHE | CIFS_MOUNT_MF_SYMLINKS | \
                         CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \
                         CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \
-                        CIFS_MOUNT_NO_DFS)
+                        CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \
+                        CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID)
 
 /**
  * Generic VFS superblock mount flags (s_flags) to consider when
@@ -1870,7 +1873,6 @@ extern unsigned int cifs_min_small;  /* min size of small buf pool */
 extern unsigned int cifs_max_pending; /* MAX requests at once to server*/
 extern bool disable_legacy_dialects;  /* forbid vers=1.0 and vers=2.0 mounts */
 
-#ifdef CONFIG_CIFS_ACL
 GLOBAL_EXTERN struct rb_root uidtree;
 GLOBAL_EXTERN struct rb_root gidtree;
 GLOBAL_EXTERN spinlock_t siduidlock;
@@ -1879,7 +1881,6 @@ GLOBAL_EXTERN struct rb_root siduidtree;
 GLOBAL_EXTERN struct rb_root sidgidtree;
 GLOBAL_EXTERN spinlock_t uidsidlock;
 GLOBAL_EXTERN spinlock_t gidsidlock;
-#endif /* CONFIG_CIFS_ACL */
 
 void cifs_oplock_break(struct work_struct *work);
 void cifs_queue_oplock_break(struct cifsFileInfo *cfile);
index 1fbd92843a73bc8899e47b1f50a6461a32eb06fa..e2f95965065d1d7fd42c8116d0d57cecb097bd6c 100644 (file)
@@ -3600,11 +3600,9 @@ static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
        return size;
 }
 
-static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
+static void convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
                                     const struct posix_acl_xattr_entry *local_ace)
 {
-       __u16 rc = 0; /* 0 = ACL converted ok */
-
        cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
        cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
        /* BB is there a better way to handle the large uid? */
@@ -3617,7 +3615,6 @@ static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
        cifs_dbg(FYI, "perm %d tag %d id %d\n",
                 ace->e_perm, ace->e_tag, ace->e_id);
 */
-       return rc;
 }
 
 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
@@ -3653,13 +3650,8 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
                cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
                return 0;
        }
-       for (i = 0; i < count; i++) {
-               rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
-               if (rc != 0) {
-                       /* ACE not converted */
-                       break;
-               }
-       }
+       for (i = 0; i < count; i++)
+               convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
        if (rc == 0) {
                rc = (__u16)(count * sizeof(struct cifs_posix_ace));
                rc += sizeof(struct cifs_posix_acl);
@@ -3920,7 +3912,6 @@ GetExtAttrOut:
 
 #endif /* CONFIG_POSIX */
 
-#ifdef CONFIG_CIFS_ACL
 /*
  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
  * all NT TRANSACTS that we init here have total parm and data under about 400
@@ -4164,7 +4155,6 @@ setCifsAclRetry:
        return (rc);
 }
 
-#endif /* CONFIG_CIFS_ACL */
 
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
index 714a359c7c8de6fc0c1fb9cecafb695d590b4c28..a4830ced0f9899c35c89609b2ea25330a06693bd 100644 (file)
@@ -96,7 +96,8 @@ enum {
        Opt_multiuser, Opt_sloppy, Opt_nosharesock,
        Opt_persistent, Opt_nopersistent,
        Opt_resilient, Opt_noresilient,
-       Opt_domainauto, Opt_rdma,
+       Opt_domainauto, Opt_rdma, Opt_modesid,
+       Opt_compress,
 
        /* Mount options which take numeric value */
        Opt_backupuid, Opt_backupgid, Opt_uid,
@@ -175,6 +176,7 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_serverino, "serverino" },
        { Opt_noserverino, "noserverino" },
        { Opt_rwpidforward, "rwpidforward" },
+       { Opt_modesid, "modefromsid" },
        { Opt_cifsacl, "cifsacl" },
        { Opt_nocifsacl, "nocifsacl" },
        { Opt_acl, "acl" },
@@ -212,6 +214,7 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_echo_interval, "echo_interval=%s" },
        { Opt_max_credits, "max_credits=%s" },
        { Opt_snapshot, "snapshot=%s" },
+       { Opt_compress, "compress=%s" },
 
        { Opt_blank_user, "user=" },
        { Opt_blank_user, "username=" },
@@ -706,10 +709,10 @@ static bool
 server_unresponsive(struct TCP_Server_Info *server)
 {
        /*
-        * We need to wait 2 echo intervals to make sure we handle such
+        * We need to wait 3 echo intervals to make sure we handle such
         * situations right:
         * 1s  client sends a normal SMB request
-        * 2s  client gets a response
+        * 3s  client gets a response
         * 30s echo workqueue job pops, and decides we got a response recently
         *     and don't need to send another
         * ...
@@ -718,9 +721,9 @@ server_unresponsive(struct TCP_Server_Info *server)
         */
        if ((server->tcpStatus == CifsGood ||
            server->tcpStatus == CifsNeedNegotiate) &&
-           time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
+           time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
                cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
-                        server->hostname, (2 * server->echo_interval) / HZ);
+                        server->hostname, (3 * server->echo_interval) / HZ);
                cifs_reconnect(server);
                wake_up(&server->response_q);
                return true;
@@ -1223,11 +1226,11 @@ next_pdu:
                                         atomic_read(&midCount));
                                cifs_dump_mem("Received Data is: ", bufs[i],
                                              HEADER_SIZE(server));
+                               smb2_add_credits_from_hdr(bufs[i], server);
 #ifdef CONFIG_CIFS_DEBUG2
                                if (server->ops->dump_detail)
                                        server->ops->dump_detail(bufs[i],
                                                                 server);
-                               smb2_add_credits_from_hdr(bufs[i], server);
                                cifs_dump_mids(server);
 #endif /* CIFS_DEBUG2 */
                        }
@@ -1830,6 +1833,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_rwpidforward:
                        vol->rwpidforward = 1;
                        break;
+               case Opt_modesid:
+                       vol->mode_ace = 1;
+                       break;
                case Opt_cifsacl:
                        vol->cifs_acl = 1;
                        break;
@@ -1911,6 +1917,11 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_rdma:
                        vol->rdma = true;
                        break;
+               case Opt_compress:
+                       vol->compression = UNKNOWN_TYPE;
+                       cifs_dbg(VFS,
+                               "SMB3 compression support is experimental\n");
+                       break;
 
                /* Numeric Values */
                case Opt_backupuid:
@@ -2544,8 +2555,15 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
        if (vol->nosharesock)
                return 0;
 
-       /* BB update this for smb3any and default case */
-       if ((server->vals != vol->vals) || (server->ops != vol->ops))
+       /* If multidialect negotiation see if existing sessions match one */
+       if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
+               if (server->vals->protocol_id < SMB30_PROT_ID)
+                       return 0;
+       } else if (strcmp(vol->vals->version_string,
+                  SMBDEFAULT_VERSION_STRING) == 0) {
+               if (server->vals->protocol_id < SMB21_PROT_ID)
+                       return 0;
+       } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
                return 0;
 
        if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
@@ -2680,6 +2698,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
        tcp_ses->sequence_number = 0;
        tcp_ses->reconnect_instance = 1;
        tcp_ses->lstrp = jiffies;
+       tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
        spin_lock_init(&tcp_ses->req_lock);
        INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
        INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
@@ -3460,12 +3479,16 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
 {
        struct cifs_sb_info *old = CIFS_SB(sb);
        struct cifs_sb_info *new = mnt_data->cifs_sb;
+       unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
+       unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
 
        if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
                return 0;
 
-       if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
-           (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
+       if (old->mnt_cifs_serverino_autodisabled)
+               newflags &= ~CIFS_MOUNT_SERVER_INUM;
+
+       if (oldflags != newflags)
                return 0;
 
        /*
@@ -3965,6 +3988,8 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
        if (pvolume_info->rwpidforward)
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
+       if (pvolume_info->mode_ace)
+               cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
        if (pvolume_info->cifs_acl)
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
        if (pvolume_info->backupuid_specified) {
@@ -4459,11 +4484,13 @@ cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
                                        unsigned int xid,
                                        struct cifs_tcon *tcon,
                                        struct cifs_sb_info *cifs_sb,
-                                       char *full_path)
+                                       char *full_path,
+                                       int added_treename)
 {
        int rc;
        char *s;
        char sep, tmp;
+       int skip = added_treename ? 1 : 0;
 
        sep = CIFS_DIR_SEP(cifs_sb);
        s = full_path;
@@ -4478,7 +4505,14 @@ cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
                /* next separator */
                while (*s && *s != sep)
                        s++;
-
+               /*
+                * if the treename is added, we then have to skip the first
+                * part within the separators
+                */
+               if (skip) {
+                       skip = 0;
+                       continue;
+               }
                /*
                 * temporarily null-terminate the path at the end of
                 * the current component
@@ -4526,8 +4560,7 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
 
        if (rc != -EREMOTE) {
                rc = cifs_are_all_path_components_accessible(server, xid, tcon,
-                                                            cifs_sb,
-                                                            full_path);
+                       cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
                if (rc != 0) {
                        cifs_dbg(VFS, "cannot query dirs between root and final path, "
                                 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
index e3e1c13df4391ea5b45782b0cfb691d34da3d2ee..1692c0c6c23ae503f45a3239c2e7ba4ae2a54a1b 100644 (file)
@@ -492,7 +492,7 @@ static struct dfs_cache_entry *__find_cache_entry(unsigned int hash,
 #ifdef CONFIG_CIFS_DEBUG2
                        char *name = get_tgt_name(ce);
 
-                       if (unlikely(IS_ERR(name))) {
+                       if (IS_ERR(name)) {
                                rcu_read_unlock();
                                return ERR_CAST(name);
                        }
index d7cc622526343dd6af9ec9ff7a83238a54b568dc..1bffe029fb6633c1443484fae69214c8efc64222 100644 (file)
@@ -892,7 +892,6 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
                        cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
        }
 
-#ifdef CONFIG_CIFS_ACL
        /* fill in 0777 bits from ACL */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
@@ -902,7 +901,6 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
                        goto cgii_exit;
                }
        }
-#endif /* CONFIG_CIFS_ACL */
 
        /* fill in remaining high mode bits e.g. SUID, VTX */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
@@ -2415,7 +2413,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 
        xid = get_xid();
 
-       cifs_dbg(FYI, "setattr on file %pd attrs->iavalid 0x%x\n",
+       cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
                 direntry, attrs->ia_valid);
 
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
@@ -2466,7 +2464,6 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
        if (attrs->ia_valid & ATTR_GID)
                gid = attrs->ia_gid;
 
-#ifdef CONFIG_CIFS_ACL
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                if (uid_valid(uid) || gid_valid(gid)) {
                        rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
@@ -2478,7 +2475,6 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
                        }
                }
        } else
-#endif /* CONFIG_CIFS_ACL */
        if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
                attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
 
@@ -2489,7 +2485,6 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
        if (attrs->ia_valid & ATTR_MODE) {
                mode = attrs->ia_mode;
                rc = 0;
-#ifdef CONFIG_CIFS_ACL
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                        rc = id_mode_to_cifs_acl(inode, full_path, mode,
                                                INVALID_UID, INVALID_GID);
@@ -2499,7 +2494,6 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
                                goto cifs_setattr_exit;
                        }
                } else
-#endif /* CONFIG_CIFS_ACL */
                if (((mode & S_IWUGO) == 0) &&
                    (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
 
index b1a696a73f7c014ae0044a7e2c721c45cc4ab10e..f383877a65117d5d42f40e99eae9c8127dcf8747 100644 (file)
@@ -539,6 +539,7 @@ cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
                        tcon = cifs_sb_master_tcon(cifs_sb);
 
                cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
+               cifs_sb->mnt_cifs_serverino_autodisabled = true;
                cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s.\n",
                         tcon ? tcon->treeName : "new server");
                cifs_dbg(VFS, "The server doesn't seem to support them properly or the files might be on different servers (DFS).\n");
index 9e430ae9314fd7a8eae349632228d8bd4411a287..b7421a0963195137474d9e3a15075796743c6157 100644 (file)
@@ -1223,16 +1223,15 @@ struct smb_version_operations smb1_operations = {
        .query_all_EAs = CIFSSMBQAllEAs,
        .set_EA = CIFSSMBSetEA,
 #endif /* CIFS_XATTR */
-#ifdef CONFIG_CIFS_ACL
        .get_acl = get_cifs_acl,
        .get_acl_by_fid = get_cifs_acl_by_fid,
        .set_acl = set_cifs_acl,
-#endif /* CIFS_ACL */
        .make_node = cifs_make_node,
 };
 
 struct smb_version_values smb1_values = {
        .version_string = SMB1_VERSION_STRING,
+       .protocol_id = SMB10_PROT_ID,
        .large_lock_type = LOCKING_ANDX_LARGE_FILES,
        .exclusive_lock_type = 0,
        .shared_lock_type = LOCKING_ANDX_SHARED_LOCK,
index 278405d26c47e9f0f0cc6b4361af911a1fb1bd9e..d8d9cdfa30b6bcbcfd8bc73646c0270a61ad0094 100644 (file)
@@ -120,6 +120,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                                SMB2_O_INFO_FILE, 0,
                                sizeof(struct smb2_file_all_info) +
                                          PATH_MAX * 2, 0, NULL);
+               if (rc)
+                       goto finished;
                smb2_set_next_command(tcon, &rqst[num_rqst]);
                smb2_set_related(&rqst[num_rqst++]);
                trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,
@@ -147,6 +149,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                                        COMPOUND_FID, current->tgid,
                                        FILE_DISPOSITION_INFORMATION,
                                        SMB2_O_INFO_FILE, 0, data, size);
+               if (rc)
+                       goto finished;
                smb2_set_next_command(tcon, &rqst[num_rqst]);
                smb2_set_related(&rqst[num_rqst++]);
                trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path);
@@ -163,6 +167,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                                        COMPOUND_FID, current->tgid,
                                        FILE_END_OF_FILE_INFORMATION,
                                        SMB2_O_INFO_FILE, 0, data, size);
+               if (rc)
+                       goto finished;
                smb2_set_next_command(tcon, &rqst[num_rqst]);
                smb2_set_related(&rqst[num_rqst++]);
                trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
@@ -180,6 +186,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                                        COMPOUND_FID, current->tgid,
                                        FILE_BASIC_INFORMATION,
                                        SMB2_O_INFO_FILE, 0, data, size);
+               if (rc)
+                       goto finished;
                smb2_set_next_command(tcon, &rqst[num_rqst]);
                smb2_set_related(&rqst[num_rqst++]);
                trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid,
@@ -206,6 +214,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                                        COMPOUND_FID, current->tgid,
                                        FILE_RENAME_INFORMATION,
                                        SMB2_O_INFO_FILE, 0, data, size);
+               if (rc)
+                       goto finished;
                smb2_set_next_command(tcon, &rqst[num_rqst]);
                smb2_set_related(&rqst[num_rqst++]);
                trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
@@ -231,6 +241,8 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                                        COMPOUND_FID, current->tgid,
                                        FILE_LINK_INFORMATION,
                                        SMB2_O_INFO_FILE, 0, data, size);
+               if (rc)
+                       goto finished;
                smb2_set_next_command(tcon, &rqst[num_rqst]);
                smb2_set_related(&rqst[num_rqst++]);
                trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path);
index 9fd56b0acd7e2fb73e92017ba41ea6a992c50ee9..0cdc4e47ca875fc7f9bd4f3fb2af2b64e897362c 100644 (file)
@@ -2027,6 +2027,10 @@ smb2_set_related(struct smb_rqst *rqst)
        struct smb2_sync_hdr *shdr;
 
        shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base);
+       if (shdr == NULL) {
+               cifs_dbg(FYI, "shdr NULL in smb2_set_related\n");
+               return;
+       }
        shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
 }
 
@@ -2041,6 +2045,12 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
        unsigned long len = smb_rqst_len(server, rqst);
        int i, num_padding;
 
+       shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base);
+       if (shdr == NULL) {
+               cifs_dbg(FYI, "shdr NULL in smb2_set_next_command\n");
+               return;
+       }
+
        /* SMB headers in a compound are 8 byte aligned. */
 
        /* No padding needed */
@@ -2080,7 +2090,6 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
        }
 
  finished:
-       shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base);
        shdr->NextCommand = cpu_to_le32(len);
 }
 
@@ -2373,6 +2382,34 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
        return rc;
 }
 
+static int
+parse_reparse_posix(struct reparse_posix_data *symlink_buf,
+                     u32 plen, char **target_path,
+                     struct cifs_sb_info *cifs_sb)
+{
+       unsigned int len;
+
+       /* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */
+       len = le16_to_cpu(symlink_buf->ReparseDataLength);
+
+       if (le64_to_cpu(symlink_buf->InodeType) != NFS_SPECFILE_LNK) {
+               cifs_dbg(VFS, "%lld not a supported symlink type\n",
+                       le64_to_cpu(symlink_buf->InodeType));
+               return -EOPNOTSUPP;
+       }
+
+       *target_path = cifs_strndup_from_utf16(
+                               symlink_buf->PathBuffer,
+                               len, true, cifs_sb->local_nls);
+       if (!(*target_path))
+               return -ENOMEM;
+
+       convert_delimiter(*target_path, '/');
+       cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+
+       return 0;
+}
+
 static int
 parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf,
                      u32 plen, char **target_path,
@@ -2381,11 +2418,7 @@ parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf,
        unsigned int sub_len;
        unsigned int sub_offset;
 
-       /* We only handle Symbolic Link : MS-FSCC 2.1.2.4 */
-       if (le32_to_cpu(symlink_buf->ReparseTag) != IO_REPARSE_TAG_SYMLINK) {
-               cifs_dbg(VFS, "srv returned invalid symlink buffer\n");
-               return -EIO;
-       }
+       /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */
 
        sub_offset = le16_to_cpu(symlink_buf->SubstituteNameOffset);
        sub_len = le16_to_cpu(symlink_buf->SubstituteNameLength);
@@ -2407,6 +2440,41 @@ parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf,
        return 0;
 }
 
+static int
+parse_reparse_point(struct reparse_data_buffer *buf,
+                   u32 plen, char **target_path,
+                   struct cifs_sb_info *cifs_sb)
+{
+       if (plen < sizeof(struct reparse_data_buffer)) {
+               cifs_dbg(VFS, "reparse buffer is too small. Must be "
+                        "at least 8 bytes but was %d\n", plen);
+               return -EIO;
+       }
+
+       if (plen < le16_to_cpu(buf->ReparseDataLength) +
+           sizeof(struct reparse_data_buffer)) {
+               cifs_dbg(VFS, "srv returned invalid reparse buf "
+                        "length: %d\n", plen);
+               return -EIO;
+       }
+
+       /* See MS-FSCC 2.1.2 */
+       switch (le32_to_cpu(buf->ReparseTag)) {
+       case IO_REPARSE_TAG_NFS:
+               return parse_reparse_posix(
+                       (struct reparse_posix_data *)buf,
+                       plen, target_path, cifs_sb);
+       case IO_REPARSE_TAG_SYMLINK:
+               return parse_reparse_symlink(
+                       (struct reparse_symlink_data_buffer *)buf,
+                       plen, target_path, cifs_sb);
+       default:
+               cifs_dbg(VFS, "srv returned unknown symlink buffer "
+                        "tag:0x%08x\n", le32_to_cpu(buf->ReparseTag));
+               return -EOPNOTSUPP;
+       }
+}
+
 #define SMB2_SYMLINK_STRUCT_SIZE \
        (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
 
@@ -2533,23 +2601,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
                        goto querty_exit;
                }
 
-               if (plen < 8) {
-                       cifs_dbg(VFS, "reparse buffer is too small. Must be "
-                                "at least 8 bytes but was %d\n", plen);
-                       rc = -EIO;
-                       goto querty_exit;
-               }
-
-               if (plen < le16_to_cpu(reparse_buf->ReparseDataLength) + 8) {
-                       cifs_dbg(VFS, "srv returned invalid reparse buf "
-                                "length: %d\n", plen);
-                       rc = -EIO;
-                       goto querty_exit;
-               }
-
-               rc = parse_reparse_symlink(
-                       (struct reparse_symlink_data_buffer *)reparse_buf,
-                       plen, target_path, cifs_sb);
+               rc = parse_reparse_point(reparse_buf, plen, target_path,
+                                        cifs_sb);
                goto querty_exit;
        }
 
@@ -2561,26 +2614,32 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
        err_buf = err_iov.iov_base;
        if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
            err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) {
-               rc = -ENOENT;
+               rc = -EINVAL;
+               goto querty_exit;
+       }
+
+       symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData;
+       if (le32_to_cpu(symlink->SymLinkErrorTag) != SYMLINK_ERROR_TAG ||
+           le32_to_cpu(symlink->ReparseTag) != IO_REPARSE_TAG_SYMLINK) {
+               rc = -EINVAL;
                goto querty_exit;
        }
 
        /* open must fail on symlink - reset rc */
        rc = 0;
-       symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData;
        sub_len = le16_to_cpu(symlink->SubstituteNameLength);
        sub_offset = le16_to_cpu(symlink->SubstituteNameOffset);
        print_len = le16_to_cpu(symlink->PrintNameLength);
        print_offset = le16_to_cpu(symlink->PrintNameOffset);
 
        if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
-               rc = -ENOENT;
+               rc = -EINVAL;
                goto querty_exit;
        }
 
        if (err_iov.iov_len <
            SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
-               rc = -ENOENT;
+               rc = -EINVAL;
                goto querty_exit;
        }
 
@@ -2606,7 +2665,6 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
        return rc;
 }
 
-#ifdef CONFIG_CIFS_ACL
 static struct cifs_ntsd *
 get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
                const struct cifs_fid *cifsfid, u32 *pacllen)
@@ -2691,7 +2749,6 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
        return pntsd;
 }
 
-#ifdef CONFIG_CIFS_ACL
 static int
 set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
                struct inode *inode, const char *path, int aclflag)
@@ -2749,7 +2806,6 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
        free_xid(xid);
        return rc;
 }
-#endif /* CIFS_ACL */
 
 /* Retrieve an ACL from the server */
 static struct cifs_ntsd *
@@ -2769,7 +2825,6 @@ get_smb2_acl(struct cifs_sb_info *cifs_sb,
        cifsFileInfo_put(open_file);
        return pntsd;
 }
-#endif
 
 static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
                            loff_t offset, loff_t len, bool keep_size)
@@ -3367,7 +3422,7 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile)
 
 static void
 fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
-                  struct smb_rqst *old_rq)
+                  struct smb_rqst *old_rq, __le16 cipher_type)
 {
        struct smb2_sync_hdr *shdr =
                        (struct smb2_sync_hdr *)old_rq->rq_iov[0].iov_base;
@@ -3376,7 +3431,10 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
        tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
        tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
        tr_hdr->Flags = cpu_to_le16(0x01);
-       get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE);
+       if (cipher_type == SMB2_ENCRYPTION_AES128_GCM)
+               get_random_bytes(&tr_hdr->Nonce, SMB3_AES128GCM_NONCE);
+       else
+               get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CCM_NONCE);
        memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
 }
 
@@ -3534,8 +3592,13 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
                rc = -ENOMEM;
                goto free_sg;
        }
-       iv[0] = 3;
-       memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES128CMM_NONCE);
+
+       if (server->cipher_type == SMB2_ENCRYPTION_AES128_GCM)
+               memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES128GCM_NONCE);
+       else {
+               iv[0] = 3;
+               memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES128CCM_NONCE);
+       }
 
        aead_request_set_crypt(req, sg, sg, crypt_len, iv);
        aead_request_set_ad(req, assoc_data_len);
@@ -3635,7 +3698,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst,
        }
 
        /* fill the 1st iov with a transform header */
-       fill_transform_hdr(tr_hdr, orig_len, old_rq);
+       fill_transform_hdr(tr_hdr, orig_len, old_rq, server->cipher_type);
 
        rc = crypt_message(server, num_rqst, new_rq, 1);
        cifs_dbg(FYI, "Encrypt message returned %d\n", rc);
@@ -4284,11 +4347,9 @@ struct smb_version_operations smb20_operations = {
        .query_all_EAs = smb2_query_eas,
        .set_EA = smb2_set_ea,
 #endif /* CIFS_XATTR */
-#ifdef CONFIG_CIFS_ACL
        .get_acl = get_smb2_acl,
        .get_acl_by_fid = get_smb2_acl_by_fid,
        .set_acl = set_smb2_acl,
-#endif /* CIFS_ACL */
        .next_header = smb2_next_header,
        .ioctl_query_info = smb2_ioctl_query_info,
        .make_node = smb2_make_node,
@@ -4385,11 +4446,9 @@ struct smb_version_operations smb21_operations = {
        .query_all_EAs = smb2_query_eas,
        .set_EA = smb2_set_ea,
 #endif /* CIFS_XATTR */
-#ifdef CONFIG_CIFS_ACL
        .get_acl = get_smb2_acl,
        .get_acl_by_fid = get_smb2_acl_by_fid,
        .set_acl = set_smb2_acl,
-#endif /* CIFS_ACL */
        .next_header = smb2_next_header,
        .ioctl_query_info = smb2_ioctl_query_info,
        .make_node = smb2_make_node,
@@ -4495,11 +4554,9 @@ struct smb_version_operations smb30_operations = {
        .query_all_EAs = smb2_query_eas,
        .set_EA = smb2_set_ea,
 #endif /* CIFS_XATTR */
-#ifdef CONFIG_CIFS_ACL
        .get_acl = get_smb2_acl,
        .get_acl_by_fid = get_smb2_acl_by_fid,
        .set_acl = set_smb2_acl,
-#endif /* CIFS_ACL */
        .next_header = smb2_next_header,
        .ioctl_query_info = smb2_ioctl_query_info,
        .make_node = smb2_make_node,
@@ -4606,11 +4663,9 @@ struct smb_version_operations smb311_operations = {
        .query_all_EAs = smb2_query_eas,
        .set_EA = smb2_set_ea,
 #endif /* CIFS_XATTR */
-#ifdef CONFIG_CIFS_ACL
        .get_acl = get_smb2_acl,
        .get_acl_by_fid = get_smb2_acl_by_fid,
        .set_acl = set_smb2_acl,
-#endif /* CIFS_ACL */
        .next_header = smb2_next_header,
        .ioctl_query_info = smb2_ioctl_query_info,
        .make_node = smb2_make_node,
index 75311a8a68bfd1941413e02a8739f9256c21bb3f..f58e4dc3987b3fe0cd942cbb8e94c24d4f173478 100644 (file)
@@ -489,10 +489,25 @@ static void
 build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
 {
        pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
-       pneg_ctxt->DataLength = cpu_to_le16(4); /* Cipher Count + le16 cipher */
-       pneg_ctxt->CipherCount = cpu_to_le16(1);
-/* pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;*/ /* not supported yet */
-       pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_CCM;
+       pneg_ctxt->DataLength = cpu_to_le16(6); /* Cipher Count + two ciphers */
+       pneg_ctxt->CipherCount = cpu_to_le16(2);
+       pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;
+       pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES128_CCM;
+}
+
+static unsigned int
+build_netname_ctxt(struct smb2_netname_neg_context *pneg_ctxt, char *hostname)
+{
+       struct nls_table *cp = load_nls_default();
+
+       pneg_ctxt->ContextType = SMB2_NETNAME_NEGOTIATE_CONTEXT_ID;
+
+       /* copy up to max of first 100 bytes of server name to NetName field */
+       pneg_ctxt->DataLength = cpu_to_le16(2 +
+               (2 * cifs_strtoUTF16(pneg_ctxt->NetName, hostname, 100, cp)));
+       /* context size is DataLength + minimal smb2_neg_context */
+       return DIV_ROUND_UP(le16_to_cpu(pneg_ctxt->DataLength) +
+                       sizeof(struct smb2_neg_context), 8) * 8;
 }
 
 static void
@@ -521,7 +536,7 @@ build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
 
 static void
 assemble_neg_contexts(struct smb2_negotiate_req *req,
-                     unsigned int *total_len)
+                     struct TCP_Server_Info *server, unsigned int *total_len)
 {
        char *pneg_ctxt = (char *)req;
        unsigned int ctxt_len;
@@ -551,17 +566,25 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
        *total_len += ctxt_len;
        pneg_ctxt += ctxt_len;
 
-       build_compression_ctxt((struct smb2_compression_capabilities_context *)
+       if (server->compress_algorithm) {
+               build_compression_ctxt((struct smb2_compression_capabilities_context *)
                                pneg_ctxt);
-       ctxt_len = DIV_ROUND_UP(
-               sizeof(struct smb2_compression_capabilities_context), 8) * 8;
+               ctxt_len = DIV_ROUND_UP(
+                       sizeof(struct smb2_compression_capabilities_context),
+                               8) * 8;
+               *total_len += ctxt_len;
+               pneg_ctxt += ctxt_len;
+               req->NegotiateContextCount = cpu_to_le16(5);
+       } else
+               req->NegotiateContextCount = cpu_to_le16(4);
+
+       ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt,
+                                       server->hostname);
        *total_len += ctxt_len;
        pneg_ctxt += ctxt_len;
 
        build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
        *total_len += sizeof(struct smb2_posix_neg_context);
-
-       req->NegotiateContextCount = cpu_to_le16(4);
 }
 
 static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
@@ -829,7 +852,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
                if ((ses->server->vals->protocol_id == SMB311_PROT_ID) ||
                    (strcmp(ses->server->vals->version_string,
                     SMBDEFAULT_VERSION_STRING) == 0))
-                       assemble_neg_contexts(req, &total_len);
+                       assemble_neg_contexts(req, server, &total_len);
        }
        iov[0].iov_base = (char *)req;
        iov[0].iov_len = total_len;
@@ -2095,6 +2118,48 @@ add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
        return 0;
 }
 
+static struct crt_query_id_ctxt *
+create_query_id_buf(void)
+{
+       struct crt_query_id_ctxt *buf;
+
+       buf = kzalloc(sizeof(struct crt_query_id_ctxt), GFP_KERNEL);
+       if (!buf)
+               return NULL;
+
+       buf->ccontext.DataOffset = cpu_to_le16(0);
+       buf->ccontext.DataLength = cpu_to_le32(0);
+       buf->ccontext.NameOffset = cpu_to_le16(offsetof
+                               (struct crt_query_id_ctxt, Name));
+       buf->ccontext.NameLength = cpu_to_le16(4);
+       /* SMB2_CREATE_QUERY_ON_DISK_ID is "QFid" */
+       buf->Name[0] = 'Q';
+       buf->Name[1] = 'F';
+       buf->Name[2] = 'i';
+       buf->Name[3] = 'd';
+       return buf;
+}
+
+/* See MS-SMB2 2.2.13.2.9 */
+static int
+add_query_id_context(struct kvec *iov, unsigned int *num_iovec)
+{
+       struct smb2_create_req *req = iov[0].iov_base;
+       unsigned int num = *num_iovec;
+
+       iov[num].iov_base = create_query_id_buf();
+       if (iov[num].iov_base == NULL)
+               return -ENOMEM;
+       iov[num].iov_len = sizeof(struct crt_query_id_ctxt);
+       if (!req->CreateContextsOffset)
+               req->CreateContextsOffset = cpu_to_le32(
+                               sizeof(struct smb2_create_req) +
+                               iov[num - 1].iov_len);
+       le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_query_id_ctxt));
+       *num_iovec = num + 1;
+       return 0;
+}
+
 static int
 alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
                            const char *treename, const __le16 *path)
@@ -2423,6 +2488,12 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock,
                        return rc;
        }
 
+       if (n_iov > 2) {
+               struct create_context *ccontext =
+                       (struct create_context *)iov[n_iov-1].iov_base;
+               ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
+       }
+       add_query_id_context(iov, &n_iov);
 
        rqst->rq_nvec = n_iov;
        return 0;
@@ -2550,12 +2621,11 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
                 * indatalen is usually small at a couple of bytes max, so
                 * just allocate through generic pool
                 */
-               in_data_buf = kmalloc(indatalen, GFP_NOFS);
+               in_data_buf = kmemdup(in_data, indatalen, GFP_NOFS);
                if (!in_data_buf) {
                        cifs_small_buf_release(req);
                        return -ENOMEM;
                }
-               memcpy(in_data_buf, in_data, indatalen);
        }
 
        req->CtlCode = cpu_to_le32(opcode);
index 858353d20c39220a6879ed9782599834b01d6f61..7e2e782f8eddd52aebc7fd156bc62b366316b726 100644 (file)
@@ -123,7 +123,7 @@ struct smb2_sync_pdu {
        __le16 StructureSize2; /* size of wct area (varies, request specific) */
 } __packed;
 
-#define SMB3_AES128CMM_NONCE 11
+#define SMB3_AES128CCM_NONCE 11
 #define SMB3_AES128GCM_NONCE 12
 
 struct smb2_transform_hdr {
@@ -166,6 +166,8 @@ struct smb2_err_rsp {
        __u8   ErrorData[1];  /* variable length */
 } __packed;
 
+#define SYMLINK_ERROR_TAG 0x4c4d5953
+
 struct smb2_symlink_err_rsp {
        __le32 SymLinkLength;
        __le32 SymLinkErrorTag;
@@ -227,6 +229,7 @@ struct smb2_negotiate_req {
 } __packed;
 
 /* Dialects */
+#define SMB10_PROT_ID 0x0000 /* local only, not sent on wire w/CIFS negprot */
 #define SMB20_PROT_ID 0x0202
 #define SMB21_PROT_ID 0x0210
 #define SMB30_PROT_ID 0x0300
@@ -293,7 +296,7 @@ struct smb2_encryption_neg_context {
        __le16  DataLength;
        __le32  Reserved;
        __le16  CipherCount; /* AES-128-GCM and AES-128-CCM */
-       __le16  Ciphers[1]; /* Ciphers[0] since only one used now */
+       __le16  Ciphers[2];
 } __packed;
 
 /* See MS-SMB2 2.2.3.1.3 */
@@ -316,6 +319,12 @@ struct smb2_compression_capabilities_context {
  * For smb2_netname_negotiate_context_id See MS-SMB2 2.2.3.1.4.
  * Its struct simply contains NetName, an array of Unicode characters
  */
+struct smb2_netname_neg_context {
+       __le16  ContextType; /* 0x100 */
+       __le16  DataLength;
+       __le32  Reserved;
+       __le16  NetName[0]; /* hostname of target converted to UCS-2 */
+} __packed;
 
 #define POSIX_CTXT_DATA_LEN    16
 struct smb2_posix_neg_context {
@@ -640,6 +649,7 @@ struct smb2_tree_disconnect_rsp {
 #define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2  "DH2Q"
 #define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2        "DH2C"
 #define SMB2_CREATE_APP_INSTANCE_ID    0x45BCA66AEFA7F74A9008FA462E144D74
+#define SMB2_CREATE_APP_INSTANCE_VERSION 0xB982D0B73B56074FA07B524A8116A010
 #define SVHDX_OPEN_DEVICE_CONTEX       0x9CCBCF9E04C1E643980E158DA1F6EC83
 #define SMB2_CREATE_TAG_POSIX          0x93AD25509CB411E7B42383DE968BCD7C
 
@@ -654,9 +664,10 @@ struct smb2_tree_disconnect_rsp {
  * [3] : durable context
  * [4] : posix context
  * [5] : time warp context
- * [6] : compound padding
+ * [6] : query id context
+ * [7] : compound padding
  */
-#define SMB2_CREATE_IOV_SIZE 7
+#define SMB2_CREATE_IOV_SIZE 8
 
 struct smb2_create_req {
        struct smb2_sync_hdr sync_hdr;
@@ -680,10 +691,10 @@ struct smb2_create_req {
 
 /*
  * Maximum size of a SMB2_CREATE response is 64 (smb2 header) +
- * 88 (fixed part of create response) + 520 (path) + 150 (contexts) +
+ * 88 (fixed part of create response) + 520 (path) + 208 (contexts) +
  * 2 bytes of padding.
  */
-#define MAX_SMB2_CREATE_RESPONSE_SIZE 824
+#define MAX_SMB2_CREATE_RESPONSE_SIZE 880
 
 struct smb2_create_rsp {
        struct smb2_sync_hdr sync_hdr;
@@ -806,6 +817,13 @@ struct durable_reconnect_context_v2 {
        __le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
 } __packed;
 
+/* See MS-SMB2 2.2.14.2.9 */
+struct on_disk_id {
+       __le64 DiskFileId;
+       __le64 VolumeId;
+       __u32  Reserved[4];
+} __packed;
+
 /* See MS-SMB2 2.2.14.2.12 */
 struct durable_reconnect_context_v2_rsp {
        __le32 Timeout;
@@ -826,6 +844,12 @@ struct crt_twarp_ctxt {
 
 } __packed;
 
+/* See MS-SMB2 2.2.13.2.9 */
+struct crt_query_id_ctxt {
+       struct create_context ccontext;
+       __u8    Name[8];
+} __packed;
+
 #define COPY_CHUNK_RES_KEY_SIZE        24
 struct resume_key_req {
        char ResumeKey[COPY_CHUNK_RES_KEY_SIZE];
index d1181572758b186c67fccaab572b502aef7497fc..1ccbcf9c2c3b009c056b4b0d83b661b3a10fd4d1 100644 (file)
@@ -734,7 +734,10 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
        struct crypto_aead *tfm;
 
        if (!server->secmech.ccmaesencrypt) {
-               tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
+               if (server->cipher_type == SMB2_ENCRYPTION_AES128_GCM)
+                       tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
+               else
+                       tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
                if (IS_ERR(tfm)) {
                        cifs_dbg(VFS, "%s: Failed to alloc encrypt aead\n",
                                 __func__);
@@ -744,7 +747,10 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
        }
 
        if (!server->secmech.ccmaesdecrypt) {
-               tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
+               if (server->cipher_type == SMB2_ENCRYPTION_AES128_GCM)
+                       tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
+               else
+                       tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
                if (IS_ERR(tfm)) {
                        crypto_free_aead(server->secmech.ccmaesencrypt);
                        server->secmech.ccmaesencrypt = NULL;
index 60661b3f983acd6242b76702dc18694dd3433baa..5d6d44bfe10a6f8b4442787f4eac3fc3bcccc34d 100644 (file)
@@ -979,6 +979,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
        };
        unsigned int instance;
        char *buf;
+       struct TCP_Server_Info *server;
 
        optype = flags & CIFS_OP_MASK;
 
@@ -990,7 +991,8 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                return -EIO;
        }
 
-       if (ses->server->tcpStatus == CifsExiting)
+       server = ses->server;
+       if (server->tcpStatus == CifsExiting)
                return -ENOENT;
 
        /*
@@ -1001,7 +1003,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
         * other requests.
         * This can be handled by the eventual session reconnect.
         */
-       rc = wait_for_compound_request(ses->server, num_rqst, flags,
+       rc = wait_for_compound_request(server, num_rqst, flags,
                                       &instance);
        if (rc)
                return rc;
@@ -1017,7 +1019,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
         * of smb data.
         */
 
-       mutex_lock(&ses->server->srv_mutex);
+       mutex_lock(&server->srv_mutex);
 
        /*
         * All the parts of the compound chain belong obtained credits from the
@@ -1026,24 +1028,24 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
         * we obtained credits and return -EAGAIN in such cases to let callers
         * handle it.
         */
-       if (instance != ses->server->reconnect_instance) {
-               mutex_unlock(&ses->server->srv_mutex);
+       if (instance != server->reconnect_instance) {
+               mutex_unlock(&server->srv_mutex);
                for (j = 0; j < num_rqst; j++)
-                       add_credits(ses->server, &credits[j], optype);
+                       add_credits(server, &credits[j], optype);
                return -EAGAIN;
        }
 
        for (i = 0; i < num_rqst; i++) {
-               midQ[i] = ses->server->ops->setup_request(ses, &rqst[i]);
+               midQ[i] = server->ops->setup_request(ses, &rqst[i]);
                if (IS_ERR(midQ[i])) {
-                       revert_current_mid(ses->server, i);
+                       revert_current_mid(server, i);
                        for (j = 0; j < i; j++)
                                cifs_delete_mid(midQ[j]);
-                       mutex_unlock(&ses->server->srv_mutex);
+                       mutex_unlock(&server->srv_mutex);
 
                        /* Update # of requests on wire to server */
                        for (j = 0; j < num_rqst; j++)
-                               add_credits(ses->server, &credits[j], optype);
+                               add_credits(server, &credits[j], optype);
                        return PTR_ERR(midQ[i]);
                }
 
@@ -1059,19 +1061,19 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                else
                        midQ[i]->callback = cifs_compound_last_callback;
        }
-       cifs_in_send_inc(ses->server);
-       rc = smb_send_rqst(ses->server, num_rqst, rqst, flags);
-       cifs_in_send_dec(ses->server);
+       cifs_in_send_inc(server);
+       rc = smb_send_rqst(server, num_rqst, rqst, flags);
+       cifs_in_send_dec(server);
 
        for (i = 0; i < num_rqst; i++)
                cifs_save_when_sent(midQ[i]);
 
        if (rc < 0) {
-               revert_current_mid(ses->server, num_rqst);
-               ses->server->sequence_number -= 2;
+               revert_current_mid(server, num_rqst);
+               server->sequence_number -= 2;
        }
 
-       mutex_unlock(&ses->server->srv_mutex);
+       mutex_unlock(&server->srv_mutex);
 
        /*
         * If sending failed for some reason or it is an oplock break that we
@@ -1079,7 +1081,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
         */
        if (rc < 0 || (flags & CIFS_NO_SRV_RSP)) {
                for (i = 0; i < num_rqst; i++)
-                       add_credits(ses->server, &credits[i], optype);
+                       add_credits(server, &credits[i], optype);
                goto out;
        }
 
@@ -1099,7 +1101,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                                           rqst[0].rq_nvec);
 
        for (i = 0; i < num_rqst; i++) {
-               rc = wait_for_response(ses->server, midQ[i]);
+               rc = wait_for_response(server, midQ[i]);
                if (rc != 0)
                        break;
        }
@@ -1107,7 +1109,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                for (; i < num_rqst; i++) {
                        cifs_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n",
                                 midQ[i]->mid, le16_to_cpu(midQ[i]->command));
-                       send_cancel(ses->server, &rqst[i], midQ[i]);
+                       send_cancel(server, &rqst[i], midQ[i]);
                        spin_lock(&GlobalMid_Lock);
                        if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
                                midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
@@ -1123,7 +1125,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                if (rc < 0)
                        goto out;
 
-               rc = cifs_sync_mid_result(midQ[i], ses->server);
+               rc = cifs_sync_mid_result(midQ[i], server);
                if (rc != 0) {
                        /* mark this mid as cancelled to not free it below */
                        cancelled_mid[i] = true;
@@ -1140,14 +1142,14 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                buf = (char *)midQ[i]->resp_buf;
                resp_iov[i].iov_base = buf;
                resp_iov[i].iov_len = midQ[i]->resp_buf_size +
-                       ses->server->vals->header_preamble_size;
+                       server->vals->header_preamble_size;
 
                if (midQ[i]->large_buf)
                        resp_buf_type[i] = CIFS_LARGE_BUFFER;
                else
                        resp_buf_type[i] = CIFS_SMALL_BUFFER;
 
-               rc = ses->server->ops->check_receive(midQ[i], ses->server,
+               rc = server->ops->check_receive(midQ[i], server,
                                                     flags & CIFS_LOG_ERROR);
 
                /* mark it so buf will not be freed by cifs_delete_mid */
index 50ddb795aaeb3b49586d8cf3454a197145db9488..9076150758d88e20efae50771db8ad1f820a478e 100644 (file)
@@ -96,7 +96,6 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
                break;
 
        case XATTR_CIFS_ACL: {
-#ifdef CONFIG_CIFS_ACL
                struct cifs_ntsd *pacl;
 
                if (!value)
@@ -117,7 +116,6 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
                                CIFS_I(inode)->time = 0;
                        kfree(pacl);
                }
-#endif /* CONFIG_CIFS_ACL */
                break;
        }
 
@@ -247,7 +245,6 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
                break;
 
        case XATTR_CIFS_ACL: {
-#ifdef CONFIG_CIFS_ACL
                u32 acllen;
                struct cifs_ntsd *pacl;
 
@@ -270,7 +267,6 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
                        rc = acllen;
                        kfree(pacl);
                }
-#endif  /* CONFIG_CIFS_ACL */
                break;
        }