Commit f1c410885288e0042099960ee9e0c260dfea4cfb

Authored by Linus Torvalds

Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "Fixes for 4 cifs bugs, including a reconnect problem, a problem
  parsing responses to SMB2 open request, and setting nlink incorrectly
  to some servers which don't report it properly on the wire.  Also
  improves data integrity on reconnect with series from Pavel which adds
  durable handle support for SMB2."

* 'for-linus' of git://git.samba.org/sfrench/cifs-2.6:
  CIFS: Fix a deadlock when a file is reopened
  CIFS: Reopen the file if reconnect durable handle failed
  [CIFS] Fix minor endian error in durable handle patch series
  CIFS: Reconnect durable handles for SMB2
  CIFS: Make SMB2_open use cifs_open_parms struct
  CIFS: Introduce cifs_open_parms struct
  CIFS: Request durable open for SMB2 opens
  CIFS: Simplify SMB2 create context handling
  CIFS: Simplify SMB2_open code path
  CIFS: Respect create_options in smb2_open_file
  CIFS: Fix lease context buffer parsing
  [CIFS] use sensible file nlink values if unprovided
  Limit allocation of crypto mechanisms to dialect which requires

Showing 15 changed files Side-by-side Diff

fs/cifs/cifsencrypt.c
1 1 /*
2 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 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 6 *
7 7 * This library is free software; you can redistribute it and/or modify
... ... @@ -31,6 +31,36 @@
31 31 #include <linux/random.h>
32 32 #include <linux/highmem.h>
33 33  
  34 +static int
  35 +cifs_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 65 * Calculate and return the CIFS signature based on the mac key and SMB PDU.
36 66 * The 16 byte signature must be allocated by the caller. Note we only use the
... ... @@ -50,8 +80,11 @@
50 80 return -EINVAL;
51 81  
52 82 if (!server->secmech.sdescmd5) {
53   - cifs_dbg(VFS, "%s: Can't generate signature\n", __func__);
54   - return -1;
  83 + rc = cifs_crypto_shash_md5_allocate(server);
  84 + if (rc) {
  85 + cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__);
  86 + return -1;
  87 + }
55 88 }
56 89  
57 90 rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
58 91  
... ... @@ -556,7 +589,34 @@
556 589 return rc;
557 590 }
558 591  
  592 +static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
  593 +{
  594 + unsigned int size;
559 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 +}
  619 +
560 620 int
561 621 setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
562 622 {
... ... @@ -606,6 +666,12 @@
606 666  
607 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 675 /* calculate ntlmv2_hash */
610 676 rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
611 677 if (rc) {
612 678  
613 679  
614 680  
615 681  
616 682  
617 683  
618 684  
619 685  
620 686  
621 687  
622 688  
... ... @@ -705,124 +771,33 @@
705 771 void
706 772 cifs_crypto_shash_release(struct TCP_Server_Info *server)
707 773 {
708   - if (server->secmech.cmacaes)
  774 + if (server->secmech.cmacaes) {
709 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 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 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 790 crypto_free_shash(server->secmech.hmacmd5);
  791 + server->secmech.hmacmd5 = NULL;
  792 + }
719 793  
720 794 kfree(server->secmech.sdesccmacaes);
721   -
  795 + server->secmech.sdesccmacaes = NULL;
722 796 kfree(server->secmech.sdeschmacsha256);
723   -
  797 + server->secmech.sdeschmacsha256 = NULL;
724 798 kfree(server->secmech.sdeschmacmd5);
725   -
  799 + server->secmech.sdeschmacmd5 = NULL;
726 800 kfree(server->secmech.sdescmd5);
727   -}
728   -
729   -int
730   -cifs_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   -
805   -crypto_allocate_cmacaes_sdesc_fail:
806   - kfree(server->secmech.sdeschmacsha256);
807   -
808   -crypto_allocate_hmacsha256_sdesc_fail:
809   - kfree(server->secmech.sdescmd5);
810   -
811   -crypto_allocate_md5_sdesc_fail:
812   - kfree(server->secmech.sdeschmacmd5);
813   -
814   -crypto_allocate_hmacmd5_sdesc_fail:
815   - crypto_free_shash(server->secmech.cmacaes);
816   -
817   -crypto_allocate_cmacaes_fail:
818   - crypto_free_shash(server->secmech.hmacsha256);
819   -
820   -crypto_allocate_hmacsha256_fail:
821   - crypto_free_shash(server->secmech.md5);
822   -
823   -crypto_allocate_md5_fail:
824   - crypto_free_shash(server->secmech.hmacmd5);
825   -
826   - return rc;
  801 + server->secmech.sdescmd5 = NULL;
827 802 }
... ... @@ -194,6 +194,7 @@
194 194 struct cifs_io_parms;
195 195 struct cifs_search_info;
196 196 struct cifsInodeInfo;
  197 +struct cifs_open_parms;
