Merge tag '4.17-SMB3-Fixes' of git://git.samba.org/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Apr 2018 21:09:27 +0000 (14:09 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Apr 2018 21:09:27 +0000 (14:09 -0700)
Pull cifs updates from Steve French:
 "Includes SMB3.11 security improvements, as well as various fixes for
  stable and some debugging improvements"

* tag '4.17-SMB3-Fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: Add minor debug message during negprot
  smb3: Fix root directory when server returns inode number of zero
  cifs: fix sparse warning on previous patch in a few printks
  cifs: add server->vals->header_preamble_size
  cifs: smbd: disconnect transport on RDMA errors
  cifs: smbd: avoid reconnect lockup
  Don't log confusing message on reconnect by default
  Don't log expected error on DFS referral request
  fs: cifs: Replace _free_xid call in cifs_root_iget function
  SMB3.1.1 dialect is no longer experimental
  Tree connect for SMB3.1.1 must be signed for non-encrypted shares
  fix smb3-encryption breakage when CONFIG_DEBUG_SG=y
  CIFS: fix sha512 check in cifs_crypto_secmech_release
  CIFS: implement v3.11 preauth integrity
  CIFS: add sha512 secmech
  CIFS: refactor crypto shash/sdesc allocation&free
  Update README file for cifs.ko
  Update TODO list for cifs.ko
  cifs: fix memory leak in SMB2_open()
  CIFS: SMBD: fix spelling mistake: "faield" and "legnth"

23 files changed:
Documentation/filesystems/cifs/README
Documentation/filesystems/cifs/TODO
fs/cifs/Kconfig
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/inode.c
fs/cifs/link.c
fs/cifs/misc.c
fs/cifs/smb1ops.c
fs/cifs/smb2maperror.c
fs/cifs/smb2misc.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/smb2proto.h
fs/cifs/smb2transport.c
fs/cifs/smbdirect.c
fs/cifs/smbencrypt.c
fs/cifs/transport.c

index a9da51553ba3e15049c17aecbad840eb607ef056..99ce3d25003d16482f01b56b7222772c9fb338d2 100644 (file)
@@ -11,13 +11,14 @@ Information Foundation.  CIFS and now SMB3 has now become a defacto
 standard for interoperating between Macs and Windows and major NAS appliances.
 
 Please see
+  MS-SMB2 (for detailed SMB2/SMB3/SMB3.1.1 protocol specification)
   http://protocolfreedom.org/ and
   http://samba.org/samba/PFIF/
 for more details.
 
 
 For questions or bug reports please contact:
-    sfrench@samba.org (sfrench@us.ibm.com) 
+    smfrench@gmail.com
 
 See the project page at: https://wiki.samba.org/index.php/LinuxCIFS_utils
 
@@ -37,15 +38,15 @@ Installation instructions:
 =========================
 If you have built the CIFS vfs as module (successfully) simply
 type "make modules_install" (or if you prefer, manually copy the file to
-the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
+the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.ko).
 
 If you have built the CIFS vfs into the kernel itself, follow the instructions
 for your distribution on how to install a new kernel (usually you
 would simply type "make install").
 
-If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on 
-the CIFS VFS web site) copy it to the same directory in which mount.smbfs and 
-similar files reside (usually /sbin).  Although the helper software is not  
+If you do not have the utility mount.cifs (in the Samba 4.x source tree and on
+the CIFS VFS web site) copy it to the same directory in which mount helpers
+reside (usually /sbin).  Although the helper software is not
 required, mount.cifs is recommended.  Most distros include a "cifs-utils"
 package that includes this utility so it is recommended to install this.
 
@@ -118,10 +119,13 @@ this can become unwieldy when potential mount targets include many
 or  unpredictable UNC names.
 
 Samba Considerations 
-==================== 
-To get the maximum benefit from the CIFS VFS, we recommend using a server that 
-supports the SNIA CIFS Unix Extensions standard (e.g.  Samba 2.2.5 or later or 
-Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers.  
+====================
+Most current servers support SMB2.1 and SMB3 which are more secure,
+but there are useful protocol extensions for the older less secure CIFS
+dialect, so to get the maximum benefit if mounting using the older dialect
+(CIFS/SMB1), we recommend using a server that supports the SNIA CIFS
+Unix Extensions standard (e.g. almost any  version of Samba ie version
+2.2.5 or later) but the CIFS vfs works fine with a wide variety of CIFS servers.
 Note that uid, gid and file permissions will display default values if you do 
 not have a server that supports the Unix extensions for CIFS (such as Samba 
 2.2.5 or later).  To enable the Unix CIFS Extensions in the Samba server, add 
@@ -603,11 +607,6 @@ Stats                      Lists summary resource usage information as well as per
                        in the kernel configuration.
 
 Configuration pseudo-files:
-PacketSigningEnabled   If set to one, cifs packet signing is enabled
-                       and will be used if the server requires 
-                       it.  If set to two, cifs packet signing is
-                       required even if the server considers packet
-                       signing optional. (default 1)
 SecurityFlags          Flags which control security negotiation and
                        also packet signing. Authentication (may/must)
                        flags (e.g. for NTLM and/or NTLMv2) may be combined with
@@ -666,8 +665,6 @@ traceSMB            If set to one, debug information is logged to the
 LookupCacheEnable      If set to one, inode information is kept cached
                        for one second improving performance of lookups
                        (default 1)
-OplockEnabled          If set to one, safe distributed caching enabled.
-                       (default 1)
 LinuxExtensionsEnabled If set to one then the client will attempt to
                        use the CIFS "UNIX" extensions which are optional
                        protocol enhancements that allow CIFS servers
index 396ecfd6ff4a0da40f099dfef57ef6111ae8da71..c5adf149b57f7f8f6e2d0b104d5b74f6bc7f5f84 100644 (file)
@@ -1,4 +1,4 @@
-Version 2.04 September 13, 2017
+Version 2.11 September 13, 2017
 
 A Partial List of Missing Features
 ==================================
@@ -8,10 +8,10 @@ for visible, important contributions to this module.  Here
 is a partial list of the known problems and missing features:
 
 a) SMB3 (and SMB3.02) missing optional features:
-   - RDMA (started)
-   - multichannel (started)
+   - multichannel (started), integration with RDMA
    - directory leases (improved metadata caching)
-   - T10 copy offload (copy chunk is only mechanism supported)
+   - T10 copy offload (copy chunk, and "Duplicate Extents" ioctl
+     currently the only two server side copy mechanisms supported)
 
 b) improved sparse file support
 
@@ -21,9 +21,8 @@ using Directory Leases
 d) quota support (needs minor kernel change since quota calls
 to make it to network filesystems or deviceless filesystems)
 
-e) Better optimize open to reduce redundant opens (using reference
-counts more) and to improve use of compounding in SMB3 to reduce
-number of roundtrips.
+e) Compounding (in progress) to reduce number of roundtrips, and also
+better optimize open to reduce redundant opens (using reference counts more).
 
 f) Finish inotify support so kde and gnome file list windows
 will autorefresh (partially complete by Asser). Needs minor kernel
@@ -35,7 +34,8 @@ the CIFS statistics (started)
 h) implement support for security and trusted categories of xattrs
 (requires minor protocol extension) to enable better support for SELINUX
 
-i) Implement O_DIRECT flag on open (already supported on mount)
+i) Add support for tree connect contexts (see MS-SMB2) a new SMB3.1.1 protocol
+   feature (may be especially useful for virtualization).
 
 j) Create UID mapping facility so server UIDs can be mapped on a per
 mount or a per server basis to client UIDs or nobody if no mapping
@@ -53,13 +53,16 @@ viewing them.
 
 o) mount helper GUI (to simplify the various configuration options on mount)
 
