Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+513 -279
+85 -110
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 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 ··· 80 50 return -EINVAL; 81 51 82 52 if (!server->secmech.sdescmd5) { 83 - cifs_dbg(VFS, "%s: Can't generate signature\n", __func__); 84 - return -1; 53 + rc = cifs_crypto_shash_md5_allocate(server); 54 + if (rc) { 55 + cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__); 56 + return -1; 57 + } 85 58 } 86 59 87 60 rc = crypto_shash_init(&server->secmech.sdescmd5->shash); ··· 589 556 return rc; 590 557 } 591 558 559 + static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server) 560 + { 561 + unsigned int size; 562 + 563 + /* check if already allocated */ 564 + if (server->secmech.sdeschmacmd5) 565 + return 0; 566 + 567 + server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); 568 + if (IS_ERR(server->secmech.hmacmd5)) { 569 + cifs_dbg(VFS, "could not allocate crypto hmacmd5\n"); 570 + return PTR_ERR(server->secmech.hmacmd5); 571 + } 572 + 573 + size = sizeof(struct shash_desc) + 574 + crypto_shash_descsize(server->secmech.hmacmd5); 575 + server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); 576 + if (!server->secmech.sdeschmacmd5) { 577 + crypto_free_shash(server->secmech.hmacmd5); 578 + server->secmech.hmacmd5 = NULL; 579 + return -ENOMEM; 580 + } 581 + server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5; 582 + server->secmech.sdeschmacmd5->shash.flags = 0x0; 583 + 584 + return 0; 585 + } 592 586 593 587 int 594 588 setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) ··· 665 605 buf->reserved2 = 0; 666 606 667 607 memcpy(ses->auth_key.response + baselen, tiblob, tilen); 608 + 609 + rc = crypto_hmacmd5_alloc(ses->server); 610 + if (rc) { 611 + cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc); 612 + goto setup_ntlmv2_rsp_ret; 613 + } 668 614 669 615 /* calculate ntlmv2_hash */ 670 616 rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp); ··· 771 705 void 772 706 cifs_crypto_shash_release(struct TCP_Server_Info *server) 773 707 { 774 - if (server->secmech.cmacaes) 708 + if (server->secmech.cmacaes) { 775 709 crypto_free_shash(server->secmech.cmacaes); 710 + server->secmech.cmacaes = NULL; 711 + } 776 712 777 - if (server->secmech.hmacsha256) 713 + if (server->secmech.hmacsha256) { 778 714 crypto_free_shash(server->secmech.hmacsha256); 715 + server->secmech.hmacsha256 = NULL; 716 + } 779 717 780 - if (server->secmech.md5) 718 + if (server->secmech.md5) { 781 719 crypto_free_shash(server->secmech.md5); 720 + server->secmech.md5 = NULL; 721 + } 782 722 783 - if (server->secmech.hmacmd5) 723 + if (server->secmech.hmacmd5) { 784 724 crypto_free_shash(server->secmech.hmacmd5); 725 + server->secmech.hmacmd5 = NULL; 726 + } 785 727 786 728 kfree(server->secmech.sdesccmacaes); 787 - 729 + server->secmech.sdesccmacaes = NULL; 788 730 kfree(server->secmech.sdeschmacsha256); 789 - 731 + server->secmech.sdeschmacsha256 = NULL; 790 732 kfree(server->secmech.sdeschmacmd5); 791 - 733 + server->secmech.sdeschmacmd5 = NULL; 792 734 kfree(server->secmech.sdescmd5); 793 - } 794 - 795 - int 796 - cifs_crypto_shash_allocate(struct TCP_Server_Info *server) 797 - { 798 - int rc; 799 - unsigned int size; 800 - 801 - server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); 802 - if (IS_ERR(server->secmech.hmacmd5)) { 803 - cifs_dbg(VFS, "could not allocate crypto hmacmd5\n"); 804 - return PTR_ERR(server->secmech.hmacmd5); 805 - } 806 - 807 - server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); 808 - if (IS_ERR(server->secmech.md5)) { 809 - cifs_dbg(VFS, "could not allocate crypto md5\n"); 810 - rc = PTR_ERR(server->secmech.md5); 811 - goto crypto_allocate_md5_fail; 812 - } 813 - 814 - server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0); 815 - if (IS_ERR(server->secmech.hmacsha256)) { 816 - cifs_dbg(VFS, "could not allocate crypto hmacsha256\n"); 817 - rc = PTR_ERR(server->secmech.hmacsha256); 818 - goto crypto_allocate_hmacsha256_fail; 819 - } 820 - 821 - server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0); 822 - if (IS_ERR(server->secmech.cmacaes)) { 823 - cifs_dbg(VFS, "could not allocate crypto cmac-aes"); 824 - rc = PTR_ERR(server->secmech.cmacaes); 825 - goto crypto_allocate_cmacaes_fail; 826 - } 827 - 828 - size = sizeof(struct shash_desc) + 829 - crypto_shash_descsize(server->secmech.hmacmd5); 830 - server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); 831 - if (!server->secmech.sdeschmacmd5) { 832 - rc = -ENOMEM; 833 - goto crypto_allocate_hmacmd5_sdesc_fail; 834 - } 835 - server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5; 836 - server->secmech.sdeschmacmd5->shash.flags = 0x0; 837 - 838 - size = sizeof(struct shash_desc) + 839 - crypto_shash_descsize(server->secmech.md5); 840 - server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); 841 - if (!server->secmech.sdescmd5) { 842 - rc = -ENOMEM; 843 - goto crypto_allocate_md5_sdesc_fail; 844 - } 845 - server->secmech.sdescmd5->shash.tfm = server->secmech.md5; 846 - server->secmech.sdescmd5->shash.flags = 0x0; 847 - 848 - size = sizeof(struct shash_desc) + 849 - crypto_shash_descsize(server->secmech.hmacsha256); 850 - server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL); 851 - if (!server->secmech.sdeschmacsha256) { 852 - rc = -ENOMEM; 853 - goto crypto_allocate_hmacsha256_sdesc_fail; 854 - } 855 - server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256; 856 - server->secmech.sdeschmacsha256->shash.flags = 0x0; 857 - 858 - size = sizeof(struct shash_desc) + 859 - crypto_shash_descsize(server->secmech.cmacaes); 860 - server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL); 861 - if (!server->secmech.sdesccmacaes) { 862 - cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__); 863 - rc = -ENOMEM; 864 - goto crypto_allocate_cmacaes_sdesc_fail; 865 - } 866 - server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes; 867 - server->secmech.sdesccmacaes->shash.flags = 0x0; 868 - 869 - return 0; 870 - 871 - crypto_allocate_cmacaes_sdesc_fail: 872 - kfree(server->secmech.sdeschmacsha256); 873 - 874 - crypto_allocate_hmacsha256_sdesc_fail: 875 - kfree(server->secmech.sdescmd5); 876 - 877 - crypto_allocate_md5_sdesc_fail: 878 - kfree(server->secmech.sdeschmacmd5); 879 - 880 - crypto_allocate_hmacmd5_sdesc_fail: 881 - crypto_free_shash(server->secmech.cmacaes); 882 - 883 - crypto_allocate_cmacaes_fail: 884 - crypto_free_shash(server->secmech.hmacsha256); 885 - 886 - crypto_allocate_hmacsha256_fail: 887 - crypto_free_shash(server->secmech.md5); 888 - 889 - crypto_allocate_md5_fail: 890 - crypto_free_shash(server->secmech.hmacmd5); 891 - 892 - return rc; 735 + server->secmech.sdescmd5 = NULL; 893 736 }
+14 -3
fs/cifs/cifsglob.h
··· 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 *, ··· 308 307 const char *, const char *, 309 308 struct cifs_sb_info *); 310 309 /* open a file for non-posix mounts */ 311 - int (*open)(const unsigned int, struct cifs_tcon *, const char *, int, 312 - int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *, 313 - struct cifs_sb_info *); 310 + int (*open)(const unsigned int, struct cifs_open_parms *, 311 + __u32 *, FILE_ALL_INFO *); 314 312 /* set fid protocol-specific info */ 315 313 void (*set_fid)(struct cifsFileInfo *, struct cifs_fid *, __u32); 316 314 /* close a file */ ··· 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 {
-1
fs/cifs/cifsproto.h
··· 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 *);
-6
fs/cifs/connect.c
··· 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));
+11 -3
fs/cifs/dir.c
··· 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) ··· 320 319 if (backup_cred(cifs_sb)) 321 320 create_options |= CREATE_OPEN_BACKUP_INTENT; 322 321 323 - rc = server->ops->open(xid, tcon, full_path, disposition, 324 - desired_access, create_options, fid, oplock, 325 - buf, cifs_sb); 322 + oparms.tcon = tcon; 323 + oparms.cifs_sb = cifs_sb; 324 + oparms.desired_access = desired_access; 325 + oparms.create_options = create_options; 326 + oparms.disposition = disposition; 327 + oparms.path = full_path; 328 + oparms.fid = fid; 329 + oparms.reconnect = false; 330 + 331 + rc = server->ops->open(xid, &oparms, oplock, buf); 326 332 if (rc) { 327 333 cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc); 328 334 goto out;
+38 -16
fs/cifs/file.c
··· 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; ··· 225 224 if (backup_cred(cifs_sb)) 226 225 create_options |= CREATE_OPEN_BACKUP_INTENT; 227 226 228 - rc = server->ops->open(xid, tcon, full_path, disposition, 229 - desired_access, create_options, fid, oplock, buf, 230 - cifs_sb); 227 + oparms.tcon = tcon; 228 + oparms.cifs_sb = cifs_sb; 229 + oparms.desired_access = desired_access; 230 + oparms.create_options = create_options; 231 + oparms.disposition = disposition; 232 + oparms.path = full_path; 233 + oparms.fid = fid; 234 + oparms.reconnect = false; 235 + 236 + rc = server->ops->open(xid, &oparms, oplock, buf); 231 237 232 238 if (rc) 233 239 goto out; ··· 561 553 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 562 554 int rc = 0; 563 555 564 - /* we are going to update can_cache_brlcks here - need a write access */ 565 - down_write(&cinode->lock_sem); 556 + down_read(&cinode->lock_sem); 566 557 if (cinode->can_cache_brlcks) { 567 - /* can cache locks - no need to push them */ 568 - up_write(&cinode->lock_sem); 558 + /* can cache locks - no need to relock */ 559 + up_read(&cinode->lock_sem); 569 560 return rc; 570 561 } 571 562 ··· 575 568 else 576 569 rc = tcon->ses->server->ops->push_mand_locks(cfile); 577 570 578 - up_write(&cinode->lock_sem); 571 + up_read(&cinode->lock_sem); 579 572 return rc; 580 573 } 581 574 ··· 594 587 int desired_access; 595 588 int disposition = FILE_OPEN; 596 589 int create_options = CREATE_NOT_DIR; 597 - struct cifs_fid fid; 590 + struct cifs_open_parms oparms; 598 591 599 592 xid = get_xid(); 600 593 mutex_lock(&cfile->fh_mutex); ··· 644 637 645 638 rc = cifs_posix_open(full_path, NULL, inode->i_sb, 646 639 cifs_sb->mnt_file_mode /* ignored */, 647 - oflags, &oplock, &fid.netfid, xid); 640 + oflags, &oplock, &cfile->fid.netfid, xid); 648 641 if (rc == 0) { 649 642 cifs_dbg(FYI, "posix reopen succeeded\n"); 650 643 goto reopen_success; ··· 661 654 create_options |= CREATE_OPEN_BACKUP_INTENT; 662 655 663 656 if (server->ops->get_lease_key) 664 - server->ops->get_lease_key(inode, &fid); 657 + server->ops->get_lease_key(inode, &cfile->fid); 658 + 659 + oparms.tcon = tcon; 660 + oparms.cifs_sb = cifs_sb; 661 + oparms.desired_access = desired_access; 662 + oparms.create_options = create_options; 663 + oparms.disposition = disposition; 664 + oparms.path = full_path; 665 + oparms.fid = &cfile->fid; 666 + oparms.reconnect = true; 665 667 666 668 /* 667 669 * Can not refresh inode by passing in file_info buf to be returned by ··· 679 663 * version of file size can be stale. If we knew for sure that inode was 680 664 * not dirty locally we could do this. 681 665 */ 682 - rc = server->ops->open(xid, tcon, full_path, disposition, 683 - desired_access, create_options, &fid, &oplock, 684 - NULL, cifs_sb); 666 + rc = server->ops->open(xid, &oparms, &oplock, NULL); 667 + if (rc == -ENOENT && oparms.reconnect == false) { 668 + /* durable handle timeout is expired - open the file again */ 669 + rc = server->ops->open(xid, &oparms, &oplock, NULL); 670 + /* indicate that we need to relock the file */ 671 + oparms.reconnect = true; 672 + } 673 + 685 674 if (rc) { 686 675 mutex_unlock(&cfile->fh_mutex); 687 676 cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc); ··· 717 696 * to the server to get the new inode info. 718 697 */ 719 698 720 - server->ops->set_fid(cfile, &fid, oplock); 721 - cifs_relock_file(cfile); 699 + server->ops->set_fid(cfile, &cfile->fid, oplock); 700 + if (oparms.reconnect) 701 + cifs_relock_file(cfile); 722 702 723 703 reopen_error_exit: 724 704 kfree(full_path);
+5
fs/cifs/inode.c
··· 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;
+15 -12
fs/cifs/smb1ops.c
··· 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
+11 -13
fs/cifs/smb2file.c
··· 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", ··· 58 57 } 59 58 60 59 int 61 - smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, 62 - int disposition, int desired_access, int create_options, 63 - struct cifs_fid *fid, __u32 *oplock, FILE_ALL_INFO *buf, 64 - struct cifs_sb_info *cifs_sb) 60 + smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, 61 + __u32 *oplock, FILE_ALL_INFO *buf) 65 62 { 66 63 int rc; 67 64 __le16 *smb2_path; 68 65 struct smb2_file_all_info *smb2_data = NULL; 69 66 __u8 smb2_oplock[17]; 67 + struct cifs_fid *fid = oparms->fid; 70 68 71 - smb2_path = cifs_convert_path_to_utf16(path, cifs_sb); 69 + smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb); 72 70 if (smb2_path == NULL) { 73 71 rc = -ENOMEM; 74 72 goto out; ··· 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) {
+32 -25
fs/cifs/smb2inode.c
··· 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; ··· 70 65 case SMB2_OP_DELETE: 71 66 break; 72 67 case SMB2_OP_QUERY_INFO: 73 - tmprc = SMB2_query_info(xid, tcon, persistent_fid, 74 - volatile_fid, 68 + tmprc = SMB2_query_info(xid, tcon, fid.persistent_fid, 69 + fid.volatile_fid, 75 70 (struct smb2_file_all_info *)data); 76 71 break; 77 72 case SMB2_OP_MKDIR: ··· 81 76 */ 82 77 break; 83 78 case SMB2_OP_RENAME: 84 - tmprc = SMB2_rename(xid, tcon, persistent_fid, volatile_fid, 85 - (__le16 *)data); 79 + tmprc = SMB2_rename(xid, tcon, fid.persistent_fid, 80 + fid.volatile_fid, (__le16 *)data); 86 81 break; 87 82 case SMB2_OP_HARDLINK: 88 - tmprc = SMB2_set_hardlink(xid, tcon, persistent_fid, 89 - volatile_fid, (__le16 *)data); 83 + tmprc = SMB2_set_hardlink(xid, tcon, fid.persistent_fid, 84 + fid.volatile_fid, (__le16 *)data); 90 85 break; 91 86 case SMB2_OP_SET_EOF: 92 - tmprc = SMB2_set_eof(xid, tcon, persistent_fid, volatile_fid, 93 - current->tgid, (__le64 *)data); 87 + tmprc = SMB2_set_eof(xid, tcon, fid.persistent_fid, 88 + fid.volatile_fid, current->tgid, 89 + (__le64 *)data); 94 90 break; 95 91 case SMB2_OP_SET_INFO: 96 - tmprc = SMB2_set_info(xid, tcon, persistent_fid, volatile_fid, 92 + tmprc = SMB2_set_info(xid, tcon, fid.persistent_fid, 93 + fid.volatile_fid, 97 94 (FILE_BASIC_INFO *)data); 98 95 break; 99 96 default: ··· 103 96 break; 104 97 } 105 98 106 - rc = SMB2_close(xid, tcon, persistent_fid, volatile_fid); 99 + rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 107 100 if (tmprc) 108 101 rc = tmprc; 109 102 kfree(utf16_path); ··· 136 129 return -ENOMEM; 137 130 138 131 rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path, 139 - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, 140 - smb2_data, SMB2_OP_QUERY_INFO); 132 + FILE_READ_ATTRIBUTES, FILE_OPEN, 0, smb2_data, 133 + SMB2_OP_QUERY_INFO); 141 134 if (rc) 142 135 goto out; 143 136 ··· 152 145 struct cifs_sb_info *cifs_sb) 153 146 { 154 147 return smb2_open_op_close(xid, tcon, cifs_sb, name, 155 - FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0, 148 + FILE_WRITE_ATTRIBUTES, FILE_CREATE, 156 149 CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR); 157 150 } 158 151 ··· 171 164 dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; 172 165 data.Attributes = cpu_to_le32(dosattrs); 173 166 tmprc = smb2_open_op_close(xid, tcon, cifs_sb, name, 174 - FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0, 167 + FILE_WRITE_ATTRIBUTES, FILE_CREATE, 175 168 CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO); 176 169 if (tmprc == 0) 177 170 cifs_i->cifsAttrs = dosattrs; ··· 182 175 struct cifs_sb_info *cifs_sb) 183 176 { 184 177 return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, 185 - 0, CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE, 178 + CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE, 186 179 NULL, SMB2_OP_DELETE); 187 180 } 188 181 ··· 191 184 struct cifs_sb_info *cifs_sb) 192 185 { 193 186 return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, 194 - 0, CREATE_DELETE_ON_CLOSE, NULL, 187 + CREATE_DELETE_ON_CLOSE, NULL, 195 188 SMB2_OP_DELETE); 196 189 } 197 190 ··· 210 203 } 211 204 212 205 rc = smb2_open_op_close(xid, tcon, cifs_sb, from_name, access, 213 - FILE_OPEN, 0, 0, smb2_to_name, command); 206 + FILE_OPEN, 0, smb2_to_name, command); 214 207 smb2_rename_path: 215 208 kfree(smb2_to_name); 216 209 return rc; ··· 241 234 { 242 235 __le64 eof = cpu_to_le64(size); 243 236 return smb2_open_op_close(xid, tcon, cifs_sb, full_path, 244 - FILE_WRITE_DATA, FILE_OPEN, 0, 0, &eof, 237 + FILE_WRITE_DATA, FILE_OPEN, 0, &eof, 245 238 SMB2_OP_SET_EOF); 246 239 } 247 240 ··· 257 250 if (IS_ERR(tlink)) 258 251 return PTR_ERR(tlink); 259 252 rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path, 260 - FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, 0, buf, 253 + FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf, 261 254 SMB2_OP_SET_INFO); 262 255 cifs_put_tlink(tlink); 263 256 return rc;
+36 -18
fs/cifs/smb2ops.c
··· 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 } ··· 450 443 __le16 *utf16_path; 451 444 int rc; 452 445 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 453 - __u64 persistent_fid, volatile_fid; 446 + struct cifs_open_parms oparms; 454 447 455 448 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); 456 449 if (!utf16_path) 457 450 return -ENOMEM; 458 451 459 - rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, 460 - FILE_READ_ATTRIBUTES | FILE_READ_DATA, FILE_OPEN, 0, 0, 461 - &oplock, NULL); 452 + oparms.tcon = tcon; 453 + oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA; 454 + oparms.disposition = FILE_OPEN; 455 + oparms.create_options = 0; 456 + oparms.fid = fid; 457 + oparms.reconnect = false; 458 + 459 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL); 462 460 kfree(utf16_path); 463 461 if (rc) { 464 462 cifs_dbg(VFS, "open dir failed\n"); ··· 472 460 473 461 srch_inf->entries_in_buffer = 0; 474 462 srch_inf->index_of_last_entry = 0; 475 - fid->persistent_fid = persistent_fid; 476 - fid->volatile_fid = volatile_fid; 477 463 478 - rc = SMB2_query_directory(xid, tcon, persistent_fid, volatile_fid, 0, 479 - srch_inf); 464 + rc = SMB2_query_directory(xid, tcon, fid->persistent_fid, 465 + fid->volatile_fid, 0, srch_inf); 480 466 if (rc) { 481 467 cifs_dbg(VFS, "query directory failed\n"); 482 - SMB2_close(xid, tcon, persistent_fid, volatile_fid); 468 + SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid); 483 469 } 484 470 return rc; 485 471 } ··· 538 528 struct kstatfs *buf) 539 529 { 540 530 int rc; 541 - u64 persistent_fid, volatile_fid; 542 531 __le16 srch_path = 0; /* Null - open root of share */ 543 532 u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 533 + struct cifs_open_parms oparms; 534 + struct cifs_fid fid; 544 535 545 - rc = SMB2_open(xid, tcon, &srch_path, &persistent_fid, &volatile_fid, 546 - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock, NULL); 536 + oparms.tcon = tcon; 537 + oparms.desired_access = FILE_READ_ATTRIBUTES; 538 + oparms.disposition = FILE_OPEN; 539 + oparms.create_options = 0; 540 + oparms.fid = &fid; 541 + oparms.reconnect = false; 542 + 543 + rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL); 547 544 if (rc) 548 545 return rc; 549 546 buf->f_type = SMB2_MAGIC_NUMBER; 550 - rc = SMB2_QFS_info(xid, tcon, persistent_fid, volatile_fid, buf); 551 - SMB2_close(xid, tcon, persistent_fid, volatile_fid); 547 + rc = SMB2_QFS_info(xid, tcon, fid.persistent_fid, fid.volatile_fid, 548 + buf); 549 + SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 552 550 return rc; 553 551 } 554 552
+158 -60
fs/cifs/smb2pdu.c
··· 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; ··· 924 877 return smb2_map_lease_to_oplock(lc->lcontext.LeaseState); 925 878 } 926 879 880 + static int 881 + add_lease_context(struct kvec *iov, unsigned int *num_iovec, __u8 *oplock) 882 + { 883 + struct smb2_create_req *req = iov[0].iov_base; 884 + unsigned int num = *num_iovec; 885 + 886 + iov[num].iov_base = create_lease_buf(oplock+1, *oplock); 887 + if (iov[num].iov_base == NULL) 888 + return -ENOMEM; 889 + iov[num].iov_len = sizeof(struct create_lease); 890 + req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE; 891 + if (!req->CreateContextsOffset) 892 + req->CreateContextsOffset = cpu_to_le32( 893 + sizeof(struct smb2_create_req) - 4 + 894 + iov[num - 1].iov_len); 895 + req->CreateContextsLength = cpu_to_le32( 896 + le32_to_cpu(req->CreateContextsLength) + 897 + sizeof(struct create_lease)); 898 + inc_rfc1001_len(&req->hdr, sizeof(struct create_lease)); 899 + *num_iovec = num + 1; 900 + return 0; 901 + } 902 + 903 + static int 904 + add_durable_context(struct kvec *iov, unsigned int *num_iovec, 905 + struct cifs_open_parms *oparms) 906 + { 907 + struct smb2_create_req *req = iov[0].iov_base; 908 + unsigned int num = *num_iovec; 909 + 910 + if (oparms->reconnect) { 911 + iov[num].iov_base = create_reconnect_durable_buf(oparms->fid); 912 + /* indicate that we don't need to relock the file */ 913 + oparms->reconnect = false; 914 + } else 915 + iov[num].iov_base = create_durable_buf(); 916 + if (iov[num].iov_base == NULL) 917 + return -ENOMEM; 918 + iov[num].iov_len = sizeof(struct create_durable); 919 + if (!req->CreateContextsOffset) 920 + req->CreateContextsOffset = 921 + cpu_to_le32(sizeof(struct smb2_create_req) - 4 + 922 + iov[1].iov_len); 923 + req->CreateContextsLength = 924 + cpu_to_le32(le32_to_cpu(req->CreateContextsLength) + 925 + sizeof(struct create_durable)); 926 + inc_rfc1001_len(&req->hdr, sizeof(struct create_durable)); 927 + *num_iovec = num + 1; 928 + return 0; 929 + } 930 + 927 931 int 928 - SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, 929 - u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access, 930 - __u32 create_disposition, __u32 file_attributes, __u32 create_options, 932 + SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, 931 933 __u8 *oplock, struct smb2_file_all_info *buf) 932 934 { 933 935 struct smb2_create_req *req; 934 936 struct smb2_create_rsp *rsp; 935 937 struct TCP_Server_Info *server; 938 + struct cifs_tcon *tcon = oparms->tcon; 936 939 struct cifs_ses *ses = tcon->ses; 937 - struct kvec iov[3]; 940 + struct kvec iov[4]; 938 941 int resp_buftype; 939 942 int uni_path_len; 940 943 __le16 *copy_path = NULL; 941 944 int copy_size; 942 945 int rc = 0; 943 - int num_iovecs = 2; 946 + unsigned int num_iovecs = 2; 947 + __u32 file_attributes = 0; 944 948 945 949 cifs_dbg(FYI, "create/open\n"); 946 950 ··· 1004 906 if (rc) 1005 907 return rc; 1006 908 909 + if (oparms->create_options & CREATE_OPTION_READONLY) 910 + file_attributes |= ATTR_READONLY; 911 + 1007 912 req->ImpersonationLevel = IL_IMPERSONATION; 1008 - req->DesiredAccess = cpu_to_le32(desired_access); 913 + req->DesiredAccess = cpu_to_le32(oparms->desired_access); 1009 914 /* File attributes ignored on open (used in create though) */ 1010 915 req->FileAttributes = cpu_to_le32(file_attributes); 1011 916 req->ShareAccess = FILE_SHARE_ALL_LE; 1012 - req->CreateDisposition = cpu_to_le32(create_disposition); 1013 - req->CreateOptions = cpu_to_le32(create_options); 917 + req->CreateDisposition = cpu_to_le32(oparms->disposition); 918 + req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK); 1014 919 uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; 1015 - req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) 1016 - - 8 /* pad */ - 4 /* do not count rfc1001 len field */); 920 + /* do not count rfc1001 len field */ 921 + req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4); 1017 922 1018 923 iov[0].iov_base = (char *)req; 1019 924 /* 4 for rfc1002 length field */ 1020 925 iov[0].iov_len = get_rfc1002_length(req) + 4; 1021 926 1022 927 /* MUST set path len (NameLength) to 0 opening root of share */ 1023 - if (uni_path_len >= 4) { 1024 - req->NameLength = cpu_to_le16(uni_path_len - 2); 1025 - /* -1 since last byte is buf[0] which is sent below (path) */ 1026 - iov[0].iov_len--; 1027 - if (uni_path_len % 8 != 0) { 1028 - copy_size = uni_path_len / 8 * 8; 1029 - if (copy_size < uni_path_len) 1030 - copy_size += 8; 928 + req->NameLength = cpu_to_le16(uni_path_len - 2); 929 + /* -1 since last byte is buf[0] which is sent below (path) */ 930 + iov[0].iov_len--; 931 + if (uni_path_len % 8 != 0) { 932 + copy_size = uni_path_len / 8 * 8; 933 + if (copy_size < uni_path_len) 934 + copy_size += 8; 1031 935 1032 - copy_path = kzalloc(copy_size, GFP_KERNEL); 1033 - if (!copy_path) 1034 - return -ENOMEM; 1035 - memcpy((char *)copy_path, (const char *)path, 1036 - uni_path_len); 1037 - uni_path_len = copy_size; 1038 - path = copy_path; 1039 - } 1040 - 1041 - iov[1].iov_len = uni_path_len; 1042 - iov[1].iov_base = path; 1043 - /* 1044 - * -1 since last byte is buf[0] which was counted in 1045 - * smb2_buf_len. 1046 - */ 1047 - inc_rfc1001_len(req, uni_path_len - 1); 1048 - } else { 1049 - iov[0].iov_len += 7; 1050 - req->hdr.smb2_buf_length = cpu_to_be32(be32_to_cpu( 1051 - req->hdr.smb2_buf_length) + 8 - 1); 1052 - num_iovecs = 1; 1053 - req->NameLength = 0; 936 + copy_path = kzalloc(copy_size, GFP_KERNEL); 937 + if (!copy_path) 938 + return -ENOMEM; 939 + memcpy((char *)copy_path, (const char *)path, 940 + uni_path_len); 941 + uni_path_len = copy_size; 942 + path = copy_path; 1054 943 } 944 + 945 + iov[1].iov_len = uni_path_len; 946 + iov[1].iov_base = path; 947 + /* -1 since last byte is buf[0] which was counted in smb2_buf_len */ 948 + inc_rfc1001_len(req, uni_path_len - 1); 1055 949 1056 950 if (!server->oplocks) 1057 951 *oplock = SMB2_OPLOCK_LEVEL_NONE; ··· 1052 962 *oplock == SMB2_OPLOCK_LEVEL_NONE) 1053 963 req->RequestedOplockLevel = *oplock; 1054 964 else { 1055 - iov[num_iovecs].iov_base = create_lease_buf(oplock+1, *oplock); 1056 - if (iov[num_iovecs].iov_base == NULL) { 965 + rc = add_lease_context(iov, &num_iovecs, oplock); 966 + if (rc) { 1057 967 cifs_small_buf_release(req); 1058 968 kfree(copy_path); 1059 - return -ENOMEM; 969 + return rc; 1060 970 } 1061 - iov[num_iovecs].iov_len = sizeof(struct create_lease); 1062 - req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE; 1063 - req->CreateContextsOffset = cpu_to_le32( 1064 - sizeof(struct smb2_create_req) - 4 - 8 + 1065 - iov[num_iovecs-1].iov_len); 1066 - req->CreateContextsLength = cpu_to_le32( 1067 - sizeof(struct create_lease)); 1068 - inc_rfc1001_len(&req->hdr, sizeof(struct create_lease)); 1069 - num_iovecs++; 971 + } 972 + 973 + if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) { 974 + /* need to set Next field of lease context if we request it */ 975 + if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) { 976 + struct create_context *ccontext = 977 + (struct create_context *)iov[num_iovecs-1].iov_base; 978 + ccontext->Next = 979 + cpu_to_le32(sizeof(struct create_lease)); 980 + } 981 + rc = add_durable_context(iov, &num_iovecs, oparms); 982 + if (rc) { 983 + cifs_small_buf_release(req); 984 + kfree(copy_path); 985 + kfree(iov[num_iovecs-1].iov_base); 986 + return rc; 987 + } 1070 988 } 1071 989 1072 990 rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); ··· 1085 987 goto creat_exit; 1086 988 } 1087 989 1088 - *persistent_fid = rsp->PersistentFileId; 1089 - *volatile_fid = rsp->VolatileFileId; 990 + oparms->fid->persistent_fid = rsp->PersistentFileId; 991 + oparms->fid->volatile_fid = rsp->VolatileFileId; 1090 992 1091 993 if (buf) { 1092 994 memcpy(buf, &rsp->CreationTime, 32);
+13 -1
fs/cifs/smb2pdu.h
··· 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 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 */
+6 -10
fs/cifs/smb2proto.h
··· 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); ··· 104 106 const char *tree, struct cifs_tcon *tcon, 105 107 const struct nls_table *); 106 108 extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon); 107 - extern int SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, 108 - __le16 *path, u64 *persistent_fid, u64 *volatile_fid, 109 - __u32 desired_access, __u32 create_disposition, 110 - __u32 file_attributes, __u32 create_options, 111 - __u8 *oplock, struct smb2_file_all_info *buf); 109 + extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, 110 + __le16 *path, __u8 *oplock, 111 + struct smb2_file_all_info *buf); 112 112 extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, 113 113 u64 persistent_fid, u64 volatile_fid, u32 opcode, 114 114 bool is_fsctl, char *in_data, u32 indatalen,
+89 -1
fs/cifs/smb2transport.c
··· 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 { ··· 123 52 memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); 124 53 memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); 125 54 55 + rc = smb2_crypto_shash_allocate(server); 56 + if (rc) { 57 + cifs_dbg(VFS, "%s: shah256 alloc failed\n", __func__); 58 + return rc; 59 + } 60 + 126 61 rc = crypto_shash_setkey(server->secmech.hmacsha256, 127 62 server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE); 128 63 if (rc) { ··· 138 61 139 62 rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash); 140 63 if (rc) { 141 - cifs_dbg(VFS, "%s: Could not init md5\n", __func__); 64 + cifs_dbg(VFS, "%s: Could not init sha256", __func__); 142 65 return rc; 143 66 } 144 67 ··· 205 128 206 129 memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); 207 130 memset(server->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE); 131 + 132 + rc = smb3_crypto_shash_allocate(server); 133 + if (rc) { 134 + cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__); 135 + goto smb3signkey_ret; 136 + } 208 137 209 138 rc = crypto_shash_setkey(server->secmech.hmacsha256, 210 139 server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE); ··· 293 210 return rc; 294 211 } 295 212 213 + /* 214 + * we already allocate sdesccmacaes when we init smb3 signing key, 215 + * so unlike smb2 case we do not have to check here if secmech are 216 + * initialized 217 + */ 296 218 rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash); 297 219 if (rc) { 298 220 cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);