197 198  
198 199 struct smb_version_operations {
199 200 int (*send_cancel)(struct TCP_Server_Info *, void *,
... ... @@ -307,9 +308,8 @@
307 308 const char *, const char *,
308 309 struct cifs_sb_info *);
309 310 /* open a file for non-posix mounts */
310   - int (*open)(const unsigned int, struct cifs_tcon *, const char *, int,
311   - int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *,
312   - struct cifs_sb_info *);
  311 + int (*open)(const unsigned int, struct cifs_open_parms *,
  312 + __u32 *, FILE_ALL_INFO *);
313 313 /* set fid protocol-specific info */
314 314 void (*set_fid)(struct cifsFileInfo *, struct cifs_fid *, __u32);
315 315 /* close a file */
... ... @@ -910,6 +910,17 @@
910 910 bool emptyDir:1;
911 911 bool unicode:1;
912 912 bool smallBuf:1; /* so we know which buf_release function to call */
  913 +};
  914 +
  915 +struct 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;
913 924 };
914 925  
915 926 struct cifs_fid {
... ... @@ -433,7 +433,6 @@
433 433 const struct nls_table *);
434 434 extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
435 435 extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
436   -extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *);
437 436 extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
438 437 extern int calc_seckey(struct cifs_ses *);
439 438 extern void generate_smb3signingkey(struct TCP_Server_Info *);
... ... @@ -2108,12 +2108,6 @@
2108 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 2111 tcp_ses->ops = volume_info->ops;
2118 2112 tcp_ses->vals = volume_info->vals;
2119 2113 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
... ... @@ -204,6 +204,7 @@
204 204 struct inode *newinode = NULL;
205 205 int disposition;
206 206 struct TCP_Server_Info *server = tcon->ses->server;
  207 + struct cifs_open_parms oparms;
207 208  
208 209 *oplock = 0;
209 210 if (tcon->ses->server->oplocks)
... ... @@ -319,9 +320,16 @@
319 320 if (backup_cred(cifs_sb))
320 321 create_options |= CREATE_OPEN_BACKUP_INTENT;
321 322  
322   - rc = server->ops->open(xid, tcon, full_path, disposition,
323   - desired_access, create_options, fid, oplock,
324   - buf, cifs_sb);
  323 + oparms.tcon = tcon;
  324 + oparms.cifs_sb = 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 333 if (rc) {
326 334 cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
327 335 goto out;
... ... @@ -183,6 +183,7 @@
183 183 int create_options = CREATE_NOT_DIR;
184 184 FILE_ALL_INFO *buf;
185 185 struct TCP_Server_Info *server = tcon->ses->server;
  186 + struct cifs_open_parms oparms;
186 187  
187 188 if (!server->ops->open)
188 189 return -ENOSYS;
189 190  
... ... @@ -224,10 +225,17 @@
224 225 if (backup_cred(cifs_sb))
225 226 create_options |= CREATE_OPEN_BACKUP_INTENT;
226 227  
227   - rc = server->ops->open(xid, tcon, full_path, disposition,
228   - desired_access, create_options, fid, oplock, buf,
229   - cifs_sb);
  228 + oparms.tcon = tcon;
  229 + oparms.cifs_sb = 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;
230 236  
  237 + rc = server->ops->open(xid, &oparms, oplock, buf);
  238 +
231 239 if (rc)
232 240 goto out;
233 241  
234 242  
... ... @@ -553,11 +561,10 @@
553 561 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
554 562 int rc = 0;
555 563  
556   - /* we are going to update can_cache_brlcks here - need a write access */
557   - down_write(&cinode->lock_sem);
  564 + down_read(&cinode->lock_sem);
558 565 if (cinode->can_cache_brlcks) {
559   - /* can cache locks - no need to push them */
560   - up_write(&cinode->lock_sem);
  566 + /* can cache locks - no need to relock */
  567 + up_read(&cinode->lock_sem);
561 568 return rc;
562 569 }
563 570  
... ... @@ -568,7 +575,7 @@
568 575 else
569 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 579 return rc;
573 580 }
574 581  
... ... @@ -587,7 +594,7 @@
587 594 int desired_access;
588 595 int disposition = FILE_OPEN;
589 596 int create_options = CREATE_NOT_DIR;
590   - struct cifs_fid fid;
  597 + struct cifs_open_parms oparms;