-p) autonegotiation of dialects (offering more than one dialect ie SMB3.02,
-SMB3, SMB2.1 not just SMB3).
+p) Add support for witness protocol (perhaps ioctl to cifs.ko from user space
+   tool listening on witness protocol RPC) to allow for notification of share
+   move, server failover, and server adapter changes.  And also improve other
+   failover scenarios, e.g. when client knows multiple DFS entries point to
+   different servers, and the server we are connected to has gone down.
 
 q) Allow mount.cifs to be more verbose in reporting errors with dialect
 or unsupported feature errors.
 
-r) updating cifs documentation, and user guid.
+r) updating cifs documentation, and user guide.
 
 s) Addressing bugs found by running a broader set of xfstests in standard
 file system xfstest suite.
index 687da62daf4e5e9c5d1c9d75d2065a321c584eee..741749a986142c5b1c2d47dfd6793ee05989ab09 100644 (file)
@@ -187,13 +187,13 @@ config CIFS_NFSD_EXPORT
           Allows NFS server to export a CIFS mounted share (nfsd over cifs)
 
 config CIFS_SMB311
-       bool "SMB3.1.1 network file system support (Experimental)"
+       bool "SMB3.1.1 network file system support"
        depends on CIFS
+       select CRYPTO_SHA512
 
        help
-         This enables experimental support for the newest, SMB3.1.1, dialect.
-         This dialect includes improved security negotiation features.
-         If unsure, say N
+         This enables support for the newest, and most secure dialect, SMB3.11.
+         If unsure, say Y
 
 config CIFS_SMB_DIRECT
        bool "SMB Direct support (Experimental)"
index f2b0a7f124da94070b46249e722e136e0a82f635..a6ef088e057bda126057d3052305b72f911ef99c 100644 (file)
 #include <crypto/skcipher.h>
 #include <crypto/aead.h>
 
-static int
-cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
-{
-       int rc;
-       unsigned int size;
-
-       if (server->secmech.sdescmd5 != NULL)
-               return 0; /* already allocated */
-
-       server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
-       if (IS_ERR(server->secmech.md5)) {
-               cifs_dbg(VFS, "could not allocate crypto md5\n");
-               rc = PTR_ERR(server->secmech.md5);
-               server->secmech.md5 = NULL;
-               return rc;
-       }
-
-       size = sizeof(struct shash_desc) +
-                       crypto_shash_descsize(server->secmech.md5);
-       server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
-       if (!server->secmech.sdescmd5) {
-               crypto_free_shash(server->secmech.md5);
-               server->secmech.md5 = NULL;
-               return -ENOMEM;
-       }
-       server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
-       server->secmech.sdescmd5->shash.flags = 0x0;
-
-       return 0;
-}
-
 int __cifs_calc_signature(struct smb_rqst *rqst,
                        struct TCP_Server_Info *server, char *signature,
                        struct shash_desc *shash)
@@ -132,13 +101,10 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
        if (!rqst->rq_iov || !signature || !server)
                return -EINVAL;
 
-       if (!server->secmech.sdescmd5) {
-               rc = cifs_crypto_shash_md5_allocate(server);
-               if (rc) {
-                       cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__);
-                       return -1;
-               }
-       }
+       rc = cifs_alloc_hash("md5", &server->secmech.md5,
+                            &server->secmech.sdescmd5);
+       if (rc)
+               return -1;
 
        rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
        if (rc) {
@@ -663,37 +629,6 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
        return rc;
 }
 
-static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
-{
-       int rc;
-       unsigned int size;
-
-       /* check if already allocated */
-       if (server->secmech.sdeschmacmd5)
-               return 0;
-
-       server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
-       if (IS_ERR(server->secmech.hmacmd5)) {
-               cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
-               rc = PTR_ERR(server->secmech.hmacmd5);
-               server->secmech.hmacmd5 = NULL;
-               return rc;
-       }
-
-       size = sizeof(struct shash_desc) +
-                       crypto_shash_descsize(server->secmech.hmacmd5);
-       server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
-       if (!server->secmech.sdeschmacmd5) {
-               crypto_free_shash(server->secmech.hmacmd5);
-               server->secmech.hmacmd5 = NULL;
-               return -ENOMEM;
-       }
-       server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
-       server->secmech.sdeschmacmd5->shash.flags = 0x0;
-
-       return 0;
-}
-
 int
 setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 {
@@ -757,9 +692,10 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 
        mutex_lock(&ses->server->srv_mutex);
 
-       rc = crypto_hmacmd5_alloc(ses->server);
+       rc = cifs_alloc_hash("hmac(md5)",
+                            &ses->server->secmech.hmacmd5,
+                            &ses->server->secmech.sdeschmacmd5);
        if (rc) {
-               cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
                goto unlock;
        }
 
@@ -893,6 +829,11 @@ cifs_crypto_secmech_release(struct TCP_Server_Info *server)
                server->secmech.md5 = NULL;
        }
 
+       if (server->secmech.sha512) {
+               crypto_free_shash(server->secmech.sha512);
+               server->secmech.sha512 = NULL;
+       }
+
        if (server->secmech.hmacmd5) {
                crypto_free_shash(server->secmech.hmacmd5);
                server->secmech.hmacmd5 = NULL;
@@ -916,4 +857,6 @@ cifs_crypto_secmech_release(struct TCP_Server_Info *server)
        server->secmech.sdeschmacmd5 = NULL;
        kfree(server->secmech.sdescmd5);
        server->secmech.sdescmd5 = NULL;
+       kfree(server->secmech.sdescsha512);
+       server->secmech.sdescsha512 = NULL;
 }
index 32cdea67bbfd9792fe92efcc94f17ceb64056c80..f715609b13f34a412de9f0486750a05cf73340b6 100644 (file)
@@ -1486,6 +1486,7 @@ MODULE_SOFTDEP("pre: nls");
 MODULE_SOFTDEP("pre: aes");
 MODULE_SOFTDEP("pre: cmac");
 MODULE_SOFTDEP("pre: sha256");
+MODULE_SOFTDEP("pre: sha512");
 MODULE_SOFTDEP("pre: aead2");
 MODULE_SOFTDEP("pre: ccm");
 module_init(init_cifs)
index 48f7c197cd2d057e1991bea0ed52595e64fe5bb3..2282562e78a1fe5313faf3948e6cf2635926ab9f 100644 (file)
@@ -130,10 +130,12 @@ struct cifs_secmech {
        struct crypto_shash *md5; /* md5 hash function */
        struct crypto_shash *hmacsha256; /* hmac-sha256 hash function */
        struct crypto_shash *cmacaes; /* block-cipher based MAC function */
+       struct crypto_shash *sha512; /* sha512 hash function */
        struct sdesc *sdeschmacmd5;  /* ctxt to generate ntlmv2 hash, CR1 */
        struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */
        struct sdesc *sdeschmacsha256;  /* ctxt to generate smb2 signature */
        struct sdesc *sdesccmacaes;  /* ctxt to generate smb3 signature */
+       struct sdesc *sdescsha512; /* ctxt to generate smb3.11 signing key */
        struct crypto_aead *ccmaesencrypt; /* smb3 encryption aead */
        struct crypto_aead *ccmaesdecrypt; /* smb3 decryption aead */
 };
