aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsencrypt.c195
-rw-r--r--fs/cifs/cifsglob.h17
-rw-r--r--fs/cifs/cifsproto.h1
-rw-r--r--fs/cifs/connect.c6
-rw-r--r--fs/cifs/dir.c14
-rw-r--r--fs/cifs/file.c54
-rw-r--r--fs/cifs/inode.c5
-rw-r--r--fs/cifs/smb1ops.c29
-rw-r--r--fs/cifs/smb2file.c24
-rw-r--r--fs/cifs/smb2inode.c57
-rw-r--r--fs/cifs/smb2ops.c54
-rw-r--r--fs/cifs/smb2pdu.c220
-rw-r--r--fs/cifs/smb2pdu.h14
-rw-r--r--fs/cifs/smb2proto.h16
-rw-r--r--fs/cifs/smb2transport.c90
15 files changed, 515 insertions, 281 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 3d8bf941d126..45e57cc38200 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsencrypt.c 2 * fs/cifs/cifsencrypt.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2005,2006 4 * Copyright (C) International Business Machines Corp., 2005,2013
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -31,6 +31,36 @@
31#include <linux/random.h> 31#include <linux/random.h>
32#include <linux/highmem.h> 32#include <linux/highmem.h>
33 33
34static int
35cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
36{
37 int rc;
38 unsigned int size;
39
40 if (server->secmech.sdescmd5 != NULL)
41 return 0; /* already allocated */
42
43 server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
44 if (IS_ERR(server->secmech.md5)) {
45 cifs_dbg(VFS, "could not allocate crypto md5\n");
46 return PTR_ERR(server->secmech.md5);
47 }
48
49 size = sizeof(struct shash_desc) +
50 crypto_shash_descsize(server->secmech.md5);
51 server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
52 if (!server->secmech.sdescmd5) {
53 rc = -ENOMEM;
54 crypto_free_shash(server->secmech.md5);
55 server->secmech.md5 = NULL;
56 return rc;
57 }
58 server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
59 server->secmech.sdescmd5->shash.flags = 0x0;
60
61 return 0;
62}
63
34/* 64/*
35 * Calculate and return the CIFS signature based on the mac key and SMB PDU. 65 * Calculate and return the CIFS signature based on the mac key and SMB PDU.
36 * The 16 byte signature must be allocated by the caller. Note we only use the 66 * The 16 byte signature must be allocated by the caller. Note we only use the
@@ -50,8 +80,11 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
50 return -EINVAL; 80 return -EINVAL;
51 81
52 if (!server->secmech.sdescmd5) { 82 if (!server->secmech.sdescmd5) {
53 cifs_dbg(VFS, "%s: Can't generate signature\n", __func__); 83 rc = cifs_crypto_shash_md5_allocate(server);
54 return -1; 84 if (rc) {
85 cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__);
86 return -1;
87 }
55 } 88 }
56 89
57 rc = crypto_shash_init(&server->secmech.sdescmd5->shash); 90 rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
@@ -556,6 +589,33 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
556 return rc; 589 return rc;
557} 590}
558 591
592static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
593{
594 unsigned int size;
595
596 /* check if already allocated */
597 if (server->secmech.sdeschmacmd5)
598 return 0;
599
600 server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
601 if (IS_ERR(server->secmech.hmacmd5)) {
602 cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
603 return PTR_ERR(server->secmech.hmacmd5);
604 }
605
606 size = sizeof(struct shash_desc) +
607 crypto_shash_descsize(server->secmech.hmacmd5);
608 server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
609 if (!server->secmech.sdeschmacmd5) {
610 crypto_free_shash(server->secmech.hmacmd5);
611 server->secmech.hmacmd5 = NULL;
612 return -ENOMEM;
613 }
614 server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
615 server->secmech.sdeschmacmd5->shash.flags = 0x0;
616
617 return 0;
618}
559 619
560int 620int
561setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) 621setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
@@ -606,6 +666,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
606 666
607 memcpy(ses->auth_key.response + baselen, tiblob, tilen); 667 memcpy(ses->auth_key.response + baselen, tiblob, tilen);
608 668
669 rc = crypto_hmacmd5_alloc(ses->server);
670 if (rc) {
671 cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
672 goto setup_ntlmv2_rsp_ret;
673 }
674
609 /* calculate ntlmv2_hash */ 675 /* calculate ntlmv2_hash */
610 rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp); 676 rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
611 if (rc) { 677 if (rc) {
@@ -705,123 +771,32 @@ calc_seckey(struct cifs_ses *ses)
705void 771void
706cifs_crypto_shash_release(struct TCP_Server_Info *server) 772cifs_crypto_shash_release(struct TCP_Server_Info *server)
707{ 773{
708 if (server->secmech.cmacaes) 774 if (server->secmech.cmacaes) {
709 crypto_free_shash(server->secmech.cmacaes); 775 crypto_free_shash(server->secmech.cmacaes);
776 server->secmech.cmacaes = NULL;
777 }
710 778
711 if (server->secmech.hmacsha256) 779 if (server->secmech.hmacsha256) {
712 crypto_free_shash(server->secmech.hmacsha256); 780 crypto_free_shash(server->secmech.hmacsha256);
781 server->secmech.hmacsha256 = NULL;
782 }
713 783
714 if (server->secmech.md5) 784 if (server->secmech.md5) {
715 crypto_free_shash(server->secmech.md5); 785 crypto_free_shash(server->secmech.md5);
786 server->secmech.md5 = NULL;
787 }
716 788
717 if (server->secmech.hmacmd5) 789 if (server->secmech.hmacmd5) {
718 crypto_free_shash(server->secmech.hmacmd5); 790 crypto_free_shash(server->secmech.hmacmd5);
791 server->secmech.hmacmd5 = NULL;
792 }
719 793
720 kfree(server->secmech.sdesccmacaes); 794 kfree(server->secmech.sdesccmacaes);
721 795 server->secmech.sdesccmacaes = NULL;
722 kfree(server->secmech.sdeschmacsha256); 796 kfree(server->secmech.sdeschmacsha256);
723 797 server->secmech.sdeschmacsha256 = NULL;
724 kfree(server->secmech.sdeschmacmd5); 798 kfree(server->secmech.sdeschmacmd5);
725 799 server->secmech.sdeschmacmd5 = NULL;
726 kfree(server->secmech.sdescmd5); 800 kfree(server->secmech.sdescmd5);
727} 801 server->secmech.sdescmd5 = NULL;
728
729int
730cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
731{
732 int rc;
733 unsigned int size;
734
735 server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
736 if (IS_ERR(server->secmech.hmacmd5)) {
737 cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
738 return PTR_ERR(server->secmech.hmacmd5);
739 }
740
741 server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
742 if (IS_ERR(server->secmech.md5)) {
743 cifs_dbg(VFS, "could not allocate crypto md5\n");
744 rc = PTR_ERR(server->secmech.md5);
745 goto crypto_allocate_md5_fail;
746 }
747
748 server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
749 if (IS_ERR(server->secmech.hmacsha256)) {
750 cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
751 rc = PTR_ERR(server->secmech.hmacsha256);
752 goto crypto_allocate_hmacsha256_fail;
753 }
754
755 server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
756 if (IS_ERR(server->secmech.cmacaes)) {
757 cifs_dbg(VFS, "could not allocate crypto cmac-aes");
758 rc = PTR_ERR(server->secmech.cmacaes);
759 goto crypto_allocate_cmacaes_fail;
760 }
761
762 size = sizeof(struct shash_desc) +
763 crypto_shash_descsize(server->secmech.hmacmd5);
764 server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
765 if (!server->secmech.sdeschmacmd5) {
766 rc = -ENOMEM;
767 goto crypto_allocate_hmacmd5_sdesc_fail;
768 }
769 server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
770 server->secmech.sdeschmacmd5->shash.flags = 0x0;
771
772 size = sizeof(struct shash_desc) +
773 crypto_shash_descsize(server->secmech.md5);
774 server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
775 if (!server->secmech.sdescmd5) {
776 rc = -ENOMEM;
777 goto crypto_allocate_md5_sdesc_fail;
778 }
779 server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
780 server->secmech.sdescmd5->shash.flags = 0x0;
781
782 size = sizeof(struct shash_desc) +
783 crypto_shash_descsize(server->secmech.hmacsha256);
784 server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
785 if (!server->secmech.sdeschmacsha256) {
786 rc = -ENOMEM;
787 goto crypto_allocate_hmacsha256_sdesc_fail;
788 }
789 server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
790 server->secmech.sdeschmacsha256->shash.flags = 0x0;
791
792 size = sizeof(struct shash_desc) +
793 crypto_shash_descsize(server->secmech.cmacaes);
794 server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
795 if (!server->secmech.sdesccmacaes) {
796 cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
797 rc = -ENOMEM;
798 goto crypto_allocate_cmacaes_sdesc_fail;
799 }
800 server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
801 server->secmech.sdesccmacaes->shash.flags = 0x0;
802
803 return 0;
804
805crypto_allocate_cmacaes_sdesc_fail:
806 kfree(server->secmech.sdeschmacsha256);
807
808crypto_allocate_hmacsha256_sdesc_fail:
809 kfree(server->secmech.sdescmd5);
810
811crypto_allocate_md5_sdesc_fail:
812 kfree(server->secmech.sdeschmacmd5);
813
814crypto_allocate_hmacmd5_sdesc_fail:
815 crypto_free_shash(server->secmech.cmacaes);
816
817crypto_allocate_cmacaes_fail:
818 crypto_free_shash(server->secmech.hmacsha256);
819
820crypto_allocate_hmacsha256_fail:
821 crypto_free_shash(server->secmech.md5);
822
823crypto_allocate_md5_fail:
824 crypto_free_shash(server->secmech.hmacmd5);
825
826 return rc;
827} 802}
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index e66b08882548..1fdc37041057 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -194,6 +194,7 @@ struct cifs_writedata;
194struct cifs_io_parms; 194struct cifs_io_parms;
195struct cifs_search_info; 195struct cifs_search_info;
196struct cifsInodeInfo; 196struct cifsInodeInfo;
197struct cifs_open_parms;
197 198
198struct smb_version_operations { 199struct smb_version_operations {
199 int (*send_cancel)(struct TCP_Server_Info *, void *, 200 int (*send_cancel)(struct TCP_Server_Info *, void *,
@@ -307,9 +308,8 @@ struct smb_version_operations {
307 const char *, const char *, 308 const char *, const char *,
308 struct cifs_sb_info *); 309 struct cifs_sb_info *);
309 /* open a file for non-posix mounts */ 310 /* open a file for non-posix mounts */
310 int (*open)(const unsigned int, struct cifs_tcon *, const char *, int, 311 int (*open)(const unsigned int, struct cifs_open_parms *,
311 int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *, 312 __u32 *, FILE_ALL_INFO *);
312 struct cifs_sb_info *);
313 /* set fid protocol-specific info */ 313 /* set fid protocol-specific info */
314 void (*set_fid)(struct cifsFileInfo *, struct cifs_fid *, __u32); 314 void (*set_fid)(struct cifsFileInfo *, struct cifs_fid *, __u32);
315 /* close a file */ 315 /* close a file */
@@ -912,6 +912,17 @@ struct cifs_search_info {
912 bool smallBuf:1; /* so we know which buf_release function to call */ 912 bool smallBuf:1; /* so we know which buf_release function to call */
913}; 913};
914 914
915struct cifs_open_parms {
916 struct cifs_tcon *tcon;
917 struct cifs_sb_info *cifs_sb;
918 int disposition;
919 int desired_access;
920 int create_options;
921 const char *path;
922 struct cifs_fid *fid;
923 bool reconnect:1;
924};
925
915struct cifs_fid { 926struct cifs_fid {
916 __u16 netfid; 927 __u16 netfid;
917#ifdef CONFIG_CIFS_SMB2 928#ifdef CONFIG_CIFS_SMB2
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index c8ff018fae68..f7e584d047e2 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -433,7 +433,6 @@ extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
433 const struct nls_table *); 433 const struct nls_table *);
434extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *); 434extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
435extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); 435extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
436extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *);
437extern void cifs_crypto_shash_release(struct TCP_Server_Info *); 436extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
438extern int calc_seckey(struct cifs_ses *); 437extern int calc_seckey(struct cifs_ses *);
439extern void generate_smb3signingkey(struct TCP_Server_Info *); 438extern void generate_smb3signingkey(struct TCP_Server_Info *);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index afcb8a1a33b7..fa68813396b5 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2108,12 +2108,6 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
2108 goto out_err; 2108 goto out_err;
2109 } 2109 }
2110 2110
2111 rc = cifs_crypto_shash_allocate(tcp_ses);
2112 if (rc) {
2113 cifs_dbg(VFS, "could not setup hash structures rc %d\n", rc);
2114 goto out_err;
2115 }
2116
2117 tcp_ses->ops = volume_info->ops; 2111 tcp_ses->ops = volume_info->ops;
2118 tcp_ses->vals = volume_info->vals; 2112 tcp_ses->vals = volume_info->vals;
2119 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); 2113 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 5175aebf6737..d62ce0d48141 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -204,6 +204,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
204 struct inode *newinode = NULL; 204 struct inode *newinode = NULL;
205 int disposition; 205 int disposition;
206 struct TCP_Server_Info *server = tcon->ses->server; 206 struct TCP_Server_Info *server = tcon->ses->server;
207 struct cifs_open_parms oparms;
207 208
208 *oplock = 0; 209 *oplock = 0;
209 if (tcon->ses->server->oplocks) 210 if (tcon->ses->server->oplocks)
@@ -319,9 +320,16 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
319 if (backup_cred(cifs_sb)) 320 if (backup_cred(cifs_sb))
320 create_options |= CREATE_OPEN_BACKUP_INTENT; 321 create_options |= CREATE_OPEN_BACKUP_INTENT;
321 322
322 rc = server->ops->open(xid, tcon, full_path, disposition, 323 oparms.tcon = tcon;
323 desired_access, create_options, fid, oplock, 324 oparms.cifs_sb = cifs_sb;
324 buf, cifs_sb); 325 oparms.desired_access = desired_access;
326 oparms.create_options = create_options;
327 oparms.disposition = disposition;
328 oparms.path = full_path;
329 oparms.fid = fid;
330 oparms.reconnect = false;
331
332 rc = server->ops->open(xid, &oparms, oplock, buf);
325 if (rc) { 333 if (rc) {
326 cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc); 334 cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
327 goto out; 335 goto out;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 91d8629e69a2..1e57f36ea1b2 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -183,6 +183,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
183 int create_options = CREATE_NOT_DIR; 183 int create_options = CREATE_NOT_DIR;
184 FILE_ALL_INFO *buf; 184 FILE_ALL_INFO *buf;
185 struct TCP_Server_Info *server = tcon->ses->server; 185 struct TCP_Server_Info *server = tcon->ses->server;
186 struct cifs_open_parms oparms;
186 187
187 if (!server->ops->open) 188 if (!server->ops->open)
188 return -ENOSYS; 189 return -ENOSYS;
@@ -224,9 +225,16 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
224 if (backup_cred(cifs_sb)) 225 if (backup_cred(cifs_sb))
225 create_options |= CREATE_OPEN_BACKUP_INTENT; 226 create_options |= CREATE_OPEN_BACKUP_INTENT;
226 227
227 rc = server->ops->open(xid, tcon, full_path, disposition, 228 oparms.tcon = tcon;
228 desired_access, create_options, fid, oplock, buf, 229 oparms.cifs_sb = cifs_sb;
229 cifs_sb); 230 oparms.desired_access = desired_access;
231 oparms.create_options = create_options;
232 oparms.disposition = disposition;
233 oparms.path = full_path;
234 oparms.fid = fid;
235 oparms.reconnect = false;
236
237 rc = server->ops->open(xid, &oparms, oplock, buf);
230 238
231 if (rc) 239 if (rc)
232 goto out; 240 goto out;
@@ -553,11 +561,10 @@ cifs_relock_file(struct cifsFileInfo *cfile)
553 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 561 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
554 int rc = 0; 562 int rc = 0;
555 563
556 /* we are going to update can_cache_brlcks here - need a write access */ 564 down_read(&cinode->lock_sem);
557 down_write(&cinode->lock_sem);
558 if (cinode->can_cache_brlcks) { 565 if (cinode->can_cache_brlcks) {
559 /* can cache locks - no need to push them */ 566 /* can cache locks - no need to relock */
560 up_write(&cinode->lock_sem); 567 up_read(&cinode->lock_sem);
561 return rc; 568 return rc;
562 } 569 }
563 570
@@ -568,7 +575,7 @@ cifs_relock_file(struct cifsFileInfo *cfile)
568 else 575 else
569 rc = tcon->ses->server->ops->push_mand_locks(cfile); 576 rc = tcon->ses->server->ops->push_mand_locks(cfile);
570 577
571 up_write(&cinode->lock_sem); 578 up_read(&cinode->lock_sem);
572 return rc; 579 return rc;
573} 580}
574 581
@@ -587,7 +594,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
587 int desired_access; 594 int desired_access;
588 int disposition = FILE_OPEN; 595 int disposition = FILE_OPEN;
589 int create_options = CREATE_NOT_DIR; 596 int create_options = CREATE_NOT_DIR;
590 struct cifs_fid fid; 597 struct cifs_open_parms oparms;
591 598
592 xid = get_xid(); 599 xid = get_xid();
593 mutex_lock(&cfile->fh_mutex); 600 mutex_lock(&cfile->fh_mutex);
@@ -637,7 +644,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
637 644
638 rc = cifs_posix_open(full_path, NULL, inode->i_sb, 645 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
639 cifs_sb->mnt_file_mode /* ignored */, 646 cifs_sb->mnt_file_mode /* ignored */,
640 oflags, &oplock, &fid.netfid, xid); 647 oflags, &oplock, &cfile->fid.netfid, xid);
641 if (rc == 0) { 648 if (rc == 0) {
642 cifs_dbg(FYI, "posix reopen succeeded\n"); 649 cifs_dbg(FYI, "posix reopen succeeded\n");
643 goto reopen_success; 650 goto reopen_success;
@@ -654,7 +661,16 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
654 create_options |= CREATE_OPEN_BACKUP_INTENT; 661 create_options |= CREATE_OPEN_BACKUP_INTENT;
655 662
656 if (server->ops->get_lease_key) 663 if (server->ops->get_lease_key)
657 server->ops->get_lease_key(inode, &fid); 664 server->ops->get_lease_key(inode, &cfile->fid);
665
666 oparms.tcon = tcon;
667 oparms.cifs_sb = cifs_sb;
668 oparms.desired_access = desired_access;
669 oparms.create_options = create_options;
670 oparms.disposition = disposition;
671 oparms.path = full_path;
672 oparms.fid = &cfile->fid;
673 oparms.reconnect = true;
658 674
659 /* 675 /*
660 * Can not refresh inode by passing in file_info buf to be returned by 676 * Can not refresh inode by passing in file_info buf to be returned by
@@ -663,9 +679,14 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
663 * version of file size can be stale. If we knew for sure that inode was 679 * version of file size can be stale. If we knew for sure that inode was
664 * not dirty locally we could do this. 680 * not dirty locally we could do this.
665 */ 681 */
666 rc = server->ops->open(xid, tcon, full_path, disposition, 682 rc = server->ops->open(xid, &oparms, &oplock, NULL);
667 desired_access, create_options, &fid, &oplock, 683 if (rc == -ENOENT && oparms.reconnect == false) {
668 NULL, cifs_sb); 684 /* durable handle timeout is expired - open the file again */
685 rc = server->ops->open(xid, &oparms, &oplock, NULL);
686 /* indicate that we need to relock the file */
687 oparms.reconnect = true;
688 }
689
669 if (rc) { 690 if (rc) {
670 mutex_unlock(&cfile->fh_mutex); 691 mutex_unlock(&cfile->fh_mutex);
671 cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc); 692 cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc);
@@ -696,8 +717,9 @@ reopen_success:
696 * to the server to get the new inode info. 717 * to the server to get the new inode info.
697 */ 718 */
698 719
699 server->ops->set_fid(cfile, &fid, oplock); 720 server->ops->set_fid(cfile, &cfile->fid, oplock);
700 cifs_relock_file(cfile); 721 if (oparms.reconnect)
722 cifs_relock_file(cfile);
701 723
702reopen_error_exit: 724reopen_error_exit:
703 kfree(full_path); 725 kfree(full_path);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 20efd81266c6..449b6cf09b09 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -558,6 +558,11 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
558 fattr->cf_mode &= ~(S_IWUGO); 558 fattr->cf_mode &= ~(S_IWUGO);
559 559
560 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); 560 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
561 if (fattr->cf_nlink < 1) {
562 cifs_dbg(1, "replacing bogus file nlink value %u\n",
563 fattr->cf_nlink);
564 fattr->cf_nlink = 1;
565 }
561 } 566 }
562 567
563 fattr->cf_uid = cifs_sb->mnt_uid; 568 fattr->cf_uid = cifs_sb->mnt_uid;
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index e813f04511d8..6457690731a2 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -674,20 +674,23 @@ cifs_mkdir_setinfo(struct inode *inode, const char *full_path,
674} 674}
675 675
676static int 676static int
677cifs_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, 677cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
678 int disposition, int desired_access, int create_options, 678 __u32 *oplock, FILE_ALL_INFO *buf)
679 struct cifs_fid *fid, __u32 *oplock, FILE_ALL_INFO *buf, 679{
680 struct cifs_sb_info *cifs_sb) 680 if (!(oparms->tcon->ses->capabilities & CAP_NT_SMBS))
681{ 681 return SMBLegacyOpen(xid, oparms->tcon, oparms->path,
682 if (!(tcon->ses->capabilities & CAP_NT_SMBS)) 682 oparms->disposition,
683 return SMBLegacyOpen(xid, tcon, path, disposition, 683 oparms->desired_access,
684 desired_access, create_options, 684 oparms->create_options,
685 &fid->netfid, oplock, buf, 685 &oparms->fid->netfid, oplock, buf,
686 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 686 oparms->cifs_sb->local_nls,
687 oparms->cifs_sb->mnt_cifs_flags
687 & CIFS_MOUNT_MAP_SPECIAL_CHR); 688 & CIFS_MOUNT_MAP_SPECIAL_CHR);
688 return CIFSSMBOpen(xid, tcon, path, disposition, desired_access, 689 return CIFSSMBOpen(xid, oparms->tcon, oparms->path,
689 create_options, &fid->netfid, oplock, buf, 690 oparms->disposition, oparms->desired_access,
690 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 691 oparms->create_options, &oparms->fid->netfid, oplock,
692 buf, oparms->cifs_sb->local_nls,
693 oparms->cifs_sb->mnt_cifs_flags &
691 CIFS_MOUNT_MAP_SPECIAL_CHR); 694 CIFS_MOUNT_MAP_SPECIAL_CHR);
692} 695}
693 696
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
index 5da1b55a2258..04a81a4142c3 100644
--- a/fs/cifs/smb2file.c
+++ b/fs/cifs/smb2file.c
@@ -40,7 +40,8 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
40 oplock &= 0xFF; 40 oplock &= 0xFF;
41 if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE) 41 if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
42 return; 42 return;
43 if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) { 43 if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
44 oplock == SMB2_OPLOCK_LEVEL_BATCH) {
44 cinode->clientCanCacheAll = true; 45 cinode->clientCanCacheAll = true;
45 cinode->clientCanCacheRead = true; 46 cinode->clientCanCacheRead = true;
46 cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n", 47 cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
@@ -57,17 +58,16 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
57} 58}
58 59
59int 60int
60smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, 61smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
61 int disposition, int desired_access, int create_options, 62 __u32 *oplock, FILE_ALL_INFO *buf)
62 struct cifs_fid *fid, __u32 *oplock, FILE_ALL_INFO *buf,
63 struct cifs_sb_info *cifs_sb)
64{ 63{
65 int rc; 64 int rc;
66 __le16 *smb2_path; 65 __le16 *smb2_path;
67 struct smb2_file_all_info *smb2_data = NULL; 66 struct smb2_file_all_info *smb2_data = NULL;
68 __u8 smb2_oplock[17]; 67 __u8 smb2_oplock[17];
68 struct cifs_fid *fid = oparms->fid;
69 69
70 smb2_path = cifs_convert_path_to_utf16(path, cifs_sb); 70 smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb);
71 if (smb2_path == NULL) { 71 if (smb2_path == NULL) {
72 rc = -ENOMEM; 72 rc = -ENOMEM;
73 goto out; 73 goto out;
@@ -80,21 +80,19 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path,
80 goto out; 80 goto out;
81 } 81 }
82 82
83 desired_access |= FILE_READ_ATTRIBUTES; 83 oparms->desired_access |= FILE_READ_ATTRIBUTES;
84 *smb2_oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE; 84 *smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH;
85 85
86 if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) 86 if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
87 memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE); 87 memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);
88 88
89 rc = SMB2_open(xid, tcon, smb2_path, &fid->persistent_fid, 89 rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data);
90 &fid->volatile_fid, desired_access, disposition,
91 0, 0, smb2_oplock, smb2_data);
92 if (rc) 90 if (rc)
93 goto out; 91 goto out;
94 92
95 if (buf) { 93 if (buf) {
96 /* open response does not have IndexNumber field - get it */ 94 /* open response does not have IndexNumber field - get it */
97 rc = SMB2_get_srv_num(xid, tcon, fid->persistent_fid, 95 rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid,
98 fid->volatile_fid, 96 fid->volatile_fid,
99 &smb2_data->IndexNumber); 97 &smb2_data->IndexNumber);
100 if (rc) { 98 if (rc) {
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index fff6dfba6204..c6ec1633309a 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -41,21 +41,26 @@ static int
41smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, 41smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
42 struct cifs_sb_info *cifs_sb, const char *full_path, 42 struct cifs_sb_info *cifs_sb, const char *full_path,
43 __u32 desired_access, __u32 create_disposition, 43 __u32 desired_access, __u32 create_disposition,
44 __u32 file_attributes, __u32 create_options, 44 __u32 create_options, void *data, int command)
45 void *data, int command)
46{ 45{
47 int rc, tmprc = 0; 46 int rc, tmprc = 0;
48 u64 persistent_fid, volatile_fid;
49 __le16 *utf16_path; 47 __le16 *utf16_path;
50 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 48 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
49 struct cifs_open_parms oparms;
50 struct cifs_fid fid;
51 51
52 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); 52 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
53 if (!utf16_path) 53 if (!utf16_path)
54 return -ENOMEM; 54 return -ENOMEM;
55 55
56 rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, 56 oparms.tcon = tcon;
57 desired_access, create_disposition, file_attributes, 57 oparms.desired_access = desired_access;
58 create_options, &oplock, NULL); 58 oparms.disposition = create_disposition;
59 oparms.create_options = create_options;
60 oparms.fid = &fid;
61 oparms.reconnect = false;
62
63 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL);
59 if (rc) { 64 if (rc) {
60 kfree(utf16_path); 65 kfree(utf16_path);
61 return rc; 66 return rc;
@@ -65,8 +70,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
65 case SMB2_OP_DELETE: 70 case SMB2_OP_DELETE:
66 break; 71 break;
67 case SMB2_OP_QUERY_INFO: 72 case SMB2_OP_QUERY_INFO:
68 tmprc = SMB2_query_info(xid, tcon, persistent_fid, 73 tmprc = SMB2_query_info(xid, tcon, fid.persistent_fid,
69 volatile_fid, 74 fid.volatile_fid,
70 (struct smb2_file_all_info *)data); 75 (struct smb2_file_all_info *)data);
71 break; 76 break;
72 case SMB2_OP_MKDIR: 77 case SMB2_OP_MKDIR:
@@ -76,19 +81,21 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
76 */ 81 */
77 break; 82 break;
78 case SMB2_OP_RENAME: 83 case SMB2_OP_RENAME:
79 tmprc = SMB2_rename(xid, tcon, persistent_fid, volatile_fid, 84 tmprc = SMB2_rename(xid, tcon, fid.persistent_fid,
80 (__le16 *)data); 85 fid.volatile_fid, (__le16 *)data);
81 break; 86 break;
82 case SMB2_OP_HARDLINK: 87 case SMB2_OP_HARDLINK:
83 tmprc = SMB2_set_hardlink(xid, tcon, persistent_fid, 88 tmprc = SMB2_set_hardlink(xid, tcon, fid.persistent_fid,
84 volatile_fid, (__le16 *)data); 89 fid.volatile_fid, (__le16 *)data);
85 break; 90 break;
86 case SMB2_OP_SET_EOF: 91 case SMB2_OP_SET_EOF:
87 tmprc = SMB2_set_eof(xid, tcon, persistent_fid, volatile_fid, 92 tmprc = SMB2_set_eof(xid, tcon, fid.persistent_fid,
88 current->tgid, (__le64 *)data); 93 fid.volatile_fid, current->tgid,
94 (__le64 *)data);
89 break; 95 break;
90 case SMB2_OP_SET_INFO: 96 case SMB2_OP_SET_INFO:
91 tmprc = SMB2_set_info(xid, tcon, persistent_fid, volatile_fid, 97 tmprc = SMB2_set_info(xid, tcon, fid.persistent_fid,
98 fid.volatile_fid,
92 (FILE_BASIC_INFO *)data); 99 (FILE_BASIC_INFO *)data);
93 break; 100 break;
94 default: 101 default:
@@ -96,7 +103,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
96 break; 103 break;
97 } 104 }
98 105
99 rc = SMB2_close(xid, tcon, persistent_fid, volatile_fid); 106 rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
100 if (tmprc) 107 if (tmprc)
101 rc = tmprc; 108 rc = tmprc;
102 kfree(utf16_path); 109 kfree(utf16_path);
@@ -129,8 +136,8 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
129 return -ENOMEM; 136 return -ENOMEM;
130 137
131 rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path, 138 rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path,
132 FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, 139 FILE_READ_ATTRIBUTES, FILE_OPEN, 0, smb2_data,
133 smb2_data, SMB2_OP_QUERY_INFO); 140 SMB2_OP_QUERY_INFO);
134 if (rc) 141 if (rc)
135 goto out; 142 goto out;
136 143
@@ -145,7 +152,7 @@ smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
145 struct cifs_sb_info *cifs_sb) 152 struct cifs_sb_info *cifs_sb)
146{ 153{
147 return smb2_open_op_close(xid, tcon, cifs_sb, name, 154 return smb2_open_op_close(xid, tcon, cifs_sb, name,
148 FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0, 155 FILE_WRITE_ATTRIBUTES, FILE_CREATE,
149 CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR); 156 CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR);
150} 157}
151 158
@@ -164,7 +171,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
164 dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; 171 dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
165 data.Attributes = cpu_to_le32(dosattrs); 172 data.Attributes = cpu_to_le32(dosattrs);
166 tmprc = smb2_open_op_close(xid, tcon, cifs_sb, name, 173 tmprc = smb2_open_op_close(xid, tcon, cifs_sb, name,
167 FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0, 174 FILE_WRITE_ATTRIBUTES, FILE_CREATE,
168 CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO); 175 CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO);
169 if (tmprc == 0) 176 if (tmprc == 0)
170 cifs_i->cifsAttrs = dosattrs; 177 cifs_i->cifsAttrs = dosattrs;
@@ -175,7 +182,7 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
175 struct cifs_sb_info *cifs_sb) 182 struct cifs_sb_info *cifs_sb)
176{ 183{
177 return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, 184 return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
178 0, CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE, 185 CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE,
179 NULL, SMB2_OP_DELETE); 186 NULL, SMB2_OP_DELETE);
180} 187}
181 188
@@ -184,7 +191,7 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
184 struct cifs_sb_info *cifs_sb) 191 struct cifs_sb_info *cifs_sb)
185{ 192{
186 return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, 193 return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
187 0, CREATE_DELETE_ON_CLOSE, NULL, 194 CREATE_DELETE_ON_CLOSE, NULL,
188 SMB2_OP_DELETE); 195 SMB2_OP_DELETE);
189} 196}
190 197
@@ -203,7 +210,7 @@ smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
203 } 210 }
204 211
205 rc = smb2_open_op_close(xid, tcon, cifs_sb, from_name, access, 212 rc = smb2_open_op_close(xid, tcon, cifs_sb, from_name, access,
206 FILE_OPEN, 0, 0, smb2_to_name, command); 213 FILE_OPEN, 0, smb2_to_name, command);
207smb2_rename_path: 214smb2_rename_path:
208 kfree(smb2_to_name); 215 kfree(smb2_to_name);
209 return rc; 216 return rc;
@@ -234,7 +241,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
234{ 241{
235 __le64 eof = cpu_to_le64(size); 242 __le64 eof = cpu_to_le64(size);
236 return smb2_open_op_close(xid, tcon, cifs_sb, full_path, 243 return smb2_open_op_close(xid, tcon, cifs_sb, full_path,
237 FILE_WRITE_DATA, FILE_OPEN, 0, 0, &eof, 244 FILE_WRITE_DATA, FILE_OPEN, 0, &eof,
238 SMB2_OP_SET_EOF); 245 SMB2_OP_SET_EOF);
239} 246}
240 247
@@ -250,7 +257,7 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
250 if (IS_ERR(tlink)) 257 if (IS_ERR(tlink))
251 return PTR_ERR(tlink); 258 return PTR_ERR(tlink);
252 rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path, 259 rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path,
253 FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, 0, buf, 260 FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf,
254 SMB2_OP_SET_INFO); 261 SMB2_OP_SET_INFO);
255 cifs_put_tlink(tlink); 262 cifs_put_tlink(tlink);
256 return rc; 263 return rc;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 6d15cab95b99..f259e6cc8357 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -213,22 +213,29 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
213 struct cifs_sb_info *cifs_sb, const char *full_path) 213 struct cifs_sb_info *cifs_sb, const char *full_path)
214{ 214{
215 int rc; 215 int rc;
216 __u64 persistent_fid, volatile_fid;
217 __le16 *utf16_path; 216 __le16 *utf16_path;
218 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 217 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
218 struct cifs_open_parms oparms;
219 struct cifs_fid fid;
219 220
220 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); 221 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
221 if (!utf16_path) 222 if (!utf16_path)
222 return -ENOMEM; 223 return -ENOMEM;
223 224
224 rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, 225 oparms.tcon = tcon;
225 FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock, NULL); 226 oparms.desired_access = FILE_READ_ATTRIBUTES;
227 oparms.disposition = FILE_OPEN;
228 oparms.create_options = 0;
229 oparms.fid = &fid;
230 oparms.reconnect = false;
231
232 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL);
226 if (rc) { 233 if (rc) {
227 kfree(utf16_path); 234 kfree(utf16_path);
228 return rc; 235 return rc;
229 } 236 }
230 237
231 rc = SMB2_close(xid, tcon, persistent_fid, volatile_fid); 238 rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
232 kfree(utf16_path); 239 kfree(utf16_path);
233 return rc; 240 return rc;
234} 241}
@@ -443,15 +450,20 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
443 __le16 *utf16_path; 450 __le16 *utf16_path;
444 int rc; 451 int rc;
445 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 452 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
446 __u64 persistent_fid, volatile_fid; 453 struct cifs_open_parms oparms;
447 454
448 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); 455 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
449 if (!utf16_path) 456 if (!utf16_path)
450 return -ENOMEM; 457 return -ENOMEM;
451 458
452 rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, 459 oparms.tcon = tcon;
453 FILE_READ_ATTRIBUTES | FILE_READ_DATA, FILE_OPEN, 0, 0, 460 oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA;
454 &oplock, NULL); 461 oparms.disposition = FILE_OPEN;
462 oparms.create_options = 0;
463 oparms.fid = fid;
464 oparms.reconnect = false;
465
466 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL);
455 kfree(utf16_path); 467 kfree(utf16_path);
456 if (rc) { 468 if (rc) {
457 cifs_dbg(VFS, "open dir failed\n"); 469 cifs_dbg(VFS, "open dir failed\n");
@@ -460,14 +472,12 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
460 472
461 srch_inf->entries_in_buffer = 0; 473 srch_inf->entries_in_buffer = 0;
462 srch_inf->index_of_last_entry = 0; 474 srch_inf->index_of_last_entry = 0;
463 fid->persistent_fid = persistent_fid;
464 fid->volatile_fid = volatile_fid;
465 475
466 rc = SMB2_query_directory(xid, tcon, persistent_fid, volatile_fid, 0, 476 rc = SMB2_query_directory(xid, tcon, fid->persistent_fid,
467 srch_inf); 477 fid->volatile_fid, 0, srch_inf);
468 if (rc) { 478 if (rc) {
469 cifs_dbg(VFS, "query directory failed\n"); 479 cifs_dbg(VFS, "query directory failed\n");
470 SMB2_close(xid, tcon, persistent_fid, volatile_fid); 480 SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
471 } 481 }
472 return rc; 482 return rc;
473} 483}
@@ -528,17 +538,25 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
528 struct kstatfs *buf) 538 struct kstatfs *buf)
529{ 539{
530 int rc; 540 int rc;
531 u64 persistent_fid, volatile_fid;
532 __le16 srch_path = 0; /* Null - open root of share */ 541 __le16 srch_path = 0; /* Null - open root of share */
533 u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 542 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
543 struct cifs_open_parms oparms;
544 struct cifs_fid fid;
545
546 oparms.tcon = tcon;
547 oparms.desired_access = FILE_READ_ATTRIBUTES;
548 oparms.disposition = FILE_OPEN;
549 oparms.create_options = 0;
550 oparms.fid = &fid;
551 oparms.reconnect = false;
534 552
535 rc = SMB2_open(xid, tcon, &srch_path, &persistent_fid, &volatile_fid, 553 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL);
536 FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock, NULL);
537 if (rc) 554 if (rc)
538 return rc; 555 return rc;
539 buf->f_type = SMB2_MAGIC_NUMBER; 556 buf->f_type = SMB2_MAGIC_NUMBER;
540 rc = SMB2_QFS_info(xid, tcon, persistent_fid, volatile_fid, buf); 557 rc = SMB2_QFS_info(xid, tcon, fid.persistent_fid, fid.volatile_fid,
541 SMB2_close(xid, tcon, persistent_fid, volatile_fid); 558 buf);
559 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
542 return rc; 560 return rc;
543} 561}
544 562
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 2b312e4eeaa6..abc9c2809b51 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -847,29 +847,76 @@ create_lease_buf(u8 *lease_key, u8 oplock)
847 return buf; 847 return buf;
848} 848}
849 849
850static struct create_durable *
851create_durable_buf(void)
852{
853 struct create_durable *buf;
854
855 buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL);
856 if (!buf)
857 return NULL;
858
859 buf->ccontext.DataOffset = cpu_to_le16(offsetof
860 (struct create_durable, Data));
861 buf->ccontext.DataLength = cpu_to_le32(16);
862 buf->ccontext.NameOffset = cpu_to_le16(offsetof
863 (struct create_durable, Name));
864 buf->ccontext.NameLength = cpu_to_le16(4);
865 buf->Name[0] = 'D';
866 buf->Name[1] = 'H';
867 buf->Name[2] = 'n';
868 buf->Name[3] = 'Q';
869 return buf;
870}
871
872static struct create_durable *
873create_reconnect_durable_buf(struct cifs_fid *fid)
874{
875 struct create_durable *buf;
876
877 buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL);
878 if (!buf)
879 return NULL;
880
881 buf->ccontext.DataOffset = cpu_to_le16(offsetof
882 (struct create_durable, Data));
883 buf->ccontext.DataLength = cpu_to_le32(16);
884 buf->ccontext.NameOffset = cpu_to_le16(offsetof
885 (struct create_durable, Name));
886 buf->ccontext.NameLength = cpu_to_le16(4);
887 buf->Data.Fid.PersistentFileId = fid->persistent_fid;
888 buf->Data.Fid.VolatileFileId = fid->volatile_fid;
889 buf->Name[0] = 'D';
890 buf->Name[1] = 'H';
891 buf->Name[2] = 'n';
892 buf->Name[3] = 'C';
893 return buf;
894}
895
850static __u8 896static __u8
851parse_lease_state(struct smb2_create_rsp *rsp) 897parse_lease_state(struct smb2_create_rsp *rsp)
852{ 898{
853 char *data_offset; 899 char *data_offset;
854 struct create_lease *lc; 900 struct create_lease *lc;
855 bool found = false; 901 bool found = false;
902 unsigned int next = 0;
903 char *name;
856 904
857 data_offset = (char *)rsp; 905 data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
858 data_offset += 4 + le32_to_cpu(rsp->CreateContextsOffset);
859 lc = (struct create_lease *)data_offset; 906 lc = (struct create_lease *)data_offset;
860 do { 907 do {
861 char *name = le16_to_cpu(lc->ccontext.NameOffset) + (char *)lc; 908 lc = (struct create_lease *)((char *)lc + next);
909 name = le16_to_cpu(lc->ccontext.NameOffset) + (char *)lc;
862 if (le16_to_cpu(lc->ccontext.NameLength) != 4 || 910 if (le16_to_cpu(lc->ccontext.NameLength) != 4 ||
863 strncmp(name, "RqLs", 4)) { 911 strncmp(name, "RqLs", 4)) {
864 lc = (struct create_lease *)((char *)lc 912 next = le32_to_cpu(lc->ccontext.Next);
865 + le32_to_cpu(lc->ccontext.Next));
866 continue; 913 continue;
867 } 914 }
868 if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS) 915 if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
869 return SMB2_OPLOCK_LEVEL_NOCHANGE; 916 return SMB2_OPLOCK_LEVEL_NOCHANGE;
870 found = true; 917 found = true;
871 break; 918 break;
872 } while (le32_to_cpu(lc->ccontext.Next) != 0); 919 } while (next != 0);
873 920
874 if (!found) 921 if (!found)
875 return 0; 922 return 0;
@@ -877,23 +924,74 @@ parse_lease_state(struct smb2_create_rsp *rsp)
877 return smb2_map_lease_to_oplock(lc->lcontext.LeaseState); 924 return smb2_map_lease_to_oplock(lc->lcontext.LeaseState);
878} 925}
879 926
927static int
928add_lease_context(struct kvec *iov, unsigned int *num_iovec, __u8 *oplock)
929{
930 struct smb2_create_req *req = iov[0].iov_base;
931 unsigned int num = *num_iovec;
932
933 iov[num].iov_base = create_lease_buf(oplock+1, *oplock);
934 if (iov[num].iov_base == NULL)
935 return -ENOMEM;
936 iov[num].iov_len = sizeof(struct create_lease);
937 req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
938 if (!req->CreateContextsOffset)
939 req->CreateContextsOffset = cpu_to_le32(
940 sizeof(struct smb2_create_req) - 4 +
941 iov[num - 1].iov_len);
942 req->CreateContextsLength = cpu_to_le32(
943 le32_to_cpu(req->CreateContextsLength) +
944 sizeof(struct create_lease));
945 inc_rfc1001_len(&req->hdr, sizeof(struct create_lease));
946 *num_iovec = num + 1;
947 return 0;
948}
949
950static int
951add_durable_context(struct kvec *iov, unsigned int *num_iovec,
952 struct cifs_open_parms *oparms)
953{
954 struct smb2_create_req *req = iov[0].iov_base;
955 unsigned int num = *num_iovec;
956
957 if (oparms->reconnect) {
958 iov[num].iov_base = create_reconnect_durable_buf(oparms->fid);
959 /* indicate that we don't need to relock the file */
960 oparms->reconnect = false;
961 } else
962 iov[num].iov_base = create_durable_buf();
963 if (iov[num].iov_base == NULL)
964 return -ENOMEM;
965 iov[num].iov_len = sizeof(struct create_durable);
966 if (!req->CreateContextsOffset)
967 req->CreateContextsOffset =
968 cpu_to_le32(sizeof(struct smb2_create_req) - 4 +
969 iov[1].iov_len);
970 req->CreateContextsLength =
971 cpu_to_le32(le32_to_cpu(req->CreateContextsLength) +
972 sizeof(struct create_durable));
973 inc_rfc1001_len(&req->hdr, sizeof(struct create_durable));
974 *num_iovec = num + 1;
975 return 0;
976}
977
880int 978int
881SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, 979SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
882 u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access,
883 __u32 create_disposition, __u32 file_attributes, __u32 create_options,
884 __u8 *oplock, struct smb2_file_all_info *buf) 980 __u8 *oplock, struct smb2_file_all_info *buf)
885{ 981{
886 struct smb2_create_req *req; 982 struct smb2_create_req *req;
887 struct smb2_create_rsp *rsp; 983 struct smb2_create_rsp *rsp;
888 struct TCP_Server_Info *server; 984 struct TCP_Server_Info *server;
985 struct cifs_tcon *tcon = oparms->tcon;
889 struct cifs_ses *ses = tcon->ses; 986 struct cifs_ses *ses = tcon->ses;
890 struct kvec iov[3]; 987 struct kvec iov[4];
891 int resp_buftype; 988 int resp_buftype;
892 int uni_path_len; 989 int uni_path_len;
893 __le16 *copy_path = NULL; 990 __le16 *copy_path = NULL;
894 int copy_size; 991 int copy_size;
895 int rc = 0; 992 int rc = 0;
896 int num_iovecs = 2; 993 unsigned int num_iovecs = 2;
994 __u32 file_attributes = 0;
897 995
898 cifs_dbg(FYI, "create/open\n"); 996 cifs_dbg(FYI, "create/open\n");
899 997
@@ -906,55 +1004,47 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path,
906 if (rc) 1004 if (rc)
907 return rc; 1005 return rc;
908 1006
1007 if (oparms->create_options & CREATE_OPTION_READONLY)
1008 file_attributes |= ATTR_READONLY;
1009
909 req->ImpersonationLevel = IL_IMPERSONATION; 1010 req->ImpersonationLevel = IL_IMPERSONATION;
910 req->DesiredAccess = cpu_to_le32(desired_access); 1011 req->DesiredAccess = cpu_to_le32(oparms->desired_access);
911 /* File attributes ignored on open (used in create though) */ 1012 /* File attributes ignored on open (used in create though) */
912 req->FileAttributes = cpu_to_le32(file_attributes); 1013 req->FileAttributes = cpu_to_le32(file_attributes);
913 req->ShareAccess = FILE_SHARE_ALL_LE; 1014 req->ShareAccess = FILE_SHARE_ALL_LE;
914 req->CreateDisposition = cpu_to_le32(create_disposition); 1015 req->CreateDisposition = cpu_to_le32(oparms->disposition);
915 req->CreateOptions = cpu_to_le32(create_options); 1016 req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK);
916 uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; 1017 uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
917 req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) 1018 /* do not count rfc1001 len field */
918 - 8 /* pad */ - 4 /* do not count rfc1001 len field */); 1019 req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4);
919 1020
920 iov[0].iov_base = (char *)req; 1021 iov[0].iov_base = (char *)req;
921 /* 4 for rfc1002 length field */ 1022 /* 4 for rfc1002 length field */
922 iov[0].iov_len = get_rfc1002_length(req) + 4; 1023 iov[0].iov_len = get_rfc1002_length(req) + 4;
923 1024
924 /* MUST set path len (NameLength) to 0 opening root of share */ 1025 /* MUST set path len (NameLength) to 0 opening root of share */
925 if (uni_path_len >= 4) { 1026 req->NameLength = cpu_to_le16(uni_path_len - 2);
926 req->NameLength = cpu_to_le16(uni_path_len - 2); 1027 /* -1 since last byte is buf[0] which is sent below (path) */
927 /* -1 since last byte is buf[0] which is sent below (path) */ 1028 iov[0].iov_len--;
928 iov[0].iov_len--; 1029 if (uni_path_len % 8 != 0) {
929 if (uni_path_len % 8 != 0) { 1030 copy_size = uni_path_len / 8 * 8;
930 copy_size = uni_path_len / 8 * 8; 1031 if (copy_size < uni_path_len)
931 if (copy_size < uni_path_len) 1032 copy_size += 8;
932 copy_size += 8; 1033
933 1034 copy_path = kzalloc(copy_size, GFP_KERNEL);
934 copy_path = kzalloc(copy_size, GFP_KERNEL); 1035 if (!copy_path)
935 if (!copy_path) 1036 return -ENOMEM;
936 return -ENOMEM; 1037 memcpy((char *)copy_path, (const char *)path,
937 memcpy((char *)copy_path, (const char *)path, 1038 uni_path_len);
938 uni_path_len); 1039 uni_path_len = copy_size;
939 uni_path_len = copy_size; 1040 path = copy_path;
940 path = copy_path;
941 }
942
943 iov[1].iov_len = uni_path_len;
944 iov[1].iov_base = path;
945 /*
946 * -1 since last byte is buf[0] which was counted in
947 * smb2_buf_len.
948 */
949 inc_rfc1001_len(req, uni_path_len - 1);
950 } else {
951 iov[0].iov_len += 7;
952 req->hdr.smb2_buf_length = cpu_to_be32(be32_to_cpu(
953 req->hdr.smb2_buf_length) + 8 - 1);
954 num_iovecs = 1;
955 req->NameLength = 0;
956 } 1041 }
957 1042
1043 iov[1].iov_len = uni_path_len;
1044 iov[1].iov_base = path;
1045 /* -1 since last byte is buf[0] which was counted in smb2_buf_len */
1046 inc_rfc1001_len(req, uni_path_len - 1);
1047
958 if (!server->oplocks) 1048 if (!server->oplocks)
959 *oplock = SMB2_OPLOCK_LEVEL_NONE; 1049 *oplock = SMB2_OPLOCK_LEVEL_NONE;
960 1050
@@ -962,21 +1052,29 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path,
962 *oplock == SMB2_OPLOCK_LEVEL_NONE) 1052 *oplock == SMB2_OPLOCK_LEVEL_NONE)
963 req->RequestedOplockLevel = *oplock; 1053 req->RequestedOplockLevel = *oplock;
964 else { 1054 else {
965 iov[num_iovecs].iov_base = create_lease_buf(oplock+1, *oplock); 1055 rc = add_lease_context(iov, &num_iovecs, oplock);
966 if (iov[num_iovecs].iov_base == NULL) { 1056 if (rc) {
967 cifs_small_buf_release(req); 1057 cifs_small_buf_release(req);
968 kfree(copy_path); 1058 kfree(copy_path);
969 return -ENOMEM; 1059 return rc;
1060 }
1061 }
1062
1063 if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) {
1064 /* need to set Next field of lease context if we request it */
1065 if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) {
1066 struct create_context *ccontext =
1067 (struct create_context *)iov[num_iovecs-1].iov_base;
1068 ccontext->Next =
1069 cpu_to_le32(sizeof(struct create_lease));
1070 }
1071 rc = add_durable_context(iov, &num_iovecs, oparms);
1072 if (rc) {
1073 cifs_small_buf_release(req);
1074 kfree(copy_path);
1075 kfree(iov[num_iovecs-1].iov_base);
1076 return rc;
970 } 1077 }
971 iov[num_iovecs].iov_len = sizeof(struct create_lease);
972 req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
973 req->CreateContextsOffset = cpu_to_le32(
974 sizeof(struct smb2_create_req) - 4 - 8 +
975 iov[num_iovecs-1].iov_len);
976 req->CreateContextsLength = cpu_to_le32(
977 sizeof(struct create_lease));
978 inc_rfc1001_len(&req->hdr, sizeof(struct create_lease));
979 num_iovecs++;
980 } 1078 }
981 1079
982 rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); 1080 rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0);
@@ -987,8 +1085,8 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path,
987 goto creat_exit; 1085 goto creat_exit;
988 } 1086 }
989 1087
990 *persistent_fid = rsp->PersistentFileId; 1088 oparms->fid->persistent_fid = rsp->PersistentFileId;
991 *volatile_fid = rsp->VolatileFileId; 1089 oparms->fid->volatile_fid = rsp->VolatileFileId;
992 1090
993 if (buf) { 1091 if (buf) {
994 memcpy(buf, &rsp->CreationTime, 32); 1092 memcpy(buf, &rsp->CreationTime, 32);
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index f31043b26bd3..36b0d37ea69b 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -428,7 +428,7 @@ struct smb2_create_req {
428 __le16 NameLength; 428 __le16 NameLength;
429 __le32 CreateContextsOffset; 429 __le32 CreateContextsOffset;
430 __le32 CreateContextsLength; 430 __le32 CreateContextsLength;
431 __u8 Buffer[8]; 431 __u8 Buffer[0];
432} __packed; 432} __packed;
433 433
434struct smb2_create_rsp { 434struct smb2_create_rsp {
@@ -485,6 +485,18 @@ struct create_lease {
485 struct lease_context lcontext; 485 struct lease_context lcontext;
486} __packed; 486} __packed;
487 487
488struct create_durable {
489 struct create_context ccontext;
490 __u8 Name[8];
491 union {
492 __u8 Reserved[16];
493 struct {
494 __u64 PersistentFileId;
495 __u64 VolatileFileId;
496 } Fid;
497 } Data;
498} __packed;
499
488/* this goes in the ioctl buffer when doing a copychunk request */ 500/* this goes in the ioctl buffer when doing a copychunk request */
489struct copychunk_ioctl { 501struct copychunk_ioctl {
490 char SourceKey[24]; 502 char SourceKey[24];
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index d4e1eb807457..1a5ecbed40ed 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -84,11 +84,9 @@ extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
84 const char *from_name, const char *to_name, 84 const char *from_name, const char *to_name,
85 struct cifs_sb_info *cifs_sb); 85 struct cifs_sb_info *cifs_sb);
86 86
87extern int smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, 87extern int smb2_open_file(const unsigned int xid,
88 const char *full_path, int disposition, 88 struct cifs_open_parms *oparms,
89 int desired_access, int create_options, 89 __u32 *oplock, FILE_ALL_INFO *buf);
90 struct cifs_fid *fid, __u32 *oplock,
91 FILE_ALL_INFO *buf, struct cifs_sb_info *cifs_sb);
92extern void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock); 90extern void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock);
93extern int smb2_unlock_range(struct cifsFileInfo *cfile, 91extern int smb2_unlock_range(struct cifsFileInfo *cfile,
94 struct file_lock *flock, const unsigned int xid); 92 struct file_lock *flock, const unsigned int xid);
@@ -106,11 +104,9 @@ extern int SMB2_tcon(const unsigned int xid, struct cifs_ses *ses,
106 const char *tree, struct cifs_tcon *tcon, 104 const char *tree, struct cifs_tcon *tcon,
107 const struct nls_table *); 105 const struct nls_table *);
108extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon); 106extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
109extern int SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, 107extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
110 __le16 *path, u64 *persistent_fid, u64 *volatile_fid, 108 __le16 *path, __u8 *oplock,
111 __u32 desired_access, __u32 create_disposition, 109 struct smb2_file_all_info *buf);
112 __u32 file_attributes, __u32 create_options,
113 __u8 *oplock, struct smb2_file_all_info *buf);
114extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, 110extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
115 u64 persistent_fid, u64 volatile_fid, u32 opcode, 111 u64 persistent_fid, u64 volatile_fid, u32 opcode,
116 bool is_fsctl, char *in_data, u32 indatalen, 112 bool is_fsctl, char *in_data, u32 indatalen,
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 09b4fbaadeb6..301b191270b9 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -39,6 +39,77 @@
39#include "smb2status.h" 39#include "smb2status.h"
40#include "smb2glob.h" 40#include "smb2glob.h"
41 41
42static int
43smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
44{
45 unsigned int size;
46
47 if (server->secmech.sdeschmacsha256 != NULL)
48 return 0; /* already allocated */
49
50 server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
51 if (IS_ERR(server->secmech.hmacsha256)) {
52 cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
53 return PTR_ERR(server->secmech.hmacsha256);
54 }
55
56 size = sizeof(struct shash_desc) +
57 crypto_shash_descsize(server->secmech.hmacsha256);
58 server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
59 if (!server->secmech.sdeschmacsha256) {
60 crypto_free_shash(server->secmech.hmacsha256);
61 server->secmech.hmacsha256 = NULL;
62 return -ENOMEM;
63 }
64 server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
65 server->secmech.sdeschmacsha256->shash.flags = 0x0;
66
67 return 0;
68}
69
70static int
71smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
72{
73 unsigned int size;
74 int rc;
75
76 if (server->secmech.sdesccmacaes != NULL)
77 return 0; /* already allocated */
78
79 rc = smb2_crypto_shash_allocate(server);
80 if (rc)
81 return rc;
82
83 server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
84 if (IS_ERR(server->secmech.cmacaes)) {
85 cifs_dbg(VFS, "could not allocate crypto cmac-aes");
86 kfree(server->secmech.sdeschmacsha256);
87 server->secmech.sdeschmacsha256 = NULL;
88 crypto_free_shash(server->secmech.hmacsha256);
89 server->secmech.hmacsha256 = NULL;
90 return PTR_ERR(server->secmech.cmacaes);
91 }
92
93 size = sizeof(struct shash_desc) +
94 crypto_shash_descsize(server->secmech.cmacaes);
95 server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
96 if (!server->secmech.sdesccmacaes) {
97 cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
98 kfree(server->secmech.sdeschmacsha256);
99 server->secmech.sdeschmacsha256 = NULL;
100 crypto_free_shash(server->secmech.hmacsha256);
101 crypto_free_shash(server->secmech.cmacaes);
102 server->secmech.hmacsha256 = NULL;
103 server->secmech.cmacaes = NULL;
104 return -ENOMEM;
105 }
106 server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
107 server->secmech.sdesccmacaes->shash.flags = 0x0;
108
109 return 0;
110}
111
112
42int 113int
43smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) 114smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
44{ 115{
@@ -52,6 +123,12 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
52 memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); 123 memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
53 memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); 124 memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE);
54 125
126 rc = smb2_crypto_shash_allocate(server);
127 if (rc) {
128 cifs_dbg(VFS, "%s: shah256 alloc failed\n", __func__);
129 return rc;
130 }
131
55 rc = crypto_shash_setkey(server->secmech.hmacsha256, 132 rc = crypto_shash_setkey(server->secmech.hmacsha256,
56 server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE); 133 server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
57 if (rc) { 134 if (rc) {
@@ -61,7 +138,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
61 138
62 rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash); 139 rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
63 if (rc) { 140 if (rc) {
64 cifs_dbg(VFS, "%s: Could not init md5\n", __func__); 141 cifs_dbg(VFS, "%s: Could not init sha256", __func__);
65 return rc; 142 return rc;
66 } 143 }
67 144
@@ -129,6 +206,12 @@ generate_smb3signingkey(struct TCP_Server_Info *server)
129 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); 206 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
130 memset(server->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE); 207 memset(server->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE);
131 208
209 rc = smb3_crypto_shash_allocate(server);
210 if (rc) {
211 cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
212 goto smb3signkey_ret;
213 }
214
132 rc = crypto_shash_setkey(server->secmech.hmacsha256, 215 rc = crypto_shash_setkey(server->secmech.hmacsha256,
133 server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE); 216 server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
134 if (rc) { 217 if (rc) {
@@ -210,6 +293,11 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
210 return rc; 293 return rc;
211 } 294 }
212 295
296 /*
297 * we already allocate sdesccmacaes when we init smb3 signing key,
298 * so unlike smb2 case we do not have to check here if secmech are
299 * initialized
300 */
213 rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash); 301 rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash);
214 if (rc) { 302 if (rc) {
215 cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__); 303 cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);