591 598  
592 599 xid = get_xid();
593 600 mutex_lock(&cfile->fh_mutex);
... ... @@ -637,7 +644,7 @@
637 644  
638 645 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
639 646 cifs_sb->mnt_file_mode /* ignored */,
640   - oflags, &oplock, &fid.netfid, xid);
  647 + oflags, &oplock, &cfile->fid.netfid, xid);
641 648 if (rc == 0) {
642 649 cifs_dbg(FYI, "posix reopen succeeded\n");
643 650 goto reopen_success;
644 651  
... ... @@ -654,8 +661,17 @@
654 661 create_options |= CREATE_OPEN_BACKUP_INTENT;
655 662  
656 663 if (server->ops->get_lease_key)
657   - server->ops->get_lease_key(inode, &fid);
  664 + server->ops->get_lease_key(inode, &cfile->fid);
658 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;
  674 +
659 675 /*
660 676 * Can not refresh inode by passing in file_info buf to be returned by
661 677 * CIFSSMBOpen and then calling get_inode_info with returned buf since
... ... @@ -663,9 +679,14 @@
663 679 * version of file size can be stale. If we knew for sure that inode was
664 680 * not dirty locally we could do this.
665 681 */
666   - rc = server->ops->open(xid, tcon, full_path, disposition,
667   - desired_access, create_options, &fid, &oplock,
668   - NULL, cifs_sb);
  682 + rc = server->ops->open(xid, &oparms, &oplock, NULL);
  683 + if (rc == -ENOENT && oparms.reconnect == false) {
  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 690 if (rc) {
670 691 mutex_unlock(&cfile->fh_mutex);
671 692 cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc);
... ... @@ -696,8 +717,9 @@
696 717 * to the server to get the new inode info.
697 718 */
698 719  
699   - server->ops->set_fid(cfile, &fid, oplock);
700   - cifs_relock_file(cfile);
  720 + server->ops->set_fid(cfile, &cfile->fid, oplock);
  721 + if (oparms.reconnect)
  722 + cifs_relock_file(cfile);
701 723  
702 724 reopen_error_exit:
703 725 kfree(full_path);
... ... @@ -558,6 +558,11 @@
558 558 fattr->cf_mode &= ~(S_IWUGO);
559 559  
560 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 568 fattr->cf_uid = cifs_sb->mnt_uid;
... ... @@ -674,20 +674,23 @@
674 674 }
675 675  
676 676 static int
677   -cifs_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path,
678   - int disposition, int desired_access, int create_options,
679   - struct cifs_fid *fid, __u32 *oplock, FILE_ALL_INFO *buf,
680   - struct cifs_sb_info *cifs_sb)
  677 +cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
  678 + __u32 *oplock, FILE_ALL_INFO *buf)