@@ -466,6 +468,7 @@ struct smb_version_values {
        __u32           exclusive_lock_type;
        __u32           shared_lock_type;
        __u32           unlock_lock_type;
+       size_t          header_preamble_size;
        size_t          header_size;
        size_t          max_header_size;
        size_t          read_rsp_size;
@@ -673,7 +676,8 @@ struct TCP_Server_Info {
        unsigned int    max_read;
        unsigned int    max_write;
 #ifdef CONFIG_CIFS_SMB311
-       __u8    preauth_sha_hash[64]; /* save initital negprot hash */
+        /* save initital negprot hash */
+       __u8    preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
 #endif /* 3.1.1 */
        struct delayed_work reconnect; /* reconnect workqueue job */
        struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
@@ -862,7 +866,7 @@ struct cifs_ses {
        __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
        __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
 #ifdef CONFIG_CIFS_SMB311
-       __u8 preauth_sha_hash[64];
+       __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
 #endif /* 3.1.1 */
 };
 
@@ -1466,6 +1470,7 @@ struct dfs_info3_param {
 #define CIFS_FATTR_NEED_REVAL          0x4
 #define CIFS_FATTR_INO_COLLISION       0x8
 #define CIFS_FATTR_UNKNOWN_NLINK       0x10
+#define CIFS_FATTR_FAKE_ROOT_INO       0x20
 
 struct cifs_fattr {
        u32             cf_flags;
index 93d565186698ca8bdad1838fc33cc8e1eb972884..365a414a75e9d145da7786fee5f501b229501c31 100644 (file)
@@ -542,4 +542,9 @@ enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
 struct cifs_aio_ctx *cifs_aio_ctx_alloc(void);
 void cifs_aio_ctx_release(struct kref *refcount);
 int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw);
+
+int cifs_alloc_hash(const char *name, struct crypto_shash **shash,
+                   struct sdesc **sdesc);
+void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);
+
 #endif                 /* _CIFSPROTO_H */
index 9ceebf30eb22e905303ad714b50150cbf16c7457..59c09a596c0a71b098c2d84a6d7597df09eb07a0 100644 (file)
@@ -1454,7 +1454,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        unsigned int data_offset, data_len;
        struct cifs_readdata *rdata = mid->callback_data;
        char *buf = server->smallbuf;
-       unsigned int buflen = get_rfc1002_length(buf) + 4;
+       unsigned int buflen = get_rfc1002_length(buf) +
+               server->vals->header_preamble_size;
        bool use_rdma_mr = false;
 
        cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
@@ -1504,7 +1505,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                return cifs_readv_discard(server, mid);
        }
 
-       data_offset = server->ops->read_data_offset(buf) + 4;
+       data_offset = server->ops->read_data_offset(buf) +
+               server->vals->header_preamble_size;
        if (data_offset < server->total_read) {
                /*
                 * win2k8 sometimes sends an offset of 0 when the read
index a726f524fb84aa2ee1114eb1187f68eec84fbd30..4e0808f4019592e67b162605bef296263949036d 100644 (file)
@@ -775,7 +775,8 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        unsigned int pdu_length = get_rfc1002_length(buf);
 
        /* make sure this will fit in a large buffer */
-       if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
+       if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
+               server->vals->header_preamble_size) {
                cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
                cifs_reconnect(server);
                wake_up(&server->response_q);
@@ -791,7 +792,9 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
        /* now read the rest */
        length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
-                               pdu_length - HEADER_SIZE(server) + 1 + 4);
+                                      pdu_length - HEADER_SIZE(server) + 1
+                                      + server->vals->header_preamble_size);
+
        if (length < 0)
                return length;
        server->total_read += length;
@@ -884,7 +887,8 @@ cifs_demultiplex_thread(void *p)
                        continue;
 
                /* make sure we have enough to get to the MID */
-               if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
+               if (pdu_length < HEADER_SIZE(server) - 1 -
+                   server->vals->header_preamble_size) {
                        cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
                                 pdu_length);
                        cifs_reconnect(server);
@@ -893,8 +897,10 @@ cifs_demultiplex_thread(void *p)
                }
 
                /* read down to the MID */
-               length = cifs_read_from_socket(server, buf + 4,
-                                              HEADER_SIZE(server) - 1 - 4);
+               length = cifs_read_from_socket(server,
+                            buf + server->vals->header_preamble_size,
+                            HEADER_SIZE(server) - 1
+                            - server->vals->header_preamble_size);
                if (length < 0)
                        continue;
                server->total_read += length;
@@ -4306,7 +4312,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
                 server->sec_mode, server->capabilities, server->timeAdj);
 
        if (ses->auth_key.response) {
-               cifs_dbg(VFS, "Free previous auth_key.response = %p\n",
+               cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
                         ses->auth_key.response);
                kfree(ses->auth_key.response);
                ses->auth_key.response = NULL;
index 8f9a8cc7cc62558e71ef5896abf05437895979a3..f856df4adae3c8e8c09cf4c9195f0c0dc2891ca4 100644 (file)
@@ -707,6 +707,18 @@ cgfi_exit:
        return rc;
 }
 
+/* Simple function to return a 64 bit hash of string.  Rarely called */
+static __u64 simple_hashstr(const char *str)
+{
+       const __u64 hash_mult =  1125899906842597L; /* a big enough prime */
+       __u64 hash = 0;
+
+       while (*str)
+               hash = (hash + (__u64) *str++) * hash_mult;
+
+       return hash;
+}
+
 int
 cifs_get_inode_info(struct inode **inode, const char *full_path,
                    FILE_ALL_INFO *data, struct super_block *sb, int xid,
@@ -816,6 +828,14 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
                                                 tmprc);
                                        fattr.cf_uniqueid = iunique(sb, ROOT_I);
                                        cifs_autodisable_serverino(cifs_sb);
+                               } else if ((fattr.cf_uniqueid == 0) &&
+                                               strlen(full_path) == 0) {
+                                       /* some servers ret bad root ino ie 0 */
+                                       cifs_dbg(FYI, "Invalid (0) inodenum\n");
+                                       fattr.cf_flags |=
+                                               CIFS_FATTR_FAKE_ROOT_INO;
+                                       fattr.cf_uniqueid =
+                                               simple_hashstr(tcon->treeName);
                                }
                        }
                } else
@@ -832,6 +852,16 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
                                &fattr.cf_uniqueid, data);
                        if (tmprc)
                                fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
+                       else if ((fattr.cf_uniqueid == 0) &&
+                                       strlen(full_path) == 0) {
+                               /*
+                                * Reuse existing root inode num since
+                                * inum zero for root causes ls of . and .. to
+                                * not be returned
+                                */
+                               cifs_dbg(FYI, "Srv ret 0 inode num for root\n");
+                               fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
+                       }
                } else
                        fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
        }
@@ -893,6 +923,9 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
        }
 
 cgii_exit:
+       if ((*inode) && ((*inode)->i_ino == 0))
+               cifs_dbg(FYI, "inode number of zero returned\n");
+
        kfree(buf);
        cifs_put_tlink(tlink);
        return rc;
@@ -1066,10 +1099,7 @@ iget_no_retry:
 
 out:
        kfree(path);
-       /* can not call macro free_xid here since in a void func
-        * TODO: This is no longer true
-        */
-       _free_xid(xid);
+       free_xid(xid);
        return inode;
 }
 
