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
  ...

1  2 
fs/cifs/Kconfig
fs/cifs/cifsfs.c
fs/cifs/connect.c

diff --combined fs/cifs/Kconfig
index 523e9ea78a285361bc23a17852e3579c9811c847,d6f71e3c4749115970ff4fb7dfcef11dfa4969b7..b16219e5dac91b2e26fbb98e5c8afb238de47ec4
@@@ -10,12 -10,14 +10,14 @@@ config CIF
        select CRYPTO_SHA512
        select CRYPTO_CMAC
        select CRYPTO_HMAC
 -      select CRYPTO_ARC4
 +      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 +111,7 @@@ config CIFS_WEAK_PW_HAS
  
  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 +146,6 @@@ config CIFS_POSI
          (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 +178,7 @@@ config CIFS_DEBUG_DUMP_KEY
  
  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 +197,10 @@@ config CIFS_NFSD_EXPOR
          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.
  
diff --combined fs/cifs/cifsfs.c
index 24635b65effa7848005c815a955ea029270c6f5f,0ee63ac4ef72f9d2d1e4288a881c2eda3a56a238..270d3c58fb3b2ac0917d3d40f6083d2d8558b6a0
@@@ -526,6 -526,8 +526,8 @@@ cifs_show_options(struct seq_file *s, s
                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)
        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)
@@@ -1149,10 -1156,6 +1156,10 @@@ static ssize_t cifs_copy_file_range(str
        rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff,
                                        len, flags);
        free_xid(xid);
 +
 +      if (rc == -EOPNOTSUPP || rc == -EXDEV)
 +              rc = generic_copy_file_range(src_file, off, dst_file,
 +                                           destoff, len, flags);
        return rc;
  }
  
@@@ -1517,11 -1520,9 +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)
        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 -1570,7 +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
@@@ -1595,6 -1592,7 +1596,6 @@@ MODULE_DESCRIPTIO
        ("VFS to access SMB3 servers e.g. Samba, Macs, Azure and Windows (and "
        "also older servers complying with the SNIA CIFS Specification)");
  MODULE_VERSION(CIFS_VERSION);
 -MODULE_SOFTDEP("pre: arc4");
  MODULE_SOFTDEP("pre: des");
  MODULE_SOFTDEP("pre: ecb");
  MODULE_SOFTDEP("pre: hmac");
@@@ -1607,5 -1605,6 +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)
diff --combined fs/cifs/connect.c
index 714a359c7c8de6fc0c1fb9cecafb695d590b4c28,6331c4f93b596e06a1101f9494790a29a48b3160..a4830ced0f9899c35c89609b2ea25330a06693bd
@@@ -96,7 -96,8 +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 +176,7 @@@ static const match_table_t cifs_mount_o
        { Opt_serverino, "serverino" },
        { Opt_noserverino, "noserverino" },
        { Opt_rwpidforward, "rwpidforward" },
+       { Opt_modesid, "modefromsid" },
        { Opt_cifsacl, "cifsacl" },
        { Opt_nocifsacl, "nocifsacl" },
        { Opt_acl, "acl" },
        { 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 +709,10 @@@ static boo
  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
         * ...
         */
        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 +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 +1833,9 @@@ cifs_parse_mount_options(const char *mo
                case Opt_rwpidforward:
                        vol->rwpidforward = 1;
                        break;
+               case Opt_modesid:
+                       vol->mode_ace = 1;
+                       break;
                case Opt_cifsacl:
                        vol->cifs_acl = 1;
                        break;
                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 +2555,15 @@@ static int match_server(struct TCP_Serv
        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))
@@@ -2631,7 -2649,7 +2649,7 @@@ cifs_put_tcp_session(struct TCP_Server_
  
        task = xchg(&server->tsk, NULL);
        if (task)
 -              force_sig(SIGKILL, task);
 +              send_sig(SIGKILL, task, 1);
  }
  
  static struct TCP_Server_Info *
@@@ -2680,6 -2698,7 +2698,7 @@@ cifs_get_tcp_session(struct smb_vol *vo
        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 +3479,16 @@@ compare_mount_options(struct super_bloc
  {
        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 +3988,8 @@@ int cifs_setup_cifs_sb(struct smb_vol *
                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 +4484,13 @@@ cifs_are_all_path_components_accessible
                                        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;
                /* 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 +4560,7 @@@ static int is_path_remote(struct cifs_s
  
        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");