681 679 {
682   - if (!(tcon->ses->capabilities & CAP_NT_SMBS))
683   - return SMBLegacyOpen(xid, tcon, path, disposition,
684   - desired_access, create_options,
685   - &fid->netfid, oplock, buf,
686   - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
  680 + if (!(oparms->tcon->ses->capabilities & CAP_NT_SMBS))
  681 + return SMBLegacyOpen(xid, oparms->tcon, oparms->path,
  682 + oparms->disposition,
  683 + oparms->desired_access,
  684 + oparms->create_options,
  685 + &oparms->fid->netfid, oplock, buf,
  686 + oparms->cifs_sb->local_nls,
  687 + oparms->cifs_sb->mnt_cifs_flags
687 688 & CIFS_MOUNT_MAP_SPECIAL_CHR);
688   - return CIFSSMBOpen(xid, tcon, path, disposition, desired_access,
689   - create_options, &fid->netfid, oplock, buf,
690   - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
  689 + return CIFSSMBOpen(xid, oparms->tcon, oparms->path,
  690 + oparms->disposition, oparms->desired_access,
  691 + oparms->create_options, &oparms->fid->netfid, oplock,
  692 + buf, oparms->cifs_sb->local_nls,
  693 + oparms->cifs_sb->mnt_cifs_flags &
691 694 CIFS_MOUNT_MAP_SPECIAL_CHR);
692 695 }
693 696  
... ... @@ -40,7 +40,8 @@
40 40 oplock &= 0xFF;
41 41 if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
42 42 return;
43   - if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
  43 + if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
  44 + oplock == SMB2_OPLOCK_LEVEL_BATCH) {
44 45 cinode->clientCanCacheAll = true;
45 46 cinode->clientCanCacheRead = true;
46 47 cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
47 48  
48 49  
... ... @@ -57,17 +58,16 @@
57 58 }
58 59  
59 60 int
60   -smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path,
61   - int disposition, int desired_access, int create_options,
62   - struct cifs_fid *fid, __u32 *oplock, FILE_ALL_INFO *buf,
63   - struct cifs_sb_info *cifs_sb)
  61 +smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
  62 + __u32 *oplock, FILE_ALL_INFO *buf)
64 63 {
65 64 int rc;
66 65 __le16 *smb2_path;
67 66 struct smb2_file_all_info *smb2_data = NULL;
68 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 71 if (smb2_path == NULL) {
72 72 rc = -ENOMEM;
73 73 goto out;
74 74  
75 75  
76 76  
... ... @@ -80,21 +80,19 @@
80 80 goto out;
81 81 }
82 82  
83   - desired_access |= FILE_READ_ATTRIBUTES;
84   - *smb2_oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
  83 + oparms->desired_access |= FILE_READ_ATTRIBUTES;
  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 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,
90   - &fid->volatile_fid, desired_access, disposition,
91   - 0, 0, smb2_oplock, smb2_data);
  89 + rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data);
92 90 if (rc)
93 91 goto out;
94 92  
95 93 if (buf) {
96 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 96 fid->volatile_fid,
99 97 &smb2_data->IndexNumber);
100 98 if (rc) {
... ... @@ -41,21 +41,26 @@
41 41 smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
42 42 struct cifs_sb_info *cifs_sb, const char *full_path,
43 43 __u32 desired_access, __u32 create_disposition,
44   - __u32 file_attributes, __u32 create_options,
45   - void *data, int command)
  44 + __u32 create_options, void *data, int command)