index 60b5a11ee11b3d778b7f6e4850a70ac5cd10f293..889a840172eb8840daa73268e2ec5523122c4307 100644 (file)
@@ -50,25 +50,12 @@ static int
 symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
 {
        int rc;
-       unsigned int size;
-       struct crypto_shash *md5;
-       struct sdesc *sdescmd5;
-
-       md5 = crypto_alloc_shash("md5", 0, 0);
-       if (IS_ERR(md5)) {
-               rc = PTR_ERR(md5);
-               cifs_dbg(VFS, "%s: Crypto md5 allocation error %d\n",
-                        __func__, rc);
-               return rc;
-       }
-       size = sizeof(struct shash_desc) + crypto_shash_descsize(md5);
-       sdescmd5 = kmalloc(size, GFP_KERNEL);
-       if (!sdescmd5) {
-               rc = -ENOMEM;
+       struct crypto_shash *md5 = NULL;
+       struct sdesc *sdescmd5 = NULL;
+
+       rc = cifs_alloc_hash("md5", &md5, &sdescmd5);
+       if (rc)
                goto symlink_hash_err;
-       }
-       sdescmd5->shash.tfm = md5;
-       sdescmd5->shash.flags = 0x0;
 
        rc = crypto_shash_init(&sdescmd5->shash);
        if (rc) {
@@ -85,9 +72,7 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
                cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
 
 symlink_hash_err:
-       crypto_free_shash(md5);
-       kfree(sdescmd5);
-
+       cifs_free_hash(&md5, &sdescmd5);
        return rc;
 }
 
index a0dbced4a45c35b01107e532ee6167425b13ddff..460084a8eac54077010c12dee60d12e7c35fc5b8 100644 (file)
@@ -848,3 +848,57 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
        iov_iter_bvec(&ctx->iter, ITER_BVEC | rw, ctx->bv, npages, ctx->len);
        return 0;
 }
+
+/**
+ * cifs_alloc_hash - allocate hash and hash context together
+ *
+ * The caller has to make sure @sdesc is initialized to either NULL or
+ * a valid context. Both can be freed via cifs_free_hash().
+ */
+int
+cifs_alloc_hash(const char *name,
+               struct crypto_shash **shash, struct sdesc **sdesc)
+{
+       int rc = 0;
+       size_t size;
+
+       if (*sdesc != NULL)
+               return 0;
+
+       *shash = crypto_alloc_shash(name, 0, 0);
+       if (IS_ERR(*shash)) {
+               cifs_dbg(VFS, "could not allocate crypto %s\n", name);
+               rc = PTR_ERR(*shash);
+               *shash = NULL;
+               *sdesc = NULL;
+               return rc;
+       }
+
+       size = sizeof(struct shash_desc) + crypto_shash_descsize(*shash);
+       *sdesc = kmalloc(size, GFP_KERNEL);
+       if (*sdesc == NULL) {
+               cifs_dbg(VFS, "no memory left to allocate crypto %s\n", name);
+               crypto_free_shash(*shash);
+               *shash = NULL;
+               return -ENOMEM;
+       }
+
+       (*sdesc)->shash.tfm = *shash;
+       (*sdesc)->shash.flags = 0x0;
+       return 0;
+}
+
+/**
+ * cifs_free_hash - free hash and hash context together
+ *
+ * Freeing a NULL hash or context is safe.
+ */
+void
+cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
+{
+       kfree(*sdesc);
+       *sdesc = NULL;
+       if (*shash)
+               crypto_free_shash(*shash);
+       *shash = NULL;
+}
index 3d495e440c87c90386207e05fca529bcc9118784..aff8ce8ba34d55485d1d15aa8b7ea498cf6726f3 100644 (file)
@@ -1122,6 +1122,7 @@ struct smb_version_values smb1_values = {
        .exclusive_lock_type = 0,
        .shared_lock_type = LOCKING_ANDX_SHARED_LOCK,
        .unlock_lock_type = 0,
+       .header_preamble_size = 4,
        .header_size = sizeof(struct smb_hdr),
        .max_header_size = MAX_CIFS_HDR_SIZE,
        .read_rsp_size = sizeof(READ_RSP),
index 62c88dfed57b3f66fff931f4abbcc8126ca4cf11..3bfc9c99072439b8abfd3171fc9aeac2445fd66f 100644 (file)
@@ -745,7 +745,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
        "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"},
        {STATUS_DOMAIN_TRUST_INCONSISTENT, -EIO,
        "STATUS_DOMAIN_TRUST_INCONSISTENT"},
-       {STATUS_FS_DRIVER_REQUIRED, -EIO, "STATUS_FS_DRIVER_REQUIRED"},
+       {STATUS_FS_DRIVER_REQUIRED, -EOPNOTSUPP, "STATUS_FS_DRIVER_REQUIRED"},
        {STATUS_IMAGE_ALREADY_LOADED_AS_DLL, -EIO,
        "STATUS_IMAGE_ALREADY_LOADED_AS_DLL"},
        {STATUS_NETWORK_OPEN_RESTRICTION, -EIO,
index 76d03abaa38c8c50883a92b03b3edbfdb9901cfc..5406e95f5d922b190181d03599128f79e22d2a46 100644 (file)
@@ -150,7 +150,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
                }
                return 1;
        }
-       if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) {
+       if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE -
+           srvr->vals->header_preamble_size) {
                cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n",
                         mid);
                return 1;
@@ -189,26 +190,26 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
                }
        }
 
-       if (4 + len != length) {
-               cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n",
-                        length, 4 + len, mid);
+       if (srvr->vals->header_preamble_size + len != length) {
+               cifs_dbg(VFS, "Total length %u RFC1002 length %zu mismatch mid %llu\n",
+                        length, srvr->vals->header_preamble_size + len, mid);
                return 1;
        }
 
        clc_len = smb2_calc_size(hdr);
 
-       if (4 + len != clc_len) {
-               cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
-                        clc_len, 4 + len, mid);
+       if (srvr->vals->header_preamble_size + len != clc_len) {
+               cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n",
+                        clc_len, srvr->vals->header_preamble_size + len, mid);
                /* create failed on symlink */
                if (command == SMB2_CREATE_HE &&
                    shdr->Status == STATUS_STOPPED_ON_SYMLINK)
                        return 0;
                /* Windows 7 server returns 24 bytes more */
-               if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
+               if (clc_len + 24 - srvr->vals->header_preamble_size == len && command == SMB2_OPLOCK_BREAK_HE)
                        return 0;
                /* server can return one byte more due to implied bcc[0] */
-               if (clc_len == 4 + len + 1)
+               if (clc_len == srvr->vals->header_preamble_size + len + 1)
                        return 0;
 
                /*
@@ -218,10 +219,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
                 * Log the server error (once), but allow it and continue
                 * since the frame is parseable.
                 */
-               if (clc_len < 4 /* RFC1001 header size */ + len) {
+               if (clc_len < srvr->vals->header_preamble_size /* RFC1001 header size */ + len) {
                        printk_once(KERN_WARNING
-                               "SMB2 server sent bad RFC1001 len %d not %d\n",
-                               len, clc_len - 4);
+                               "SMB2 server sent bad RFC1001 len %d not %zu\n",
+                               len, clc_len - srvr->vals->header_preamble_size);
                        return 0;
                }
 
@@ -706,3 +707,67 @@ smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
 
        return 0;
 }
