Commit f1c410885288e0042099960ee9e0c260dfea4cfb
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
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 | } |
fs/cifs/cifsglob.h
... | ... | @@ -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 { |
fs/cifs/cifsproto.h
... | ... | @@ -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 *); |
fs/cifs/connect.c
... | ... | @@ -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)); |
fs/cifs/dir.c
... | ... | @@ -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; |
fs/cifs/file.c
... | ... | @@ -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); |
fs/cifs/inode.c
... | ... | @@ -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; |
fs/cifs/smb1ops.c
... | ... | @@ -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 |
fs/cifs/smb2file.c
... | ... | @@ -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) { |
fs/cifs/smb2inode.c
... | ... | @@ -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; |
fs/cifs/smb2ops.c
... | ... | @@ -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 |
fs/cifs/smb2pdu.c
... | ... | @@ -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); |
fs/cifs/smb2pdu.h
... | ... | @@ -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 */ |
fs/cifs/smb2proto.h
... | ... | @@ -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__); |