46 45 {
47 46 int rc, tmprc = 0;
48   - u64 persistent_fid, volatile_fid;
49 47 __le16 *utf16_path;
50 48 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
  49 + struct cifs_open_parms oparms;
  50 + struct cifs_fid fid;
51 51  
52 52 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
53 53 if (!utf16_path)
54 54 return -ENOMEM;
55 55  
56   - rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid,
57   - desired_access, create_disposition, file_attributes,
58   - create_options, &oplock, NULL);
  56 + oparms.tcon = tcon;
  57 + oparms.desired_access = desired_access;
  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 64 if (rc) {
60 65 kfree(utf16_path);
61 66 return rc;
... ... @@ -65,8 +70,8 @@
65 70 case SMB2_OP_DELETE:
66 71 break;
67 72 case SMB2_OP_QUERY_INFO:
68   - tmprc = SMB2_query_info(xid, tcon, persistent_fid,
69   - volatile_fid,
  73 + tmprc = SMB2_query_info(xid, tcon, fid.persistent_fid,
  74 + fid.volatile_fid,
70 75 (struct smb2_file_all_info *)data);
71 76 break;
72 77 case SMB2_OP_MKDIR:
73 78  
74 79  
75 80  
... ... @@ -76,19 +81,21 @@
76 81 */
77 82 break;
78 83 case SMB2_OP_RENAME:
79   - tmprc = SMB2_rename(xid, tcon, persistent_fid, volatile_fid,
80   - (__le16 *)data);
  84 + tmprc = SMB2_rename(xid, tcon, fid.persistent_fid,
  85 + fid.volatile_fid, (__le16 *)data);
81 86 break;
82 87 case SMB2_OP_HARDLINK:
83   - tmprc = SMB2_set_hardlink(xid, tcon, persistent_fid,
84   - volatile_fid, (__le16 *)data);
  88 + tmprc = SMB2_set_hardlink(xid, tcon, fid.persistent_fid,
  89 + fid.volatile_fid, (__le16 *)data);
85 90 break;
86 91 case SMB2_OP_SET_EOF:
87   - tmprc = SMB2_set_eof(xid, tcon, persistent_fid, volatile_fid,
88   - current->tgid, (__le64 *)data);
  92 + tmprc = SMB2_set_eof(xid, tcon, fid.persistent_fid,
  93 + fid.volatile_fid, current->tgid,
  94 + (__le64 *)data);
89 95 break;
90 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 99 (FILE_BASIC_INFO *)data);
93 100 break;
94 101 default:
... ... @@ -96,7 +103,7 @@
96 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 107 if (tmprc)
101 108 rc = tmprc;
102 109 kfree(utf16_path);
... ... @@ -129,8 +136,8 @@
129 136 return -ENOMEM;
130 137  
131 138 rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path,
132   - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0,
133   - smb2_data, SMB2_OP_QUERY_INFO);
  139 + FILE_READ_ATTRIBUTES, FILE_OPEN, 0, smb2_data,
  140 + SMB2_OP_QUERY_INFO);
134 141 if (rc)
135 142 goto out;
136 143  
... ... @@ -145,7 +152,7 @@
145 152 struct cifs_sb_info *cifs_sb)
146 153 {
147 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 156 CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR);
150 157 }
151 158  
... ... @@ -164,7 +171,7 @@
164 171 dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
165 172 data.Attributes = cpu_to_le32(dosattrs);
166 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 175 CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO);
169 176 if (tmprc == 0)
170 177 cifs_i->cifsAttrs = dosattrs;
... ... @@ -175,7 +182,7 @@
175 182 struct cifs_sb_info *cifs_sb)
176 183 {
177 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 186 NULL, SMB2_OP_DELETE);
180 187 }
181 188  
... ... @@ -184,7 +191,7 @@
184 191 struct cifs_sb_info *cifs_sb)
185 192 {
186 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 195 SMB2_OP_DELETE);
189 196 }
190 197  
... ... @@ -203,7 +210,7 @@
203 210 }
204 211  
205 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);
207 214 smb2_rename_path:
208 215 kfree(smb2_to_name);
209 216 return rc;
... ... @@ -234,7 +241,7 @@
234 241 {
235 242 __le64 eof = cpu_to_le64(size);
236 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 245 SMB2_OP_SET_EOF);
239 246 }
240 247  
... ... @@ -250,7 +257,7 @@
250 257 if (IS_ERR(tlink))
251 258 return PTR_ERR(tlink);
252 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 261 SMB2_OP_SET_INFO);
255 262 cifs_put_tlink(tlink);
256 263 return rc;
... ... @@ -213,22 +213,29 @@
213 213 struct cifs_sb_info *cifs_sb, const char *full_path)
214 214 {
215 215 int rc;
216   - __u64 persistent_fid, volatile_fid;
217 216 __le16 *utf16_path;
218 217 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
  218 + struct cifs_open_parms oparms;
  219 + struct cifs_fid fid;
219 220  
220 221 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
221 222 if (!utf16_path)
222 223 return -ENOMEM;
223 224  
224   - rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid,
225   - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock, NULL);
  225 + oparms.tcon = tcon;
  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 233 if (rc) {
227 234 kfree(utf16_path);
228 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 239 kfree(utf16_path);
233 240 return rc;
234 241 }
235 242  
... ... @@ -443,15 +450,20 @@
443 450 __le16 *utf16_path;
444 451 int rc;
445 452 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
446   - __u64 persistent_fid, volatile_fid;
  453 + struct cifs_open_parms oparms;