+
+#ifdef CONFIG_CIFS_SMB311
+/**
+ * smb311_update_preauth_hash - update @ses hash with the packet data in @iov
+ *
+ * Assumes @iov does not contain the rfc1002 length and iov[0] has the
+ * SMB2 header.
+ */
+int
+smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec)
+{
+       int i, rc;
+       struct sdesc *d;
+       struct smb2_sync_hdr *hdr;
+
+       if (ses->server->tcpStatus == CifsGood) {
+               /* skip non smb311 connections */
+               if (ses->server->dialect != SMB311_PROT_ID)
+                       return 0;
+
+               /* skip last sess setup response */
+               hdr = (struct smb2_sync_hdr *)iov[0].iov_base;
+               if (hdr->Flags & SMB2_FLAGS_SIGNED)
+                       return 0;
+       }
+
+       rc = smb311_crypto_shash_allocate(ses->server);
+       if (rc)
+               return rc;
+
+       d = ses->server->secmech.sdescsha512;
+       rc = crypto_shash_init(&d->shash);
+       if (rc) {
+               cifs_dbg(VFS, "%s: could not init sha512 shash\n", __func__);
+               return rc;
+       }
+
+       rc = crypto_shash_update(&d->shash, ses->preauth_sha_hash,
+                                SMB2_PREAUTH_HASH_SIZE);
+       if (rc) {
+               cifs_dbg(VFS, "%s: could not update sha512 shash\n", __func__);
+               return rc;
+       }
+
+       for (i = 0; i < nvec; i++) {
+               rc = crypto_shash_update(&d->shash,
+                                        iov[i].iov_base, iov[i].iov_len);
+               if (rc) {
+                       cifs_dbg(VFS, "%s: could not update sha512 shash\n",
+                                __func__);
+                       return rc;
+               }
+       }
+
+       rc = crypto_shash_final(&d->shash, ses->preauth_sha_hash);
+       if (rc) {
+               cifs_dbg(VFS, "%s: could not finalize sha512 shash\n",
+                        __func__);
+               return rc;
+       }
+
+       return 0;
+}
+#endif
index eb68e2fcc5001825adab93e623990d50895afe59..968b1d43a1ea5a792fef2a0c1e429534e92213b0 100644 (file)
@@ -1412,7 +1412,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
        } while (rc == -EAGAIN);
 
        if (rc) {
-               if (rc != -ENOENT)
+               if ((rc != -ENOENT) && (rc != -EOPNOTSUPP))
                        cifs_dbg(VFS, "ioctl error in smb2_get_dfs_refer rc=%d\n", rc);
                goto out;
        }
@@ -1457,6 +1457,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
        unsigned int sub_offset;
        unsigned int print_len;
        unsigned int print_offset;
+       struct cifs_ses *ses = tcon->ses;
+       struct TCP_Server_Info *server = ses->server;
 
        cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
 
@@ -1479,7 +1481,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
        }
 
        if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
-           get_rfc1002_length(err_buf) + 4 < SMB2_SYMLINK_STRUCT_SIZE) {
+           get_rfc1002_length(err_buf) + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
                kfree(utf16_path);
                return -ENOENT;
        }
@@ -1492,13 +1494,13 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
        print_len = le16_to_cpu(symlink->PrintNameLength);
        print_offset = le16_to_cpu(symlink->PrintNameOffset);
 
-       if (get_rfc1002_length(err_buf) + 4 <
+       if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
                        SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
                kfree(utf16_path);
                return -ENOENT;
        }
 
-       if (get_rfc1002_length(err_buf) + 4 <
+       if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
                        SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
                kfree(utf16_path);
                return -ENOENT;
@@ -2050,7 +2052,8 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile)
 }
 
 static void
-fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
+fill_transform_hdr(struct TCP_Server_Info *server,
+                  struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
 {
        struct smb2_sync_hdr *shdr =
                        (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base;
@@ -2062,10 +2065,19 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
        tr_hdr->Flags = cpu_to_le16(0x01);
        get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE);
        memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
-       inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - 4);
+       inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - server->vals->header_preamble_size);
        inc_rfc1001_len(tr_hdr, orig_len);
 }
 
+/* We can not use the normal sg_set_buf() as we will sometimes pass a
+ * stack object as buf.
+ */
+static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
+                                  unsigned int buflen)
+{
+       sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
+}
+
 static struct scatterlist *
 init_sg(struct smb_rqst *rqst, u8 *sign)
 {
@@ -2080,16 +2092,16 @@ init_sg(struct smb_rqst *rqst, u8 *sign)
                return NULL;
 
        sg_init_table(sg, sg_len);
-       sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len);
+       smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len);
        for (i = 1; i < rqst->rq_nvec; i++)
-               sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
+               smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
                                                rqst->rq_iov[i].iov_len);
        for (j = 0; i < sg_len - 1; i++, j++) {
                unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz
                                                        : rqst->rq_tailsz;
                sg_set_page(&sg[i], rqst->rq_pages[j], len, 0);
        }
-       sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE);
+       smb2_sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE);
        return sg;
 }
 
@@ -2125,7 +2137,7 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
 {
        struct smb2_transform_hdr *tr_hdr =
                        (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base;
-       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
+       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20 - server->vals->header_preamble_size;
        int rc = 0;
        struct scatterlist *sg;
        u8 sign[SMB2_SIGNATURE_SIZE] = {};
@@ -2253,7 +2265,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
                goto err_free_iov;
 
        /* fill the 1st iov with a transform header */
-       fill_transform_hdr(tr_hdr, old_rq);
+       fill_transform_hdr(server, tr_hdr, old_rq);
        new_rq->rq_iov[0].iov_base = tr_hdr;
        new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr);
 
@@ -2335,10 +2347,10 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
        if (rc)
                return rc;
 
-       memmove(buf + 4, iov[1].iov_base, buf_data_size);
+       memmove(buf + server->vals->header_preamble_size, iov[1].iov_base, buf_data_size);
        hdr = (struct smb2_hdr *)buf;
        hdr->smb2_buf_length = cpu_to_be32(buf_data_size + page_data_size);
-       server->total_read = buf_data_size + page_data_size + 4;
+       server->total_read = buf_data_size + page_data_size + server->vals->header_preamble_size;
 
        return rc;
 }
@@ -2442,7 +2454,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                return 0;
        }
 
-       data_offset = server->ops->read_data_offset(buf) + 4;
+       data_offset = server->ops->read_data_offset(buf) + server->vals->header_preamble_size;
 #ifdef CONFIG_CIFS_SMB_DIRECT
        use_rdma_mr = rdata->mr;
 #endif
@@ -2538,11 +2550,12 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
        unsigned int npages;
        struct page **pages;
        unsigned int len;
-       unsigned int buflen = get_rfc1002_length(buf) + 4;
+       unsigned int buflen = get_rfc1002_length(buf) + server->vals->header_preamble_size;
        int rc;
        int i = 0;
 
-       len = min_t(unsigned int, buflen, server->vals->read_rsp_size - 4 +
+       len = min_t(unsigned int, buflen, server->vals->read_rsp_size -
+               server->vals->header_preamble_size +
                sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1;
 
        rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len);
@@ -2550,8 +2563,9 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
                return rc;
        server->total_read += rc;
 
-       len = le32_to_cpu(tr_hdr->OriginalMessageSize) + 4 -
-                                               server->vals->read_rsp_size;
+       len = le32_to_cpu(tr_hdr->OriginalMessageSize) +
+               server->vals->header_preamble_size -
+               server->vals->read_rsp_size;
        npages = DIV_ROUND_UP(len, PAGE_SIZE);
 
        pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
@@ -2577,7 +2591,8 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
        if (rc)
                goto free_pages;
 
-       rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size - 4,
+       rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size -
+                             server->vals->header_preamble_size,
                              pages, npages, len);
        if (rc)
                goto free_pages;
@@ -2614,7 +2629,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
        struct mid_q_entry *mid_entry;
 
        /* switch to large buffer if too big for a small one */
-       if (pdu_length + 4 > MAX_CIFS_SMALL_BUFFER_SIZE) {
+       if (pdu_length + server->vals->header_preamble_size > MAX_CIFS_SMALL_BUFFER_SIZE) {
                server->large_buf = true;
                memcpy(server->bigbuf, buf, server->total_read);
                buf = server->bigbuf;
@@ -2622,12 +2637,13 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
 
        /* now read the rest */
        length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
-                               pdu_length - HEADER_SIZE(server) + 1 + 4);
+                               pdu_length - HEADER_SIZE(server) + 1 +
+                               server->vals->header_preamble_size);
        if (length < 0)
                return length;
        server->total_read += length;
 
