.. | .. |
---|
29 | 29 | #include "cifs_unicode.h" |
---|
30 | 30 | #include "smb2status.h" |
---|
31 | 31 | #include "smb2glob.h" |
---|
| 32 | +#include "nterr.h" |
---|
32 | 33 | |
---|
33 | 34 | static int |
---|
34 | 35 | check_smb2_hdr(struct smb2_sync_hdr *shdr, __u64 mid) |
---|
.. | .. |
---|
93 | 94 | /* SMB2_OPLOCK_BREAK */ cpu_to_le16(24) |
---|
94 | 95 | }; |
---|
95 | 96 | |
---|
| 97 | +#define SMB311_NEGPROT_BASE_SIZE (sizeof(struct smb2_sync_hdr) + sizeof(struct smb2_negotiate_rsp)) |
---|
| 98 | + |
---|
96 | 99 | static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len, |
---|
97 | 100 | __u32 non_ctxlen) |
---|
98 | 101 | { |
---|
.. | .. |
---|
108 | 111 | |
---|
109 | 112 | /* Make sure that negotiate contexts start after gss security blob */ |
---|
110 | 113 | nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset); |
---|
111 | | - if (nc_offset < non_ctxlen) { |
---|
112 | | - printk_once(KERN_WARNING "invalid negotiate context offset\n"); |
---|
| 114 | + if (nc_offset + 1 < non_ctxlen) { |
---|
| 115 | + pr_warn_once("Invalid negotiate context offset %d\n", nc_offset); |
---|
113 | 116 | return 0; |
---|
114 | | - } |
---|
115 | | - size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen; |
---|
| 117 | + } else if (nc_offset + 1 == non_ctxlen) { |
---|
| 118 | + cifs_dbg(FYI, "no SPNEGO security blob in negprot rsp\n"); |
---|
| 119 | + size_of_pad_before_neg_ctxts = 0; |
---|
| 120 | + } else if (non_ctxlen == SMB311_NEGPROT_BASE_SIZE) |
---|
| 121 | + /* has padding, but no SPNEGO blob */ |
---|
| 122 | + size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen + 1; |
---|
| 123 | + else |
---|
| 124 | + size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen; |
---|
116 | 125 | |
---|
117 | 126 | /* Verify that at least minimal negotiate contexts fit within frame */ |
---|
118 | 127 | if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) { |
---|
119 | | - printk_once(KERN_WARNING "negotiate context goes beyond end\n"); |
---|
| 128 | + pr_warn_once("negotiate context goes beyond end\n"); |
---|
120 | 129 | return 0; |
---|
121 | 130 | } |
---|
122 | 131 | |
---|
.. | .. |
---|
189 | 198 | return 1; |
---|
190 | 199 | |
---|
191 | 200 | if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) { |
---|
192 | | - cifs_dbg(VFS, "Illegal structure size %u\n", |
---|
| 201 | + cifs_dbg(VFS, "Invalid structure size %u\n", |
---|
193 | 202 | le16_to_cpu(shdr->StructureSize)); |
---|
194 | 203 | return 1; |
---|
195 | 204 | } |
---|
196 | 205 | |
---|
197 | 206 | command = le16_to_cpu(shdr->Command); |
---|
198 | 207 | if (command >= NUMBER_OF_SMB2_COMMANDS) { |
---|
199 | | - cifs_dbg(VFS, "Illegal SMB2 command %d\n", command); |
---|
| 208 | + cifs_dbg(VFS, "Invalid SMB2 command %d\n", command); |
---|
200 | 209 | return 1; |
---|
201 | 210 | } |
---|
202 | 211 | |
---|
.. | .. |
---|
204 | 213 | if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 || |
---|
205 | 214 | pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) { |
---|
206 | 215 | /* error packets have 9 byte structure size */ |
---|
207 | | - cifs_dbg(VFS, "Illegal response size %u for command %d\n", |
---|
| 216 | + cifs_dbg(VFS, "Invalid response size %u for command %d\n", |
---|
208 | 217 | le16_to_cpu(pdu->StructureSize2), command); |
---|
209 | 218 | return 1; |
---|
210 | 219 | } else if (command == SMB2_OPLOCK_BREAK_HE |
---|
.. | .. |
---|
212 | 221 | && (le16_to_cpu(pdu->StructureSize2) != 44) |
---|
213 | 222 | && (le16_to_cpu(pdu->StructureSize2) != 36)) { |
---|
214 | 223 | /* special case for SMB2.1 lease break message */ |
---|
215 | | - cifs_dbg(VFS, "Illegal response size %d for oplock break\n", |
---|
| 224 | + cifs_dbg(VFS, "Invalid response size %d for oplock break\n", |
---|
216 | 225 | le16_to_cpu(pdu->StructureSize2)); |
---|
217 | 226 | return 1; |
---|
218 | 227 | } |
---|
.. | .. |
---|
249 | 258 | * of junk. Other servers match RFC1001 len to actual |
---|
250 | 259 | * SMB2/SMB3 frame length (header + smb2 response specific data) |
---|
251 | 260 | * Some windows servers also pad up to 8 bytes when compounding. |
---|
252 | | - * If pad is longer than eight bytes, log the server behavior |
---|
253 | | - * (once), since may indicate a problem but allow it and continue |
---|
254 | | - * since the frame is parseable. |
---|
255 | 261 | */ |
---|
256 | | - if (clc_len < len) { |
---|
257 | | - pr_warn_once( |
---|
258 | | - "srv rsp padded more than expected. Length %d not %d for cmd:%d mid:%llu\n", |
---|
259 | | - len, clc_len, command, mid); |
---|
| 262 | + if (clc_len < len) |
---|
260 | 263 | return 0; |
---|
261 | | - } |
---|
| 264 | + |
---|
262 | 265 | pr_warn_once( |
---|
263 | 266 | "srv rsp too short, len %d not %d. cmd:%d mid:%llu\n", |
---|
264 | 267 | len, clc_len, command, mid); |
---|
.. | .. |
---|
359 | 362 | ((struct smb2_ioctl_rsp *)shdr)->OutputCount); |
---|
360 | 363 | break; |
---|
361 | 364 | case SMB2_CHANGE_NOTIFY: |
---|
| 365 | + *off = le16_to_cpu( |
---|
| 366 | + ((struct smb2_change_notify_rsp *)shdr)->OutputBufferOffset); |
---|
| 367 | + *len = le32_to_cpu( |
---|
| 368 | + ((struct smb2_change_notify_rsp *)shdr)->OutputBufferLength); |
---|
| 369 | + break; |
---|
362 | 370 | default: |
---|
363 | | - /* BB FIXME for unimplemented cases above */ |
---|
364 | | - cifs_dbg(VFS, "no length check for command\n"); |
---|
| 371 | + cifs_dbg(VFS, "no length check for command %d\n", le16_to_cpu(shdr->Command)); |
---|
365 | 372 | break; |
---|
366 | 373 | } |
---|
367 | 374 | |
---|
.. | .. |
---|
747 | 754 | { |
---|
748 | 755 | struct close_cancelled_open *cancelled = container_of(work, |
---|
749 | 756 | struct close_cancelled_open, work); |
---|
| 757 | + struct cifs_tcon *tcon = cancelled->tcon; |
---|
| 758 | + int rc; |
---|
750 | 759 | |
---|
751 | | - cifs_dbg(VFS, "Close unmatched open\n"); |
---|
| 760 | + if (cancelled->mid) |
---|
| 761 | + cifs_tcon_dbg(VFS, "Close unmatched open for MID:%llx\n", |
---|
| 762 | + cancelled->mid); |
---|
| 763 | + else |
---|
| 764 | + cifs_tcon_dbg(VFS, "Close interrupted close\n"); |
---|
752 | 765 | |
---|
753 | | - SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid, |
---|
754 | | - cancelled->fid.volatile_fid); |
---|
755 | | - cifs_put_tcon(cancelled->tcon); |
---|
| 766 | + rc = SMB2_close(0, tcon, cancelled->fid.persistent_fid, |
---|
| 767 | + cancelled->fid.volatile_fid); |
---|
| 768 | + if (rc) |
---|
| 769 | + cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc); |
---|
| 770 | + |
---|
| 771 | + cifs_put_tcon(tcon); |
---|
756 | 772 | kfree(cancelled); |
---|
757 | 773 | } |
---|
758 | 774 | |
---|
759 | | -/* Caller should already has an extra reference to @tcon */ |
---|
| 775 | +/* |
---|
| 776 | + * Caller should already has an extra reference to @tcon |
---|
| 777 | + * This function is used to queue work to close a handle to prevent leaks |
---|
| 778 | + * on the server. |
---|
| 779 | + * We handle two cases. If an open was interrupted after we sent the |
---|
| 780 | + * SMB2_CREATE to the server but before we processed the reply, and second |
---|
| 781 | + * if a close was interrupted before we sent the SMB2_CLOSE to the server. |
---|
| 782 | + */ |
---|
760 | 783 | static int |
---|
761 | | -__smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, |
---|
762 | | - __u64 volatile_fid) |
---|
| 784 | +__smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid, |
---|
| 785 | + __u64 persistent_fid, __u64 volatile_fid) |
---|
763 | 786 | { |
---|
764 | 787 | struct close_cancelled_open *cancelled; |
---|
765 | 788 | |
---|
.. | .. |
---|
770 | 793 | cancelled->fid.persistent_fid = persistent_fid; |
---|
771 | 794 | cancelled->fid.volatile_fid = volatile_fid; |
---|
772 | 795 | cancelled->tcon = tcon; |
---|
| 796 | + cancelled->cmd = cmd; |
---|
| 797 | + cancelled->mid = mid; |
---|
773 | 798 | INIT_WORK(&cancelled->work, smb2_cancelled_close_fid); |
---|
774 | 799 | WARN_ON(queue_work(cifsiod_wq, &cancelled->work) == false); |
---|
775 | 800 | |
---|
.. | .. |
---|
784 | 809 | |
---|
785 | 810 | cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count); |
---|
786 | 811 | spin_lock(&cifs_tcp_ses_lock); |
---|
| 812 | + if (tcon->tc_count <= 0) { |
---|
| 813 | + struct TCP_Server_Info *server = NULL; |
---|
| 814 | + |
---|
| 815 | + WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative"); |
---|
| 816 | + spin_unlock(&cifs_tcp_ses_lock); |
---|
| 817 | + |
---|
| 818 | + if (tcon->ses) |
---|
| 819 | + server = tcon->ses->server; |
---|
| 820 | + |
---|
| 821 | + cifs_server_dbg(FYI, "tid=%u: tcon is closing, skipping async close retry of fid %llu %llu\n", |
---|
| 822 | + tcon->tid, persistent_fid, volatile_fid); |
---|
| 823 | + |
---|
| 824 | + return 0; |
---|
| 825 | + } |
---|
787 | 826 | tcon->tc_count++; |
---|
788 | 827 | spin_unlock(&cifs_tcp_ses_lock); |
---|
789 | 828 | |
---|
790 | | - rc = __smb2_handle_cancelled_close(tcon, persistent_fid, volatile_fid); |
---|
| 829 | + rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0, |
---|
| 830 | + persistent_fid, volatile_fid); |
---|
791 | 831 | if (rc) |
---|
792 | 832 | cifs_put_tcon(tcon); |
---|
793 | 833 | |
---|
.. | .. |
---|
795 | 835 | } |
---|
796 | 836 | |
---|
797 | 837 | int |
---|
798 | | -smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) |
---|
| 838 | +smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server) |
---|
799 | 839 | { |
---|
800 | | - struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer; |
---|
801 | | - struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; |
---|
| 840 | + struct smb2_sync_hdr *sync_hdr = mid->resp_buf; |
---|
| 841 | + struct smb2_create_rsp *rsp = mid->resp_buf; |
---|
802 | 842 | struct cifs_tcon *tcon; |
---|
803 | 843 | int rc; |
---|
804 | 844 | |
---|
805 | | - if (sync_hdr->Command != SMB2_CREATE || |
---|
| 845 | + if ((mid->optype & CIFS_CP_CREATE_CLOSE_OP) || sync_hdr->Command != SMB2_CREATE || |
---|
806 | 846 | sync_hdr->Status != STATUS_SUCCESS) |
---|
807 | 847 | return 0; |
---|
808 | 848 | |
---|
.. | .. |
---|
811 | 851 | if (!tcon) |
---|
812 | 852 | return -ENOENT; |
---|
813 | 853 | |
---|
814 | | - rc = __smb2_handle_cancelled_close(tcon, rsp->PersistentFileId, |
---|
815 | | - rsp->VolatileFileId); |
---|
| 854 | + rc = __smb2_handle_cancelled_cmd(tcon, |
---|
| 855 | + le16_to_cpu(sync_hdr->Command), |
---|
| 856 | + le64_to_cpu(sync_hdr->MessageId), |
---|
| 857 | + rsp->PersistentFileId, |
---|
| 858 | + rsp->VolatileFileId); |
---|
816 | 859 | if (rc) |
---|
817 | 860 | cifs_put_tcon(tcon); |
---|
818 | 861 | |
---|
.. | .. |
---|
831 | 874 | int i, rc; |
---|
832 | 875 | struct sdesc *d; |
---|
833 | 876 | struct smb2_sync_hdr *hdr; |
---|
| 877 | + struct TCP_Server_Info *server = cifs_ses_server(ses); |
---|
834 | 878 | |
---|
835 | | - if (ses->server->tcpStatus == CifsGood) { |
---|
836 | | - /* skip non smb311 connections */ |
---|
837 | | - if (ses->server->dialect != SMB311_PROT_ID) |
---|
838 | | - return 0; |
---|
| 879 | + hdr = (struct smb2_sync_hdr *)iov[0].iov_base; |
---|
| 880 | + /* neg prot are always taken */ |
---|
| 881 | + if (hdr->Command == SMB2_NEGOTIATE) |
---|
| 882 | + goto ok; |
---|
839 | 883 | |
---|
840 | | - /* skip last sess setup response */ |
---|
841 | | - hdr = (struct smb2_sync_hdr *)iov[0].iov_base; |
---|
842 | | - if (hdr->Flags & SMB2_FLAGS_SIGNED) |
---|
843 | | - return 0; |
---|
844 | | - } |
---|
| 884 | + /* |
---|
| 885 | + * If we process a command which wasn't a negprot it means the |
---|
| 886 | + * neg prot was already done, so the server dialect was set |
---|
| 887 | + * and we can test it. Preauth requires 3.1.1 for now. |
---|
| 888 | + */ |
---|
| 889 | + if (server->dialect != SMB311_PROT_ID) |
---|
| 890 | + return 0; |
---|
845 | 891 | |
---|
846 | | - rc = smb311_crypto_shash_allocate(ses->server); |
---|
| 892 | + if (hdr->Command != SMB2_SESSION_SETUP) |
---|
| 893 | + return 0; |
---|
| 894 | + |
---|
| 895 | + /* skip last sess setup response */ |
---|
| 896 | + if ((hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) |
---|
| 897 | + && (hdr->Status == NT_STATUS_OK |
---|
| 898 | + || (hdr->Status != |
---|
| 899 | + cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)))) |
---|
| 900 | + return 0; |
---|
| 901 | + |
---|
| 902 | +ok: |
---|
| 903 | + rc = smb311_crypto_shash_allocate(server); |
---|
847 | 904 | if (rc) |
---|
848 | 905 | return rc; |
---|
849 | 906 | |
---|
850 | | - d = ses->server->secmech.sdescsha512; |
---|
| 907 | + d = server->secmech.sdescsha512; |
---|
851 | 908 | rc = crypto_shash_init(&d->shash); |
---|
852 | 909 | if (rc) { |
---|
853 | | - cifs_dbg(VFS, "%s: could not init sha512 shash\n", __func__); |
---|
| 910 | + cifs_dbg(VFS, "%s: Could not init sha512 shash\n", __func__); |
---|
854 | 911 | return rc; |
---|
855 | 912 | } |
---|
856 | 913 | |
---|
857 | 914 | rc = crypto_shash_update(&d->shash, ses->preauth_sha_hash, |
---|
858 | 915 | SMB2_PREAUTH_HASH_SIZE); |
---|
859 | 916 | if (rc) { |
---|
860 | | - cifs_dbg(VFS, "%s: could not update sha512 shash\n", __func__); |
---|
| 917 | + cifs_dbg(VFS, "%s: Could not update sha512 shash\n", __func__); |
---|
861 | 918 | return rc; |
---|
862 | 919 | } |
---|
863 | 920 | |
---|
.. | .. |
---|
865 | 922 | rc = crypto_shash_update(&d->shash, |
---|
866 | 923 | iov[i].iov_base, iov[i].iov_len); |
---|
867 | 924 | if (rc) { |
---|
868 | | - cifs_dbg(VFS, "%s: could not update sha512 shash\n", |
---|
| 925 | + cifs_dbg(VFS, "%s: Could not update sha512 shash\n", |
---|
869 | 926 | __func__); |
---|
870 | 927 | return rc; |
---|
871 | 928 | } |
---|
.. | .. |
---|
873 | 930 | |
---|
874 | 931 | rc = crypto_shash_final(&d->shash, ses->preauth_sha_hash); |
---|
875 | 932 | if (rc) { |
---|
876 | | - cifs_dbg(VFS, "%s: could not finalize sha512 shash\n", |
---|
| 933 | + cifs_dbg(VFS, "%s: Could not finalize sha512 shash\n", |
---|
877 | 934 | __func__); |
---|
878 | 935 | return rc; |
---|
879 | 936 | } |
---|