447 454  
448 455 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
449 456 if (!utf16_path)
450 457 return -ENOMEM;
451 458  
452   - rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid,
453   - FILE_READ_ATTRIBUTES | FILE_READ_DATA, FILE_OPEN, 0, 0,
454   - &oplock, NULL);
  459 + oparms.tcon = tcon;
  460 + oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA;
  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 467 kfree(utf16_path);
456 468 if (rc) {
457 469 cifs_dbg(VFS, "open dir failed\n");
458 470  
459 471  
... ... @@ -460,14 +472,12 @@
460 472  
461 473 srch_inf->entries_in_buffer = 0;
462 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,
467   - srch_inf);
  476 + rc = SMB2_query_directory(xid, tcon, fid->persistent_fid,
  477 + fid->volatile_fid, 0, srch_inf);
468 478 if (rc) {
469 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 482 return rc;
473 483 }
474 484  
475 485  
476 486  
... ... @@ -528,17 +538,25 @@
528 538 struct kstatfs *buf)
529 539 {
530 540 int rc;
531   - u64 persistent_fid, volatile_fid;
532 541 __le16 srch_path = 0; /* Null - open root of share */
533 542 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
  543 + struct cifs_open_parms oparms;
  544 + struct cifs_fid fid;
534 545  
535   - rc = SMB2_open(xid, tcon, &srch_path, &persistent_fid, &volatile_fid,
536   - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock, NULL);
  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;
  552 +
  553 + rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL);
537 554 if (rc)
538 555 return rc;
539 556 buf->f_type = SMB2_MAGIC_NUMBER;
540   - rc = SMB2_QFS_info(xid, tcon, persistent_fid, volatile_fid, buf);
541   - SMB2_close(xid, tcon, persistent_fid, volatile_fid);
  557 + rc = SMB2_QFS_info(xid, tcon, fid.persistent_fid, fid.volatile_fid,
  558 + buf);
  559 + SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
542 560 return rc;
543 561 }
544 562  
... ... @@ -847,29 +847,76 @@
847 847 return buf;
848 848 }
849 849  
  850 +static struct create_durable *
  851 +create_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 +
  872 +static struct create_durable *
  873 +create_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 +
850 896 static __u8
851 897 parse_lease_state(struct smb2_create_rsp *rsp)
852 898 {
853 899 char *data_offset;
854 900 struct create_lease *lc;
855 901 bool found = false;
  902 + unsigned int next = 0;
  903 + char *name;
856 904  
857   - data_offset = (char *)rsp;
858   - data_offset += 4 + le32_to_cpu(rsp->CreateContextsOffset);
  905 + data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
859 906 lc = (struct create_lease *)data_offset;
860 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 910 if (le16_to_cpu(lc->ccontext.NameLength) != 4 ||
863 911 strncmp(name, "RqLs", 4)) {
864   - lc = (struct create_lease *)((char *)lc
865   - + le32_to_cpu(lc->ccontext.Next));
  912 + next = le32_to_cpu(lc->ccontext.Next);
866 913 continue;
867 914 }
868 915 if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
869 916 return SMB2_OPLOCK_LEVEL_NOCHANGE;
870 917 found = true;
871 918 break;
872   - } while (le32_to_cpu(lc->ccontext.Next) != 0);
  919 + } while (next != 0);
873 920  
874 921 if (!found)
875 922 return 0;
876 923  
877 924  
878 925  
879 926  
... ... @@ -877,23 +924,74 @@
877 924 return smb2_map_lease_to_oplock(lc->lcontext.LeaseState);
878 925 }
879 926  
  927 +static int
  928 +add_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 +
  950 +static int
  951 +add_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 +
880 978 int
881   -SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path,
882   - u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access,
883   - __u32 create_disposition, __u32 file_attributes, __u32 create_options,
  979 +SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