-       buf_size = pdu_length + 4 - sizeof(struct smb2_transform_hdr);
+       buf_size = pdu_length + server->vals->header_preamble_size - sizeof(struct smb2_transform_hdr);
        length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0);
        if (length)
                return length;
@@ -2656,7 +2672,7 @@ smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
        struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
        unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
 
-       if (pdu_length + 4 < sizeof(struct smb2_transform_hdr) +
+       if (pdu_length + server->vals->header_preamble_size < sizeof(struct smb2_transform_hdr) +
                                                sizeof(struct smb2_sync_hdr)) {
                cifs_dbg(VFS, "Transform message is too small (%u)\n",
                         pdu_length);
@@ -2665,14 +2681,14 @@ smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
                return -ECONNABORTED;
        }
 
-       if (pdu_length + 4 < orig_len + sizeof(struct smb2_transform_hdr)) {
+       if (pdu_length + server->vals->header_preamble_size < orig_len + sizeof(struct smb2_transform_hdr)) {
                cifs_dbg(VFS, "Transform message is broken\n");
                cifs_reconnect(server);
                wake_up(&server->response_q);
                return -ECONNABORTED;
        }
 
-       if (pdu_length + 4 > CIFSMaxBufSize + MAX_HEADER_SIZE(server))
+       if (pdu_length + server->vals->header_preamble_size > CIFSMaxBufSize + MAX_HEADER_SIZE(server))
                return receive_encrypted_read(server, mid);
 
        return receive_encrypted_standard(server, mid);
@@ -2683,7 +2699,8 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 {
        char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
 
-       return handle_read_data(server, mid, buf, get_rfc1002_length(buf) + 4,
+       return handle_read_data(server, mid, buf, get_rfc1002_length(buf) +
+                               server->vals->header_preamble_size,
                                NULL, 0, 0);
 }
 
@@ -3088,6 +3105,7 @@ struct smb_version_values smb20_values = {
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
        .header_size = sizeof(struct smb2_hdr),
+       .header_preamble_size = 4,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
@@ -3108,6 +3126,7 @@ struct smb_version_values smb21_values = {
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
        .header_size = sizeof(struct smb2_hdr),
+       .header_preamble_size = 4,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
@@ -3128,6 +3147,7 @@ struct smb_version_values smb3any_values = {
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
        .header_size = sizeof(struct smb2_hdr),
+       .header_preamble_size = 4,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
@@ -3148,6 +3168,7 @@ struct smb_version_values smbdefault_values = {
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
        .header_size = sizeof(struct smb2_hdr),
+       .header_preamble_size = 4,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
@@ -3168,6 +3189,7 @@ struct smb_version_values smb30_values = {
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
        .header_size = sizeof(struct smb2_hdr),
+       .header_preamble_size = 4,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
@@ -3188,6 +3210,7 @@ struct smb_version_values smb302_values = {
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
        .header_size = sizeof(struct smb2_hdr),
+       .header_preamble_size = 4,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
@@ -3209,6 +3232,7 @@ struct smb_version_values smb311_values = {
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
        .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
        .header_size = sizeof(struct smb2_hdr),
+       .header_preamble_size = 4,
        .max_header_size = MAX_SMB2_HDR_SIZE,
        .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
        .lock_cmd = SMB2_LOCK,
index 63778ac22fd93e68663213ab8943f69c504837dc..f7741cee2a4cc73366dba1c724a8c74c38f11744 100644 (file)
@@ -453,6 +453,10 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
                return rc;
 
        req->sync_hdr.SessionId = 0;
+#ifdef CONFIG_CIFS_SMB311
+       memset(server->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
+       memset(ses->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
+#endif
 
        if (strcmp(ses->server->vals->version_string,
                   SMB3ANY_VERSION_STRING) == 0) {
@@ -564,6 +568,15 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 
        /* BB: add check that dialect was valid given dialect(s) we asked for */
 
+#ifdef CONFIG_CIFS_SMB311
+       /*
+        * Keep a copy of the hash after negprot. This hash will be
+        * the starting hash value for all sessions made from this
+        * server.
+        */
+       memcpy(server->preauth_sha_hash, ses->preauth_sha_hash,
+              SMB2_PREAUTH_HASH_SIZE);
+#endif
        /* SMB2 only has an extended negflavor */
        server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
        /* set it to the maximum buffer size value we can send with 1 credit */
@@ -571,8 +584,10 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
                               SMB2_MAX_BUFFER_SIZE);
        server->max_read = le32_to_cpu(rsp->MaxReadSize);
        server->max_write = le32_to_cpu(rsp->MaxWriteSize);
-       /* BB Do we need to validate the SecurityMode? */
        server->sec_mode = le16_to_cpu(rsp->SecurityMode);
+       if ((server->sec_mode & SMB2_SEC_MODE_FLAGS_ALL) != server->sec_mode)
+               cifs_dbg(FYI, "Server returned unexpected security mode 0x%x\n",
+                               server->sec_mode);
        server->capabilities = le32_to_cpu(rsp->Capabilities);
        /* Internal types */
        server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
@@ -621,6 +636,10 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
                return 0;
 #endif
 
+       /* In SMB3.11 preauth integrity supersedes validate negotiate */
+       if (tcon->ses->server->dialect == SMB311_PROT_ID)
+               return 0;
+
        /*
         * validation ioctl must be signed, so no point sending this if we
         * can not sign it (ie are not known user).  Even if signing is not
@@ -1148,6 +1167,14 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
        sess_data->buf0_type = CIFS_NO_BUFFER;
        sess_data->nls_cp = (struct nls_table *) nls_cp;
 
+#ifdef CONFIG_CIFS_SMB311
+       /*
+        * Initialize the session hash with the server one.
+        */
+       memcpy(ses->preauth_sha_hash, ses->server->preauth_sha_hash,
+              SMB2_PREAUTH_HASH_SIZE);
+#endif
+
        while (sess_data->func)
                sess_data->func(sess_data);
 
@@ -1280,6 +1307,11 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
        iov[1].iov_base = unc_path;
        iov[1].iov_len = unc_path_len;
 
+       /* 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1 */
+       if ((ses->server->dialect == SMB311_PROT_ID) &&
+           !encryption_required(tcon))
+               req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
+
        rc = smb2_send_recv(xid, ses, iov, 2, &resp_buftype, flags, &rsp_iov);
        cifs_small_buf_release(req);
        rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base;
@@ -1441,7 +1473,7 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
        unsigned int remaining;
        char *name;
 
-       data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
+       data_offset = (char *)rsp + server->vals->header_preamble_size + le32_to_cpu(rsp->CreateContextsOffset);
        remaining = le32_to_cpu(rsp->CreateContextsLength);
        cc = (struct create_context *)data_offset;
        while (remaining >= sizeof(struct create_context)) {
@@ -1738,8 +1770,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
                rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
                                                 &name_len,
                                                 tcon->treeName, path);
-               if (rc)
+               if (rc) {
+                       cifs_small_buf_release(req);
                        return rc;
+               }
                req->NameLength = cpu_to_le16(name_len * 2);
                uni_path_len = copy_size;
                path = copy_path;
@@ -1750,8 +1784,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
                if (uni_path_len % 8 != 0) {
                        copy_size = roundup(uni_path_len, 8);
                        copy_path = kzalloc(copy_size, GFP_KERNEL);
-                       if (!copy_path)
+                       if (!copy_path) {
+                               cifs_small_buf_release(req);
                                return -ENOMEM;
+                       }
                        memcpy((char *)copy_path, (const char *)path,
                               uni_path_len);
                        uni_path_len = copy_size;
@@ -3418,6 +3454,7 @@ static int
 build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
                   int outbuf_len, u64 persistent_fid, u64 volatile_fid)
 {
+       struct TCP_Server_Info *server = tcon->ses->server;
        int rc;
        struct smb2_query_info_req *req;
        unsigned int total_len;
@@ -3440,7 +3477,7 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
        req->InputBufferOffset =
                        cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
        req->OutputBufferLength = cpu_to_le32(
-               outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - 4);
+               outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - server->vals->header_preamble_size);
 
        iov->iov_base = (char *)req;
        iov->iov_len = total_len;
@@ -3457,6 +3494,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
        int rc = 0;
        int resp_buftype;
        struct cifs_ses *ses = tcon->ses;
+       struct TCP_Server_Info *server = ses->server;
        struct smb2_fs_full_size_info *info = NULL;
        int flags = 0;
 
@@ -3477,7 +3515,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
        }
        rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
 
-       info = (struct smb2_fs_full_size_info *)(4 /* RFC1001 len */ +
+       info = (struct smb2_fs_full_size_info *)(server->vals->header_preamble_size +
                le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr);
        rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
                          le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
@@ -3500,6 +3538,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
        int rc = 0;
        int resp_buftype, max_len, min_len;
        struct cifs_ses *ses = tcon->ses;
+       struct TCP_Server_Info *server = ses->server;
        unsigned int rsp_len, offset;
        int flags = 0;
 
@@ -3540,15 +3579,15 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
                goto qfsattr_exit;
 
        if (level == FS_ATTRIBUTE_INFORMATION)
-               memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset
+               memcpy(&tcon->fsAttrInfo, server->vals->header_preamble_size + offset
                        + (char *)&rsp->hdr, min_t(unsigned int,
                        rsp_len, max_len));
        else if (level == FS_DEVICE_INFORMATION)
-               memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset
+               memcpy(&tcon->fsDevInfo, server->vals->header_preamble_size + offset
                        + (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO));
        else if (level == FS_SECTOR_SIZE_INFORMATION) {
                struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
-                       (4 /* RFC1001 len */ + offset + (char *)&rsp->hdr);
+                       (server->vals->header_preamble_size + offset + (char *)&rsp->hdr);
                tcon->ss_flags = le32_to_cpu(ss_info->Flags);
                tcon->perf_sector_size =
                        le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
index 2a2b34ccaf492026d1a2e787836b6304ee3997dc..253e2c7c952f64e1fef446fbad1895dfafe753fa 100644 (file)
@@ -249,6 +249,8 @@ struct smb2_negotiate_req {
 /* SecurityMode flags */
 #define        SMB2_NEGOTIATE_SIGNING_ENABLED  0x0001
 #define SMB2_NEGOTIATE_SIGNING_REQUIRED        0x0002
+#define SMB2_SEC_MODE_FLAGS_ALL                0x0003
+
 /* Capabilities flags */
 #define SMB2_GLOBAL_CAP_DFS            0x00000001
 #define SMB2_GLOBAL_CAP_LEASING                0x00000002 /* Resp only New to SMB2.1 */
@@ -264,6 +266,7 @@ struct smb2_negotiate_req {
 #define SMB311_SALT_SIZE                       32
 /* Hash Algorithm Types */
 #define SMB2_PREAUTH_INTEGRITY_SHA512  cpu_to_le16(0x0001)
+#define SMB2_PREAUTH_HASH_SIZE 64
 
 struct smb2_preauth_neg_context {
        __le16  ContextType; /* 1 */
index 05287b01f5961c57ae0730558328424a4ee32aef..cbcce3f7e86f92c57bc739906f95f5ed6b1d989b 100644 (file)
@@ -202,4 +202,9 @@ extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *);
 
 extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
                                        enum securityEnum);
+#ifdef CONFIG_CIFS_SMB311
+extern int smb311_crypto_shash_allocate(struct TCP_Server_Info *server);
+extern int smb311_update_preauth_hash(struct cifs_ses *ses,
+                                     struct kvec *iov, int nvec);
+#endif
 #endif                 /* _SMB2PROTO_H */
index 99493946e2f9abcf02673bf685238b0313da4180..bf49cb73b9e6ad80f4e67b961e22640fda6df3db 100644 (file)
 static int
 smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
 {
-       int rc;
-       unsigned int size;
+       return cifs_alloc_hash("hmac(sha256)",
+                              &server->secmech.hmacsha256,
+                              &server->secmech.sdeschmacsha256);
+}
 
-       if (server->secmech.sdeschmacsha256 != NULL)
-               return 0; /* already allocated */
+static int
+smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
+{
+       struct cifs_secmech *p = &server->secmech;
+       int rc;
 
-       server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
-       if (IS_ERR(server->secmech.hmacsha256)) {
-               cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
-               rc = PTR_ERR(server->secmech.hmacsha256);
-               server->secmech.hmacsha256 = NULL;
-               return rc;
-       }
+       rc = cifs_alloc_hash("hmac(sha256)",
+                            &p->hmacsha256,
+                            &p->sdeschmacsha256);
+       if (rc)
+               goto err;
 
-       size = sizeof(struct shash_desc) +
-                       crypto_shash_descsize(server->secmech.hmacsha256);
-       server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
-       if (!server->secmech.sdeschmacsha256) {
-               crypto_free_shash(server->secmech.hmacsha256);
-               server->secmech.hmacsha256 = NULL;
-               return -ENOMEM;
-       }
-       server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
-       server->secmech.sdeschmacsha256->shash.flags = 0x0;
+       rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
+       if (rc)
+               goto err;
 
        return 0;
+err:
+       cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
+       return rc;
 }
 
-static int
-smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
+#ifdef CONFIG_CIFS_SMB311
+int
+smb311_crypto_shash_allocate(struct TCP_Server_Info *server)
 {
-       unsigned int size;
-       int rc;
-
-       if (server->secmech.sdesccmacaes != NULL)
-               return 0;  /* already allocated */
+       struct cifs_secmech *p = &server->secmech;
+       int rc = 0;
 
-       rc = smb2_crypto_shash_allocate(server);
+       rc = cifs_alloc_hash("hmac(sha256)",
+                            &p->hmacsha256,
+                            &p->sdeschmacsha256);
        if (rc)
                return rc;
 
-       server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
-       if (IS_ERR(server->secmech.cmacaes)) {
-               cifs_dbg(VFS, "could not allocate crypto cmac-aes");
-               kfree(server->secmech.sdeschmacsha256);
-               server->secmech.sdeschmacsha256 = NULL;
-               crypto_free_shash(server->secmech.hmacsha256);
-               server->secmech.hmacsha256 = NULL;
-               rc = PTR_ERR(server->secmech.cmacaes);
-               server->secmech.cmacaes = NULL;
-               return rc;
-       }
+       rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
+       if (rc)
+               goto err;
 
-       size = sizeof(struct shash_desc) +
-                       crypto_shash_descsize(server->secmech.cmacaes);
-       server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
-       if (!server->secmech.sdesccmacaes) {
-               cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
-               kfree(server->secmech.sdeschmacsha256);
-               server->secmech.sdeschmacsha256 = NULL;
-               crypto_free_shash(server->secmech.hmacsha256);
-               crypto_free_shash(server->secmech.cmacaes);
-               server->secmech.hmacsha256 = NULL;
-               server->secmech.cmacaes = NULL;
-               return -ENOMEM;
-       }
-       server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
-       server->secmech.sdesccmacaes->shash.flags = 0x0;
+       rc = cifs_alloc_hash("sha512", &p->sha512, &p->sdescsha512);
+       if (rc)
+               goto err;
 
        return 0;
+
+err:
+       cifs_free_hash(&p->cmacaes, &p->sdesccmacaes);
+       cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
+       return rc;
 }
+#endif
 
 static struct cifs_ses *
 smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
@@ -457,7 +442,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
                cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
                return rc;
        }
-       
+
        rc = __cifs_calc_signature(rqst, server, sigptr,
                                   &server->secmech.sdesccmacaes->shash);
 
index 91710eb571fb3a61a1fe601d2eb72b0e7b15cc8a..5008af546dd16d6e276953b24b354cd7bb54796d 100644 (file)
@@ -862,6 +862,8 @@ static int smbd_post_send_negotiate_req(struct smbd_connection *info)
        ib_dma_unmap_single(info->id->device, request->sge[0].addr,
                request->sge[0].length, DMA_TO_DEVICE);
 
+       smbd_disconnect_rdma_connection(info);
+
 dma_mapping_failed:
        mempool_free(request, info->request_mempool);
        return rc;
@@ -1025,7 +1027,7 @@ static int smbd_post_send(struct smbd_connection *info,
 
        for (i = 0; i < request->num_sge; i++) {
                log_rdma_send(INFO,
-                       "rdma_request sge[%d] addr=%llu legnth=%u\n",
+                       "rdma_request sge[%d] addr=%llu length=%u\n",
                        i, request->sge[0].addr, request->sge[0].length);
                ib_dma_sync_single_for_device(
                        info->id->device,
@@ -1061,6 +1063,7 @@ static int smbd_post_send(struct smbd_connection *info,
                        if (atomic_dec_and_test(&info->send_pending))
                                wake_up(&info->wait_send_pending);
                }
+               smbd_disconnect_rdma_connection(info);
        } else
                /* Reset timer for idle connection after packet is sent */
                mod_delayed_work(info->workqueue, &info->idle_timer_work,
@@ -1202,7 +1205,7 @@ static int smbd_post_recv(
        if (rc) {
                ib_dma_unmap_single(info->id->device, response->sge.addr,
                                    response->sge.length, DMA_FROM_DEVICE);
-
+               smbd_disconnect_rdma_connection(info);
                log_rdma_recv(ERR, "ib_post_recv failed rc=%d\n", rc);
        }
 
@@ -1498,8 +1501,8 @@ int smbd_reconnect(struct TCP_Server_Info *server)
        log_rdma_event(INFO, "reconnecting rdma session\n");
 
        if (!server->smbd_conn) {
-               log_rdma_event(ERR, "rdma session already destroyed\n");
-               return -EINVAL;
+               log_rdma_event(INFO, "rdma session already destroyed\n");
+               goto create_conn;
        }
 
        /*
@@ -1512,15 +1515,19 @@ int smbd_reconnect(struct TCP_Server_Info *server)
        }
 
        /* wait until the transport is destroyed */
-       wait_event(server->smbd_conn->wait_destroy,
-               server->smbd_conn->transport_status == SMBD_DESTROYED);
+       if (!wait_event_timeout(server->smbd_conn->wait_destroy,
+               server->smbd_conn->transport_status == SMBD_DESTROYED, 5*HZ))
+               return -EAGAIN;
 
        destroy_workqueue(server->smbd_conn->workqueue);
        kfree(server->smbd_conn);
 
+create_conn:
        log_rdma_event(INFO, "creating rdma session\n");
        server->smbd_conn = smbd_get_connection(
                server, (struct sockaddr *) &server->dstaddr);
+       log_rdma_event(INFO, "created rdma session info=%p\n",
+               server->smbd_conn);
 
        return server->smbd_conn ? 0 : -ENOENT;
 }
@@ -2295,7 +2302,7 @@ static void smbd_mr_recovery_work(struct work_struct *work)
                                rc = ib_dereg_mr(smbdirect_mr->mr);
                                if (rc) {
                                        log_rdma_mr(ERR,
-                                               "ib_dereg_mr faield rc=%x\n",
+                                               "ib_dereg_mr failed rc=%x\n",
                                                rc);
                                        smbd_disconnect_rdma_connection(info);
                                }
@@ -2542,6 +2549,8 @@ dma_map_error:
        if (atomic_dec_and_test(&info->mr_used_count))
                wake_up(&info->wait_for_mr_cleanup);
 
+       smbd_disconnect_rdma_connection(info);
+
        return NULL;
 }
 
index c12bffefa3c9b59b2290ecdb243ae308b08e7224..a0b80ac651a60a385738ff5dff8b9cfa01de2ce4 100644 (file)
@@ -121,25 +121,12 @@ int
 mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
 {
        int rc;
-       unsigned int size;
-       struct crypto_shash *md4;
-       struct sdesc *sdescmd4;
-
-       md4 = crypto_alloc_shash("md4", 0, 0);
-       if (IS_ERR(md4)) {
-               rc = PTR_ERR(md4);
-               cifs_dbg(VFS, "%s: Crypto md4 allocation error %d\n",
-                        __func__, rc);
-               return rc;
-       }
-       size = sizeof(struct shash_desc) + crypto_shash_descsize(md4);
-       sdescmd4 = kmalloc(size, GFP_KERNEL);
-       if (!sdescmd4) {
-               rc = -ENOMEM;
+       struct crypto_shash *md4 = NULL;
+       struct sdesc *sdescmd4 = NULL;
+
+       rc = cifs_alloc_hash("md4", &md4, &sdescmd4);
+       if (rc)
                goto mdfour_err;
-       }
-       sdescmd4->shash.tfm = md4;
-       sdescmd4->shash.flags = 0x0;
 
        rc = crypto_shash_init(&sdescmd4->shash);
        if (rc) {
@@ -156,9 +143,7 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
                cifs_dbg(VFS, "%s: Could not generate md4 hash\n", __func__);
 
 mdfour_err:
-       crypto_free_shash(md4);
-       kfree(sdescmd4);
-
+       cifs_free_hash(&md4, &sdescmd4);
        return rc;
 }
 
index 9779b3292d8e8d1cfc8a38558f1e04644b0ed224..279718dcb2edb0960bd772d5fc356932a4556747 100644 (file)
@@ -37,6 +37,7 @@
 #include "cifsglob.h"
 #include "cifsproto.h"
 #include "cifs_debug.h"
+#include "smb2proto.h"
 #include "smbdirect.h"
 
 /* Max number of iovectors we can use off the stack when sending requests. */
@@ -751,6 +752,12 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
        if (rc < 0)
                goto out;
 
+#ifdef CONFIG_CIFS_SMB311
+       if (ses->status == CifsNew)
+               smb311_update_preauth_hash(ses, rqst->rq_iov+1,
+                                          rqst->rq_nvec-1);
+#endif
+
        if (timeout == CIFS_ASYNC_OP)
                goto out;
 
@@ -783,12 +790,23 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
 
        buf = (char *)midQ->resp_buf;
        resp_iov->iov_base = buf;
-       resp_iov->iov_len = get_rfc1002_length(buf) + 4;
+       resp_iov->iov_len = get_rfc1002_length(buf) +
+               ses->server->vals->header_preamble_size;
        if (midQ->large_buf)
                *resp_buf_type = CIFS_LARGE_BUFFER;
        else
                *resp_buf_type = CIFS_SMALL_BUFFER;
 
+#ifdef CONFIG_CIFS_SMB311
+       if (ses->status == CifsNew) {
+               struct kvec iov = {
+                       .iov_base = buf + 4,
+                       .iov_len = get_rfc1002_length(buf)
+               };
+               smb311_update_preauth_hash(ses, &iov, 1);
+       }
+#endif
+
        credits = ses->server->ops->get_credits(midQ);
 
        rc = ses->server->ops->check_receive(midQ, ses->server,