884 980 __u8 *oplock, struct smb2_file_all_info *buf)
885 981 {
886 982 struct smb2_create_req *req;
887 983 struct smb2_create_rsp *rsp;
888 984 struct TCP_Server_Info *server;
  985 + struct cifs_tcon *tcon = oparms->tcon;
889 986 struct cifs_ses *ses = tcon->ses;
890   - struct kvec iov[3];
  987 + struct kvec iov[4];
891 988 int resp_buftype;
892 989 int uni_path_len;
893 990 __le16 *copy_path = NULL;
894 991 int copy_size;
895 992 int rc = 0;
896   - int num_iovecs = 2;
  993 + unsigned int num_iovecs = 2;
  994 + __u32 file_attributes = 0;
897 995  
898 996 cifs_dbg(FYI, "create/open\n");
899 997  
900 998  
901 999  
902 1000  
903 1001  
904 1002  
905 1003  
... ... @@ -906,55 +1004,47 @@
906 1004 if (rc)
907 1005 return rc;
908 1006  
  1007 + if (oparms->create_options & CREATE_OPTION_READONLY)
  1008 + file_attributes |= ATTR_READONLY;
  1009 +
909 1010 req->ImpersonationLevel = IL_IMPERSONATION;
910   - req->DesiredAccess = cpu_to_le32(desired_access);
  1011 + req->DesiredAccess = cpu_to_le32(oparms->desired_access);
911 1012 /* File attributes ignored on open (used in create though) */
912 1013 req->FileAttributes = cpu_to_le32(file_attributes);
913 1014 req->ShareAccess = FILE_SHARE_ALL_LE;
914   - req->CreateDisposition = cpu_to_le32(create_disposition);
915   - req->CreateOptions = cpu_to_le32(create_options);
  1015 + req->CreateDisposition = cpu_to_le32(oparms->disposition);
  1016 + req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK);
916 1017 uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
917   - req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req)
918   - - 8 /* pad */ - 4 /* do not count rfc1001 len field */);
  1018 + /* do not count rfc1001 len field */
  1019 + req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4);
919 1020  
920 1021 iov[0].iov_base = (char *)req;
921 1022 /* 4 for rfc1002 length field */
922 1023 iov[0].iov_len = get_rfc1002_length(req) + 4;
923 1024  
924 1025 /* MUST set path len (NameLength) to 0 opening root of share */
925   - if (uni_path_len >= 4) {
926   - req->NameLength = cpu_to_le16(uni_path_len - 2);
927   - /* -1 since last byte is buf[0] which is sent below (path) */
928   - iov[0].iov_len--;
929   - if (uni_path_len % 8 != 0) {
930   - copy_size = uni_path_len / 8 * 8;
931   - if (copy_size < uni_path_len)
932   - copy_size += 8;
  1026 + req->NameLength = cpu_to_le16(uni_path_len - 2);
  1027 + /* -1 since last byte is buf[0] which is sent below (path) */
  1028 + iov[0].iov_len--;
  1029 + if (uni_path_len % 8 != 0) {
  1030 + copy_size = uni_path_len / 8 * 8;
  1031 + if (copy_size < uni_path_len)
  1032 + copy_size += 8;
933 1033  
934   - copy_path = kzalloc(copy_size, GFP_KERNEL);
935   - if (!copy_path)
936   - return -ENOMEM;
937   - memcpy((char *)copy_path, (const char *)path,
938   - uni_path_len);
939   - uni_path_len = copy_size;
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;
  1034 + copy_path = kzalloc(copy_size, GFP_KERNEL);
  1035 + if (!copy_path)
  1036 + return -ENOMEM;
  1037 + memcpy((char *)copy_path, (const char *)path,
  1038 + uni_path_len);
  1039 + uni_path_len = copy_size;
  1040 + path = copy_path;
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 1048 if (!server->oplocks)
959 1049 *oplock = SMB2_OPLOCK_LEVEL_NONE;
960 1050  
961 1051  
962 1052  
963 1053  
... ... @@ -962,23 +1052,31 @@
962 1052 *oplock == SMB2_OPLOCK_LEVEL_NONE)
963 1053 req->RequestedOplockLevel = *oplock;
964 1054 else {
965   - iov[num_iovecs].iov_base = create_lease_buf(oplock+1, *oplock);
966   - if (iov[num_iovecs].iov_base == NULL) {
  1055 + rc = add_lease_context(iov, &num_iovecs, oplock);
  1056 + if (rc) {
967 1057 cifs_small_buf_release(req);
968 1058 kfree(copy_path);
969   - return -ENOMEM;
  1059 + return rc;
970 1060 }
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 1061 }
981 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;
  1077 + }
  1078 + }
  1079 +
982 1080 rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0);
983 1081 rsp = (struct smb2_create_rsp *)iov[0].iov_base;
984 1082  
... ... @@ -987,8 +1085,8 @@
987 1085 goto creat_exit;
988 1086 }
989 1087  
990   - *persistent_fid = rsp->PersistentFileId;
991   - *volatile_fid = rsp->VolatileFileId;
  1088 + oparms->fid->persistent_fid = rsp->PersistentFileId;
  1089 + oparms->fid->volatile_fid = rsp->VolatileFileId;
992 1090  
993 1091 if (buf) {
994 1092 memcpy(buf, &rsp->CreationTime, 32);
... ... @@ -428,7 +428,7 @@
428 428 __le16 NameLength;
429 429 __le32 CreateContextsOffset;
430 430 __le32 CreateContextsLength;
431   - __u8 Buffer[8];
  431 + __u8 Buffer[0];
432 432 } __packed;
433 433  
434 434 struct smb2_create_rsp {
... ... @@ -483,6 +483,18 @@
483 483 struct create_context ccontext;
484 484 __u8 Name[8];
485 485 struct lease_context lcontext;
  486 +} __packed;
  487 +
  488 +struct 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;
486 498 } __packed;
487 499  
488 500 /* this goes in the ioctl buffer when doing a copychunk request */
... ... @@ -84,11 +84,9 @@
84 84 const char *from_name, const char *to_name,
85 85 struct cifs_sb_info *cifs_sb);
86 86  
87   -extern int smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon,
88   - const char *full_path, int disposition,
89   - int desired_access, int create_options,
90   - struct cifs_fid *fid, __u32 *oplock,
91   - FILE_ALL_INFO *buf, struct cifs_sb_info *cifs_sb);
  87 +extern int smb2_open_file(const unsigned int xid,
  88 + struct cifs_open_parms *oparms,
  89 + __u32 *oplock, FILE_ALL_INFO *buf);
92 90 extern void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock);
93 91 extern int smb2_unlock_range(struct cifsFileInfo *cfile,
94 92 struct file_lock *flock, const unsigned int xid);
... ... @@ -106,11 +104,9 @@
106 104 const char *tree, struct cifs_tcon *tcon,
107 105 const struct nls_table *);
108 106 extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
109   -extern int SMB2_open(const unsigned int xid, struct cifs_tcon *tcon,
110   - __le16 *path, u64 *persistent_fid, u64 *volatile_fid,
111   - __u32 desired_access, __u32 create_disposition,
112   - __u32 file_attributes, __u32 create_options,
113   - __u8 *oplock, struct smb2_file_all_info *buf);
  107 +extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
  108 + __le16 *path, __u8 *oplock,
  109 + struct smb2_file_all_info *buf);
114 110 extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
115 111 u64 persistent_fid, u64 volatile_fid, u32 opcode,
116 112 bool is_fsctl, char *in_data, u32 indatalen,
fs/cifs/smb2transport.c
... ... @@ -39,6 +39,77 @@
39 39 #include "smb2status.h"
40 40 #include "smb2glob.h"
41 41  
  42 +static int
  43 +smb2_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 +
  70 +static int
  71 +smb3_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 +
42 113 int
43 114 smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
44 115 {
... ... @@ -52,6 +123,12 @@
52 123 memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
53 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 132 rc = crypto_shash_setkey(server->secmech.hmacsha256,
56 133 server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
57 134 if (rc) {
... ... @@ -61,7 +138,7 @@
61 138  
62 139 rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
63 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 142 return rc;
66 143 }
67 144  
... ... @@ -129,6 +206,12 @@
129 206 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
130 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 215 rc = crypto_shash_setkey(server->secmech.hmacsha256,
133 216 server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
134 217 if (rc) {
... ... @@ -210,6 +293,11 @@
210 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 301 rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash);
214 302 if (rc) {
215 303 cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);