Blame view
fs/cifs/smb2misc.c
26.4 KB
093b2bdad CIFS: Make demult... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/* * fs/cifs/smb2misc.c * * Copyright (C) International Business Machines Corp., 2002,2011 * Etersoft, 2012 * Author(s): Steve French (sfrench@us.ibm.com) * Pavel Shilovsky (pshilovsky@samba.org) 2012 * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/ctype.h> #include "smb2pdu.h" #include "cifsglob.h" #include "cifsproto.h" #include "smb2proto.h" #include "cifs_debug.h" #include "cifs_unicode.h" #include "smb2status.h" |
31473fc4f CIFS: Separate SM... |
31 |
#include "smb2glob.h" |
d70e9fa55 cifs: try opening... |
32 |
#include "nterr.h" |
093b2bdad CIFS: Make demult... |
33 34 |
static int |
31473fc4f CIFS: Separate SM... |
35 |
check_smb2_hdr(struct smb2_sync_hdr *shdr, __u64 mid) |
093b2bdad CIFS: Make demult... |
36 |
{ |
31473fc4f CIFS: Separate SM... |
37 |
__u64 wire_mid = le64_to_cpu(shdr->MessageId); |
9235d0987 Convert MessageID... |
38 |
|
093b2bdad CIFS: Make demult... |
39 40 41 42 |
/* * Make sure that this really is an SMB, that it is a response, * and that the message ids match. */ |
31473fc4f CIFS: Separate SM... |
43 |
if ((shdr->ProtocolId == SMB2_PROTO_NUMBER) && |
9235d0987 Convert MessageID... |
44 |
(mid == wire_mid)) { |
31473fc4f CIFS: Separate SM... |
45 |
if (shdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) |
093b2bdad CIFS: Make demult... |
46 47 48 |
return 0; else { /* only one valid case where server sends us request */ |
31473fc4f CIFS: Separate SM... |
49 |
if (shdr->Command == SMB2_OPLOCK_BREAK) |
093b2bdad CIFS: Make demult... |
50 51 |
return 0; else |
f96637be0 [CIFS] cifs: Rena... |
52 53 |
cifs_dbg(VFS, "Received Request not response "); |
093b2bdad CIFS: Make demult... |
54 55 |
} } else { /* bad signature or mid */ |
31473fc4f CIFS: Separate SM... |
56 |
if (shdr->ProtocolId != SMB2_PROTO_NUMBER) |
f96637be0 [CIFS] cifs: Rena... |
57 58 |
cifs_dbg(VFS, "Bad protocol string signature header %x ", |
31473fc4f CIFS: Separate SM... |
59 |
le32_to_cpu(shdr->ProtocolId)); |
9235d0987 Convert MessageID... |
60 |
if (mid != wire_mid) |
f96637be0 [CIFS] cifs: Rena... |
61 62 |
cifs_dbg(VFS, "Mids do not match: %llu and %llu ", |
9235d0987 Convert MessageID... |
63 |
mid, wire_mid); |
093b2bdad CIFS: Make demult... |
64 |
} |
9235d0987 Convert MessageID... |
65 66 |
cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu ", wire_mid); |
093b2bdad CIFS: Make demult... |
67 68 69 70 71 72 73 74 75 76 77 |
return 1; } /* * The following table defines the expected "StructureSize" of SMB2 responses * in order by SMB2 command. This is similar to "wct" in SMB/CIFS responses. * * Note that commands are defined in smb2pdu.h in le16 but the array below is * indexed by command in host byte order */ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { |
bc09d141e fs/cifs: remove o... |
78 79 80 81 82 83 84 85 86 87 88 89 |
/* SMB2_NEGOTIATE */ cpu_to_le16(65), /* SMB2_SESSION_SETUP */ cpu_to_le16(9), /* SMB2_LOGOFF */ cpu_to_le16(4), /* SMB2_TREE_CONNECT */ cpu_to_le16(16), /* SMB2_TREE_DISCONNECT */ cpu_to_le16(4), /* SMB2_CREATE */ cpu_to_le16(89), /* SMB2_CLOSE */ cpu_to_le16(60), /* SMB2_FLUSH */ cpu_to_le16(4), /* SMB2_READ */ cpu_to_le16(17), /* SMB2_WRITE */ cpu_to_le16(17), /* SMB2_LOCK */ cpu_to_le16(4), /* SMB2_IOCTL */ cpu_to_le16(49), |
093b2bdad CIFS: Make demult... |
90 |
/* BB CHECK this ... not listed in documentation */ |
bc09d141e fs/cifs: remove o... |
91 92 93 94 95 96 |
/* SMB2_CANCEL */ cpu_to_le16(0), /* SMB2_ECHO */ cpu_to_le16(4), /* SMB2_QUERY_DIRECTORY */ cpu_to_le16(9), /* SMB2_CHANGE_NOTIFY */ cpu_to_le16(9), /* SMB2_QUERY_INFO */ cpu_to_le16(9), /* SMB2_SET_INFO */ cpu_to_le16(2), |
093b2bdad CIFS: Make demult... |
97 |
/* BB FIXME can also be 44 for lease break */ |
bc09d141e fs/cifs: remove o... |
98 |
/* SMB2_OPLOCK_BREAK */ cpu_to_le16(24) |
093b2bdad CIFS: Make demult... |
99 |
}; |
639fd3819 SMB3.1.1: remove ... |
100 |
#define SMB311_NEGPROT_BASE_SIZE (sizeof(struct smb2_sync_hdr) + sizeof(struct smb2_negotiate_rsp)) |
98170fb53 cifs: update smb2... |
101 |
static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len, |
1fc6ad2f1 cifs: remove head... |
102 |
__u32 non_ctxlen) |
136ff1b4b SMB3: Fix length ... |
103 104 105 106 107 108 109 110 111 112 113 114 115 |
{ __u16 neg_count; __u32 nc_offset, size_of_pad_before_neg_ctxts; struct smb2_negotiate_rsp *pneg_rsp = (struct smb2_negotiate_rsp *)hdr; /* Negotiate contexts are only valid for latest dialect SMB3.11 */ neg_count = le16_to_cpu(pneg_rsp->NegotiateContextCount); if ((neg_count == 0) || (pneg_rsp->DialectRevision != cpu_to_le16(SMB311_PROT_ID))) return 0; /* Make sure that negotiate contexts start after gss security blob */ nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset); |
639fd3819 SMB3.1.1: remove ... |
116 117 118 |
if (nc_offset + 1 < non_ctxlen) { pr_warn_once("Invalid negotiate context offset %d ", nc_offset); |
136ff1b4b SMB3: Fix length ... |
119 |
return 0; |
639fd3819 SMB3.1.1: remove ... |
120 121 122 123 124 125 126 127 128 |
} else if (nc_offset + 1 == non_ctxlen) { cifs_dbg(FYI, "no SPNEGO security blob in negprot rsp "); size_of_pad_before_neg_ctxts = 0; } else if (non_ctxlen == SMB311_NEGPROT_BASE_SIZE) /* has padding, but no SPNEGO blob */ size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen + 1; else size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen; |
136ff1b4b SMB3: Fix length ... |
129 130 131 |
/* Verify that at least minimal negotiate contexts fit within frame */ if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) { |
a0a3036b8 cifs: Standardize... |
132 133 |
pr_warn_once("negotiate context goes beyond end "); |
136ff1b4b SMB3: Fix length ... |
134 135 136 137 138 139 140 141 142 143 |
return 0; } cifs_dbg(FYI, "length of negcontexts %d pad %d ", len - nc_offset, size_of_pad_before_neg_ctxts); /* length of negcontexts including pad from end of sec blob to them */ return (len - nc_offset) + size_of_pad_before_neg_ctxts; } |
136ff1b4b SMB3: Fix length ... |
144 |
|
093b2bdad CIFS: Make demult... |
145 |
int |
98170fb53 cifs: update smb2... |
146 |
smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) |
093b2bdad CIFS: Make demult... |
147 |
{ |
1fc6ad2f1 cifs: remove head... |
148 |
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; |
98170fb53 cifs: update smb2... |
149 |
struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr; |
373512ec5 Prepare for encry... |
150 |
__u64 mid; |
093b2bdad CIFS: Make demult... |
151 152 |
__u32 clc_len; /* calculated length */ int command; |
98170fb53 cifs: update smb2... |
153 154 |
int pdu_size = sizeof(struct smb2_sync_pdu); int hdr_size = sizeof(struct smb2_sync_hdr); |
093b2bdad CIFS: Make demult... |
155 156 157 158 159 |
/* * Add function to do table lookup of StructureSize by command * ie Validate the wct via smb2_struct_sizes table above */ |
31473fc4f CIFS: Separate SM... |
160 |
if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { |
373512ec5 Prepare for encry... |
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
struct smb2_transform_hdr *thdr = (struct smb2_transform_hdr *)buf; struct cifs_ses *ses = NULL; struct list_head *tmp; /* decrypt frame now that it is completely read in */ spin_lock(&cifs_tcp_ses_lock); list_for_each(tmp, &srvr->smb_ses_list) { ses = list_entry(tmp, struct cifs_ses, smb_ses_list); if (ses->Suid == thdr->SessionId) break; ses = NULL; } spin_unlock(&cifs_tcp_ses_lock); if (ses == NULL) { cifs_dbg(VFS, "no decryption - session id not found "); return 1; } } |
31473fc4f CIFS: Separate SM... |
182 |
mid = le64_to_cpu(shdr->MessageId); |
98170fb53 cifs: update smb2... |
183 184 |
if (len < pdu_size) { if ((len >= hdr_size) |
31473fc4f CIFS: Separate SM... |
185 |
&& (shdr->Status != 0)) { |
093b2bdad CIFS: Make demult... |
186 187 188 189 190 191 192 |
pdu->StructureSize2 = 0; /* * As with SMB/CIFS, on some error cases servers may * not return wct properly */ return 0; } else { |
f96637be0 [CIFS] cifs: Rena... |
193 194 |
cifs_dbg(VFS, "Length less than SMB header size "); |
093b2bdad CIFS: Make demult... |
195 196 197 |
} return 1; } |
1fc6ad2f1 cifs: remove head... |
198 |
if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE) { |
f96637be0 [CIFS] cifs: Rena... |
199 200 201 |
cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu ", mid); |
093b2bdad CIFS: Make demult... |
202 203 |
return 1; } |
31473fc4f CIFS: Separate SM... |
204 |
if (check_smb2_hdr(shdr, mid)) |
093b2bdad CIFS: Make demult... |
205 |
return 1; |
31473fc4f CIFS: Separate SM... |
206 |
if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) { |
a0a3036b8 cifs: Standardize... |
207 208 |
cifs_dbg(VFS, "Invalid structure size %u ", |
31473fc4f CIFS: Separate SM... |
209 |
le16_to_cpu(shdr->StructureSize)); |
093b2bdad CIFS: Make demult... |
210 211 |
return 1; } |
31473fc4f CIFS: Separate SM... |
212 |
command = le16_to_cpu(shdr->Command); |
093b2bdad CIFS: Make demult... |
213 |
if (command >= NUMBER_OF_SMB2_COMMANDS) { |
a0a3036b8 cifs: Standardize... |
214 215 |
cifs_dbg(VFS, "Invalid SMB2 command %d ", command); |
093b2bdad CIFS: Make demult... |
216 217 218 219 |
return 1; } if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) { |
31473fc4f CIFS: Separate SM... |
220 |
if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 || |
983c88a49 CIFS: Add oplock ... |
221 |
pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) { |
093b2bdad CIFS: Make demult... |
222 |
/* error packets have 9 byte structure size */ |
a0a3036b8 cifs: Standardize... |
223 224 |
cifs_dbg(VFS, "Invalid response size %u for command %d ", |
f96637be0 [CIFS] cifs: Rena... |
225 |
le16_to_cpu(pdu->StructureSize2), command); |
093b2bdad CIFS: Make demult... |
226 |
return 1; |
31473fc4f CIFS: Separate SM... |
227 228 |
} else if (command == SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0) |
0822f5142 CIFS: Add SMB2.1 ... |
229 230 231 |
&& (le16_to_cpu(pdu->StructureSize2) != 44) && (le16_to_cpu(pdu->StructureSize2) != 36)) { /* special case for SMB2.1 lease break message */ |
a0a3036b8 cifs: Standardize... |
232 233 |
cifs_dbg(VFS, "Invalid response size %d for oplock break ", |
f96637be0 [CIFS] cifs: Rena... |
234 |
le16_to_cpu(pdu->StructureSize2)); |
0822f5142 CIFS: Add SMB2.1 ... |
235 |
return 1; |
093b2bdad CIFS: Make demult... |
236 237 |
} } |
98170fb53 cifs: update smb2... |
238 |
clc_len = smb2_calc_size(buf, srvr); |
093b2bdad CIFS: Make demult... |
239 |
|
136ff1b4b SMB3: Fix length ... |
240 |
if (shdr->Command == SMB2_NEGOTIATE) |
1fc6ad2f1 cifs: remove head... |
241 |
clc_len += get_neg_ctxt_len(shdr, len, clc_len); |
0fdfef9aa smb3: simplify co... |
242 |
|
98170fb53 cifs: update smb2... |
243 244 245 246 |
if (len != clc_len) { cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu ", clc_len, len, mid); |
b42bf8882 CIFS: Implement f... |
247 248 |
/* create failed on symlink */ if (command == SMB2_CREATE_HE && |
31473fc4f CIFS: Separate SM... |
249 |
shdr->Status == STATUS_STOPPED_ON_SYMLINK) |
b42bf8882 CIFS: Implement f... |
250 |
return 0; |
983c88a49 CIFS: Add oplock ... |
251 |
/* Windows 7 server returns 24 bytes more */ |
98170fb53 cifs: update smb2... |
252 |
if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) |
983c88a49 CIFS: Add oplock ... |
253 |
return 0; |
754789a1c [CIFS] Workaround... |
254 |
/* server can return one byte more due to implied bcc[0] */ |
98170fb53 cifs: update smb2... |
255 |
if (clc_len == len + 1) |
741128608 CIFS: Fix log mes... |
256 |
return 0; |
754789a1c [CIFS] Workaround... |
257 258 |
/* |
e6c47dd0d cifs: check if SM... |
259 260 261 262 263 264 265 |
* Some windows servers (win2016) will pad also the final * PDU in a compound to 8 bytes. */ if (((clc_len + 7) & ~7) == len) return 0; /* |
754789a1c [CIFS] Workaround... |
266 267 268 |
* MacOS server pads after SMB2.1 write response with 3 bytes * of junk. Other servers match RFC1001 len to actual * SMB2/SMB3 frame length (header + smb2 response specific data) |
25f257351 smb3: minor debug... |
269 |
* Some windows servers also pad up to 8 bytes when compounding. |
754789a1c [CIFS] Workaround... |
270 |
*/ |
037d05072 smb3: remove conf... |
271 |
if (clc_len < len) |
754789a1c [CIFS] Workaround... |
272 |
return 0; |
037d05072 smb3: remove conf... |
273 |
|
25f257351 smb3: minor debug... |
274 275 276 277 |
pr_warn_once( "srv rsp too short, len %d not %d. cmd:%d mid:%llu ", len, clc_len, command, mid); |
754789a1c [CIFS] Workaround... |
278 |
|
093b2bdad CIFS: Make demult... |
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
return 1; } return 0; } /* * The size of the variable area depends on the offset and length fields * located in different fields for various SMB2 responses. SMB2 responses * with no variable length info, show an offset of zero for the offset field. */ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = { /* SMB2_NEGOTIATE */ true, /* SMB2_SESSION_SETUP */ true, /* SMB2_LOGOFF */ false, /* SMB2_TREE_CONNECT */ false, /* SMB2_TREE_DISCONNECT */ false, /* SMB2_CREATE */ true, /* SMB2_CLOSE */ false, /* SMB2_FLUSH */ false, /* SMB2_READ */ true, /* SMB2_WRITE */ false, /* SMB2_LOCK */ false, /* SMB2_IOCTL */ true, /* SMB2_CANCEL */ false, /* BB CHECK this not listed in documentation */ /* SMB2_ECHO */ false, /* SMB2_QUERY_DIRECTORY */ true, /* SMB2_CHANGE_NOTIFY */ true, /* SMB2_QUERY_INFO */ true, /* SMB2_SET_INFO */ false, /* SMB2_OPLOCK_BREAK */ false }; /* * Returns the pointer to the beginning of the data area. Length of the data * area and the offset to it (from the beginning of the smb are also returned. */ |
ec2e4523f CIFS: Add capabil... |
315 |
char * |
e4dc31fe9 cifs: change smb2... |
316 |
smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr) |
093b2bdad CIFS: Make demult... |
317 318 319 320 321 |
{ *off = 0; *len = 0; /* error responses do not have data area */ |
31473fc4f CIFS: Separate SM... |
322 |
if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED && |
e4dc31fe9 cifs: change smb2... |
323 |
(((struct smb2_err_rsp *)shdr)->StructureSize) == |
093b2bdad CIFS: Make demult... |
324 325 326 327 328 329 330 331 |
SMB2_ERROR_STRUCTURE_SIZE2) return NULL; /* * Following commands have data areas so we have to get the location * of the data buffer offset and data buffer length for the particular * command. */ |
31473fc4f CIFS: Separate SM... |
332 |
switch (shdr->Command) { |
093b2bdad CIFS: Make demult... |
333 |
case SMB2_NEGOTIATE: |
ec2e4523f CIFS: Add capabil... |
334 |
*off = le16_to_cpu( |
e4dc31fe9 cifs: change smb2... |
335 |
((struct smb2_negotiate_rsp *)shdr)->SecurityBufferOffset); |
ec2e4523f CIFS: Add capabil... |
336 |
*len = le16_to_cpu( |
e4dc31fe9 cifs: change smb2... |
337 |
((struct smb2_negotiate_rsp *)shdr)->SecurityBufferLength); |
ec2e4523f CIFS: Add capabil... |
338 |
break; |
093b2bdad CIFS: Make demult... |
339 |
case SMB2_SESSION_SETUP: |
5478f9ba9 CIFS: Add session... |
340 |
*off = le16_to_cpu( |
e4dc31fe9 cifs: change smb2... |
341 |
((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset); |
5478f9ba9 CIFS: Add session... |
342 |
*len = le16_to_cpu( |
e4dc31fe9 cifs: change smb2... |
343 |
((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength); |
5478f9ba9 CIFS: Add session... |
344 |
break; |
093b2bdad CIFS: Make demult... |
345 |
case SMB2_CREATE: |
2503a0dba CIFS: Add SMB2 su... |
346 |
*off = le32_to_cpu( |
e4dc31fe9 cifs: change smb2... |
347 |
((struct smb2_create_rsp *)shdr)->CreateContextsOffset); |
2503a0dba CIFS: Add SMB2 su... |
348 |
*len = le32_to_cpu( |
e4dc31fe9 cifs: change smb2... |
349 |
((struct smb2_create_rsp *)shdr)->CreateContextsLength); |
2503a0dba CIFS: Add SMB2 su... |
350 |
break; |
093b2bdad CIFS: Make demult... |
351 |
case SMB2_QUERY_INFO: |
be4cb9e3d CIFS: Query SMB2 ... |
352 |
*off = le16_to_cpu( |
e4dc31fe9 cifs: change smb2... |
353 |
((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset); |
be4cb9e3d CIFS: Query SMB2 ... |
354 |
*len = le32_to_cpu( |
e4dc31fe9 cifs: change smb2... |
355 |
((struct smb2_query_info_rsp *)shdr)->OutputBufferLength); |
be4cb9e3d CIFS: Query SMB2 ... |
356 357 |
break; case SMB2_READ: |
e4dc31fe9 cifs: change smb2... |
358 359 360 |
/* TODO: is this a bug ? */ *off = ((struct smb2_read_rsp *)shdr)->DataOffset; *len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength); |
09a4707e7 CIFS: Add SMB2 su... |
361 |
break; |
093b2bdad CIFS: Make demult... |
362 |
case SMB2_QUERY_DIRECTORY: |
d324f08d6 CIFS: Add readdir... |
363 |
*off = le16_to_cpu( |
e4dc31fe9 cifs: change smb2... |
364 |
((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset); |
d324f08d6 CIFS: Add readdir... |
365 |
*len = le32_to_cpu( |
e4dc31fe9 cifs: change smb2... |
366 |
((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength); |
d324f08d6 CIFS: Add readdir... |
367 |
break; |
093b2bdad CIFS: Make demult... |
368 |
case SMB2_IOCTL: |
4a72dafa1 SMB2 FSCTL and IO... |
369 |
*off = le32_to_cpu( |
e4dc31fe9 cifs: change smb2... |
370 371 372 |
((struct smb2_ioctl_rsp *)shdr)->OutputOffset); *len = le32_to_cpu( ((struct smb2_ioctl_rsp *)shdr)->OutputCount); |
4a72dafa1 SMB2 FSCTL and IO... |
373 |
break; |
093b2bdad CIFS: Make demult... |
374 |
case SMB2_CHANGE_NOTIFY: |
8668115cf smb3: fix unneede... |
375 376 377 378 379 |
*off = le16_to_cpu( ((struct smb2_change_notify_rsp *)shdr)->OutputBufferOffset); *len = le32_to_cpu( ((struct smb2_change_notify_rsp *)shdr)->OutputBufferLength); break; |
093b2bdad CIFS: Make demult... |
380 |
default: |
8668115cf smb3: fix unneede... |
381 382 |
cifs_dbg(VFS, "no length check for command %d ", le16_to_cpu(shdr->Command)); |
093b2bdad CIFS: Make demult... |
383 384 385 386 387 388 389 390 |
break; } /* * Invalid length or offset probably means data area is invalid, but * we have little choice but to ignore the data area in this case. */ if (*off > 4096) { |
f96637be0 [CIFS] cifs: Rena... |
391 392 |
cifs_dbg(VFS, "offset %d too large, data area ignored ", *off); |
093b2bdad CIFS: Make demult... |
393 394 395 |
*len = 0; *off = 0; } else if (*off < 0) { |
f96637be0 [CIFS] cifs: Rena... |
396 397 398 |
cifs_dbg(VFS, "negative offset %d to data invalid ignore data area ", *off); |
093b2bdad CIFS: Make demult... |
399 400 401 |
*off = 0; *len = 0; } else if (*len < 0) { |
f96637be0 [CIFS] cifs: Rena... |
402 403 404 |
cifs_dbg(VFS, "negative data length %d invalid, data area ignored ", *len); |
093b2bdad CIFS: Make demult... |
405 406 |
*len = 0; } else if (*len > 128 * 1024) { |
f96637be0 [CIFS] cifs: Rena... |
407 408 |
cifs_dbg(VFS, "data area larger than 128K: %d ", *len); |
093b2bdad CIFS: Make demult... |
409 410 411 412 413 |
*len = 0; } /* return pointer to beginning of data area, ie offset from SMB start */ if ((*off != 0) && (*len != 0)) |
31473fc4f CIFS: Separate SM... |
414 |
return (char *)shdr + *off; |
093b2bdad CIFS: Make demult... |
415 416 417 418 419 420 421 422 423 |
else return NULL; } /* * Calculate the size of the SMB message based on the fixed header * portion, the number of word parameters and the data portion of the message. */ unsigned int |
9ec672bd1 cifs: update calc... |
424 |
smb2_calc_size(void *buf, struct TCP_Server_Info *srvr) |
093b2bdad CIFS: Make demult... |
425 |
{ |
84f0cbfba cifs: update smb2... |
426 427 |
struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf; struct smb2_sync_hdr *shdr = &pdu->sync_hdr; |
093b2bdad CIFS: Make demult... |
428 429 430 |
int offset; /* the offset from the beginning of SMB to data area */ int data_length; /* the length of the variable length data area */ /* Structure Size has already been checked to make sure it is 64 */ |
1fc6ad2f1 cifs: remove head... |
431 |
int len = le16_to_cpu(shdr->StructureSize); |
093b2bdad CIFS: Make demult... |
432 433 434 435 436 437 |
/* * StructureSize2, ie length of fixed parameter area has already * been checked to make sure it is the correct length. */ len += le16_to_cpu(pdu->StructureSize2); |
31473fc4f CIFS: Separate SM... |
438 |
if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false) |
093b2bdad CIFS: Make demult... |
439 |
goto calc_size_exit; |
e4dc31fe9 cifs: change smb2... |
440 |
smb2_get_data_area_len(&offset, &data_length, shdr); |
f96637be0 [CIFS] cifs: Rena... |
441 442 |
cifs_dbg(FYI, "SMB2 data length %d offset %d ", data_length, offset); |
093b2bdad CIFS: Make demult... |
443 444 445 446 447 448 |
if (data_length > 0) { /* * Check to make sure that data area begins after fixed area, * Note that last byte of the fixed area is part of data area * for some commands, typically those with odd StructureSize, |
84f0cbfba cifs: update smb2... |
449 |
* so we must add one to the calculation. |
093b2bdad CIFS: Make demult... |
450 |
*/ |
1fc6ad2f1 cifs: remove head... |
451 452 453 454 |
if (offset + 1 < len) { cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d ", offset + 1, len); |
093b2bdad CIFS: Make demult... |
455 456 |
data_length = 0; } else { |
1fc6ad2f1 cifs: remove head... |
457 |
len = offset + data_length; |
093b2bdad CIFS: Make demult... |
458 459 460 |
} } calc_size_exit: |
f96637be0 [CIFS] cifs: Rena... |
461 462 |
cifs_dbg(FYI, "SMB2 len %d ", len); |
093b2bdad CIFS: Make demult... |
463 464 |
return len; } |
2503a0dba CIFS: Add SMB2 su... |
465 466 467 468 469 470 471 472 |
/* Note: caller must free return buffer */ __le16 * cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb) { int len; const char *start_of_path; __le16 *to; |
a4153cb1d Allow conversion ... |
473 474 475 476 477 478 479 480 |
int map_type; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR) map_type = SFM_MAP_UNI_RSVD; else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) map_type = SFU_MAP_UNI_RSVD; else map_type = NO_MAP_UNI_RSVD; |
2503a0dba CIFS: Add SMB2 su... |
481 482 483 484 |
/* Windows doesn't allow paths beginning with \ */ if (from[0] == '\\') start_of_path = from + 1; |
0fdfef9aa smb3: simplify co... |
485 |
|
ce558b0e1 smb3: Add posix c... |
486 |
/* SMB311 POSIX extensions paths do not include leading slash */ |
8ddecf5fd CIFS: Fix NULL pt... |
487 |
else if (cifs_sb_master_tlink(cifs_sb) && |
d819d298c smb3: fix corrupt... |
488 489 |
cifs_sb_master_tcon(cifs_sb)->posix_extensions && (from[0] == '/')) { |
ce558b0e1 smb3: Add posix c... |
490 |
start_of_path = from + 1; |
0fdfef9aa smb3: simplify co... |
491 |
} else |
2503a0dba CIFS: Add SMB2 su... |
492 |
start_of_path = from; |
ce558b0e1 smb3: Add posix c... |
493 |
|
2503a0dba CIFS: Add SMB2 su... |
494 |
to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len, |
a4153cb1d Allow conversion ... |
495 |
cifs_sb->local_nls, map_type); |
2503a0dba CIFS: Add SMB2 su... |
496 497 |
return to; } |
983c88a49 CIFS: Add oplock ... |
498 |
|
0822f5142 CIFS: Add SMB2.1 ... |
499 500 501 |
__le32 smb2_get_lease_state(struct cifsInodeInfo *cinode) { |
53ef1016f CIFS: Store lease... |
502 |
__le32 lease = 0; |
0822f5142 CIFS: Add SMB2.1 ... |
503 |
|
53ef1016f CIFS: Store lease... |
504 505 506 507 508 509 510 |
if (CIFS_CACHE_WRITE(cinode)) lease |= SMB2_LEASE_WRITE_CACHING; if (CIFS_CACHE_HANDLE(cinode)) lease |= SMB2_LEASE_HANDLE_CACHING; if (CIFS_CACHE_READ(cinode)) lease |= SMB2_LEASE_READ_CACHING; return lease; |
0822f5142 CIFS: Add SMB2.1 ... |
511 |
} |
233839b1d CIFS: Fix fast le... |
512 513 514 515 516 517 518 519 520 521 522 523 |
struct smb2_lease_break_work { struct work_struct lease_break; struct tcon_link *tlink; __u8 lease_key[16]; __le32 lease_state; }; static void cifs_ses_oplock_break(struct work_struct *work) { struct smb2_lease_break_work *lw = container_of(work, struct smb2_lease_break_work, lease_break); |
a93864d93 cifs: add lease t... |
524 |
int rc = 0; |
233839b1d CIFS: Fix fast le... |
525 526 527 |
rc = SMB2_lease_break(0, tlink_tcon(lw->tlink), lw->lease_key, lw->lease_state); |
a93864d93 cifs: add lease t... |
528 |
|
f96637be0 [CIFS] cifs: Rena... |
529 530 |
cifs_dbg(FYI, "Lease release rc %d ", rc); |
233839b1d CIFS: Fix fast le... |
531 532 533 |
cifs_put_tlink(lw->tlink); kfree(lw); } |
baf57b56d cifs: Fix leak wh... |
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 |
static void smb2_queue_pending_open_break(struct tcon_link *tlink, __u8 *lease_key, __le32 new_lease_state) { struct smb2_lease_break_work *lw; lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL); if (!lw) { cifs_put_tlink(tlink); return; } INIT_WORK(&lw->lease_break, cifs_ses_oplock_break); lw->tlink = tlink; lw->lease_state = new_lease_state; memcpy(lw->lease_key, lease_key, SMB2_LEASE_KEY_SIZE); queue_work(cifsiod_wq, &lw->lease_break); } |
0822f5142 CIFS: Add SMB2.1 ... |
552 |
static bool |
baf57b56d cifs: Fix leak wh... |
553 |
smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp) |
933d4b365 CIFS: Fix missing... |
554 |
{ |
933d4b365 CIFS: Fix missing... |
555 556 557 |
__u8 lease_state; struct list_head *tmp; struct cifsFileInfo *cfile; |
933d4b365 CIFS: Fix missing... |
558 559 560 |
struct cifsInodeInfo *cinode; int ack_req = le32_to_cpu(rsp->Flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED); |
53ef1016f CIFS: Store lease... |
561 |
lease_state = le32_to_cpu(rsp->NewLeaseState); |
933d4b365 CIFS: Fix missing... |
562 563 564 |
list_for_each(tmp, &tcon->openFileList) { cfile = list_entry(tmp, struct cifsFileInfo, tlist); |
2b0143b5c VFS: normal files... |
565 |
cinode = CIFS_I(d_inode(cfile->dentry)); |
933d4b365 CIFS: Fix missing... |
566 567 568 569 570 571 572 |
if (memcmp(cinode->lease_key, rsp->LeaseKey, SMB2_LEASE_KEY_SIZE)) continue; cifs_dbg(FYI, "found in the open list "); |
59b04c5df [CIFS] Fix incorr... |
573 574 |
cifs_dbg(FYI, "lease key match, lease break 0x%x ", |
9bd454083 CIFS: Properly pr... |
575 |
lease_state); |
933d4b365 CIFS: Fix missing... |
576 |
|
933d4b365 CIFS: Fix missing... |
577 578 579 580 |
if (ack_req) cfile->oplock_break_cancelled = false; else cfile->oplock_break_cancelled = true; |
7b9b9edb4 CIFS: Do not rese... |
581 |
set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags); |
9bd454083 CIFS: Properly pr... |
582 583 |
cfile->oplock_epoch = le16_to_cpu(rsp->Epoch); cfile->oplock_level = lease_state; |
7b9b9edb4 CIFS: Do not rese... |
584 |
|
b98749cac CIFS: keep FileIn... |
585 |
cifs_queue_oplock_break(cfile); |
933d4b365 CIFS: Fix missing... |
586 587 |
return true; } |
baf57b56d cifs: Fix leak wh... |
588 589 590 591 592 593 594 595 596 597 598 599 |
return false; } static struct cifs_pending_open * smb2_tcon_find_pending_open_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp) { __u8 lease_state = le32_to_cpu(rsp->NewLeaseState); int ack_req = le32_to_cpu(rsp->Flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED); struct cifs_pending_open *open; struct cifs_pending_open *found = NULL; |
933d4b365 CIFS: Fix missing... |
600 601 602 603 604 605 |
list_for_each_entry(open, &tcon->pending_opens, olist) { if (memcmp(open->lease_key, rsp->LeaseKey, SMB2_LEASE_KEY_SIZE)) continue; if (!found && ack_req) { |
baf57b56d cifs: Fix leak wh... |
606 |
found = open; |
933d4b365 CIFS: Fix missing... |
607 608 609 610 |
} cifs_dbg(FYI, "found in the pending open list "); |
59b04c5df [CIFS] Fix incorr... |
611 612 |
cifs_dbg(FYI, "lease key match, lease break 0x%x ", |
9bd454083 CIFS: Properly pr... |
613 |
lease_state); |
933d4b365 CIFS: Fix missing... |
614 615 616 |
open->oplock = lease_state; } |
a93864d93 cifs: add lease t... |
617 |
|
933d4b365 CIFS: Fix missing... |
618 619 620 621 622 |
return found; } static bool smb2_is_valid_lease_break(char *buffer) |
0822f5142 CIFS: Add SMB2.1 ... |
623 624 625 |
{ struct smb2_lease_break *rsp = (struct smb2_lease_break *)buffer; struct list_head *tmp, *tmp1, *tmp2; |
933d4b365 CIFS: Fix missing... |
626 |
struct TCP_Server_Info *server; |
0822f5142 CIFS: Add SMB2.1 ... |
627 628 |
struct cifs_ses *ses; struct cifs_tcon *tcon; |
baf57b56d cifs: Fix leak wh... |
629 |
struct cifs_pending_open *open; |
0822f5142 CIFS: Add SMB2.1 ... |
630 |
|
f96637be0 [CIFS] cifs: Rena... |
631 632 |
cifs_dbg(FYI, "Checking for lease break "); |
0822f5142 CIFS: Add SMB2.1 ... |
633 634 635 |
/* look up tcon based on tid & uid */ spin_lock(&cifs_tcp_ses_lock); |
933d4b365 CIFS: Fix missing... |
636 637 |
list_for_each(tmp, &cifs_tcp_ses_list) { server = list_entry(tmp, struct TCP_Server_Info, tcp_ses_list); |
0822f5142 CIFS: Add SMB2.1 ... |
638 |
|
933d4b365 CIFS: Fix missing... |
639 640 |
list_for_each(tmp1, &server->smb_ses_list) { ses = list_entry(tmp1, struct cifs_ses, smb_ses_list); |
0822f5142 CIFS: Add SMB2.1 ... |
641 |
|
933d4b365 CIFS: Fix missing... |
642 643 644 |
list_for_each(tmp2, &ses->tcon_list) { tcon = list_entry(tmp2, struct cifs_tcon, tcon_list); |
3afca265b Clarify locking o... |
645 |
spin_lock(&tcon->open_file_lock); |
933d4b365 CIFS: Fix missing... |
646 647 |
cifs_stats_inc( &tcon->stats.cifs_stats.num_oplock_brks); |
baf57b56d cifs: Fix leak wh... |
648 |
if (smb2_tcon_has_lease(tcon, rsp)) { |
3afca265b Clarify locking o... |
649 |
spin_unlock(&tcon->open_file_lock); |
933d4b365 CIFS: Fix missing... |
650 651 |
spin_unlock(&cifs_tcp_ses_lock); return true; |
233839b1d CIFS: Fix fast le... |
652 |
} |
baf57b56d cifs: Fix leak wh... |
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 |
open = smb2_tcon_find_pending_open_lease(tcon, rsp); if (open) { __u8 lease_key[SMB2_LEASE_KEY_SIZE]; struct tcon_link *tlink; tlink = cifs_get_tlink(open->tlink); memcpy(lease_key, open->lease_key, SMB2_LEASE_KEY_SIZE); spin_unlock(&tcon->open_file_lock); spin_unlock(&cifs_tcp_ses_lock); smb2_queue_pending_open_break(tlink, lease_key, rsp->NewLeaseState); return true; } |
3afca265b Clarify locking o... |
669 |
spin_unlock(&tcon->open_file_lock); |
a93864d93 cifs: add lease t... |
670 671 672 673 674 675 676 677 678 679 680 681 |
if (tcon->crfid.is_valid && !memcmp(rsp->LeaseKey, tcon->crfid.fid->lease_key, SMB2_LEASE_KEY_SIZE)) { INIT_WORK(&tcon->crfid.lease_break, smb2_cached_lease_break); queue_work(cifsiod_wq, &tcon->crfid.lease_break); spin_unlock(&cifs_tcp_ses_lock); return true; } |
233839b1d CIFS: Fix fast le... |
682 |
} |
0822f5142 CIFS: Add SMB2.1 ... |
683 684 685 |
} } spin_unlock(&cifs_tcp_ses_lock); |
f96637be0 [CIFS] cifs: Rena... |
686 687 |
cifs_dbg(FYI, "Can not process lease break - no lease matched "); |
0822f5142 CIFS: Add SMB2.1 ... |
688 689 |
return false; } |
983c88a49 CIFS: Add oplock ... |
690 691 692 |
bool smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) { |
0d5a288d2 cifs: remove stru... |
693 |
struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer; |
983c88a49 CIFS: Add oplock ... |
694 695 696 697 698 |
struct list_head *tmp, *tmp1, *tmp2; struct cifs_ses *ses; struct cifs_tcon *tcon; struct cifsInodeInfo *cinode; struct cifsFileInfo *cfile; |
f96637be0 [CIFS] cifs: Rena... |
699 700 |
cifs_dbg(FYI, "Checking for oplock break "); |
983c88a49 CIFS: Add oplock ... |
701 |
|
0d5a288d2 cifs: remove stru... |
702 |
if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK) |
983c88a49 CIFS: Add oplock ... |
703 |
return false; |
12e8a2082 Trivial endian fixes |
704 |
if (rsp->StructureSize != |
983c88a49 CIFS: Add oplock ... |
705 |
smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) { |
0822f5142 CIFS: Add SMB2.1 ... |
706 |
if (le16_to_cpu(rsp->StructureSize) == 44) |
933d4b365 CIFS: Fix missing... |
707 |
return smb2_is_valid_lease_break(buffer); |
0822f5142 CIFS: Add SMB2.1 ... |
708 709 |
else return false; |
983c88a49 CIFS: Add oplock ... |
710 |
} |
59b04c5df [CIFS] Fix incorr... |
711 712 |
cifs_dbg(FYI, "oplock level 0x%x ", rsp->OplockLevel); |
983c88a49 CIFS: Add oplock ... |
713 714 715 716 717 |
/* look up tcon based on tid & uid */ spin_lock(&cifs_tcp_ses_lock); list_for_each(tmp, &server->smb_ses_list) { ses = list_entry(tmp, struct cifs_ses, smb_ses_list); |
fa9c23624 CIFS: Fix SMB2 op... |
718 |
|
983c88a49 CIFS: Add oplock ... |
719 720 |
list_for_each(tmp1, &ses->tcon_list) { tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); |
3afca265b Clarify locking o... |
721 |
spin_lock(&tcon->open_file_lock); |
983c88a49 CIFS: Add oplock ... |
722 723 724 725 726 727 728 729 |
list_for_each(tmp2, &tcon->openFileList) { cfile = list_entry(tmp2, struct cifsFileInfo, tlist); if (rsp->PersistentFid != cfile->fid.persistent_fid || rsp->VolatileFid != cfile->fid.volatile_fid) continue; |
f96637be0 [CIFS] cifs: Rena... |
730 731 |
cifs_dbg(FYI, "file id match, oplock break "); |
fa9c23624 CIFS: Fix SMB2 op... |
732 733 |
cifs_stats_inc( &tcon->stats.cifs_stats.num_oplock_brks); |
2b0143b5c VFS: normal files... |
734 |
cinode = CIFS_I(d_inode(cfile->dentry)); |
3afca265b Clarify locking o... |
735 |
spin_lock(&cfile->file_info_lock); |
18cceb6a7 CIFS: Replace cli... |
736 |
if (!CIFS_CACHE_WRITE(cinode) && |
983c88a49 CIFS: Add oplock ... |
737 738 739 740 |
rsp->OplockLevel == SMB2_OPLOCK_LEVEL_NONE) cfile->oplock_break_cancelled = true; else cfile->oplock_break_cancelled = false; |
c11f1df50 cifs: Wait for wr... |
741 742 |
set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags); |
9bd454083 CIFS: Properly pr... |
743 744 |
cfile->oplock_epoch = 0; cfile->oplock_level = rsp->OplockLevel; |
3afca265b Clarify locking o... |
745 |
spin_unlock(&cfile->file_info_lock); |
b98749cac CIFS: keep FileIn... |
746 747 |
cifs_queue_oplock_break(cfile); |
983c88a49 CIFS: Add oplock ... |
748 |
|
3afca265b Clarify locking o... |
749 |
spin_unlock(&tcon->open_file_lock); |
983c88a49 CIFS: Add oplock ... |
750 751 752 |
spin_unlock(&cifs_tcp_ses_lock); return true; } |
3afca265b Clarify locking o... |
753 |
spin_unlock(&tcon->open_file_lock); |
983c88a49 CIFS: Add oplock ... |
754 755 756 |
} } spin_unlock(&cifs_tcp_ses_lock); |
f96637be0 [CIFS] cifs: Rena... |
757 758 |
cifs_dbg(FYI, "Can not process oplock break for non-existent connection "); |
983c88a49 CIFS: Add oplock ... |
759 760 |
return false; } |
38bd49064 Handle mismatched... |
761 762 763 764 765 766 |
void smb2_cancelled_close_fid(struct work_struct *work) { struct close_cancelled_open *cancelled = container_of(work, struct close_cancelled_open, work); |
87bc2376f smb3: add debug m... |
767 768 769 770 771 772 773 774 775 776 |
struct cifs_tcon *tcon = cancelled->tcon; int rc; if (cancelled->mid) cifs_tcon_dbg(VFS, "Close unmatched open for MID:%llx ", cancelled->mid); else cifs_tcon_dbg(VFS, "Close interrupted close "); |
38bd49064 Handle mismatched... |
777 |
|
87bc2376f smb3: add debug m... |
778 779 780 781 782 |
rc = SMB2_close(0, tcon, cancelled->fid.persistent_fid, cancelled->fid.volatile_fid); if (rc) cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d ", rc); |
38bd49064 Handle mismatched... |
783 |
|
87bc2376f smb3: add debug m... |
784 |
cifs_put_tcon(tcon); |
38bd49064 Handle mismatched... |
785 786 |
kfree(cancelled); } |
87bc2376f smb3: add debug m... |
787 788 789 790 791 792 793 794 |
/* * Caller should already has an extra reference to @tcon * This function is used to queue work to close a handle to prevent leaks * on the server. * We handle two cases. If an open was interrupted after we sent the * SMB2_CREATE to the server but before we processed the reply, and second * if a close was interrupted before we sent the SMB2_CLOSE to the server. */ |
9150c3adb CIFS: Close open ... |
795 |
static int |
87bc2376f smb3: add debug m... |
796 797 |
__smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid, __u64 persistent_fid, __u64 volatile_fid) |
9150c3adb CIFS: Close open ... |
798 799 |
{ struct close_cancelled_open *cancelled; |
0a5a98863 cifs: Fix memory ... |
800 |
cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC); |
9150c3adb CIFS: Close open ... |
801 802 803 804 805 806 |
if (!cancelled) return -ENOMEM; cancelled->fid.persistent_fid = persistent_fid; cancelled->fid.volatile_fid = volatile_fid; cancelled->tcon = tcon; |
87bc2376f smb3: add debug m... |
807 808 |
cancelled->cmd = cmd; cancelled->mid = mid; |
9150c3adb CIFS: Close open ... |
809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 |
INIT_WORK(&cancelled->work, smb2_cancelled_close_fid); WARN_ON(queue_work(cifsiod_wq, &cancelled->work) == false); return 0; } int smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, __u64 volatile_fid) { int rc; cifs_dbg(FYI, "%s: tc_count=%d ", __func__, tcon->tc_count); spin_lock(&cifs_tcp_ses_lock); |
e79b0332a cifs: ignore cach... |
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 |
if (tcon->tc_count <= 0) { struct TCP_Server_Info *server = NULL; WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative"); spin_unlock(&cifs_tcp_ses_lock); if (tcon->ses) server = tcon->ses->server; cifs_server_dbg(FYI, "tid=%u: tcon is closing, skipping async close retry of fid %llu %llu ", tcon->tid, persistent_fid, volatile_fid); return 0; } |
9150c3adb CIFS: Close open ... |
839 840 |
tcon->tc_count++; spin_unlock(&cifs_tcp_ses_lock); |
87bc2376f smb3: add debug m... |
841 842 |
rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0, persistent_fid, volatile_fid); |
9150c3adb CIFS: Close open ... |
843 844 845 846 847 |
if (rc) cifs_put_tcon(tcon); return rc; } |
38bd49064 Handle mismatched... |
848 849 850 |
int smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) { |
49f466bdb cifs: remove stru... |
851 |
struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer; |
38bd49064 Handle mismatched... |
852 853 |
struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; struct cifs_tcon *tcon; |
9150c3adb CIFS: Close open ... |
854 |
int rc; |
38bd49064 Handle mismatched... |
855 856 857 858 |
if (sync_hdr->Command != SMB2_CREATE || sync_hdr->Status != STATUS_SUCCESS) return 0; |
38bd49064 Handle mismatched... |
859 860 |
tcon = smb2_find_smb_tcon(server, sync_hdr->SessionId, sync_hdr->TreeId); |
9150c3adb CIFS: Close open ... |
861 |
if (!tcon) |
38bd49064 Handle mismatched... |
862 |
return -ENOENT; |
38bd49064 Handle mismatched... |
863 |
|
87bc2376f smb3: add debug m... |
864 865 866 867 868 |
rc = __smb2_handle_cancelled_cmd(tcon, le16_to_cpu(sync_hdr->Command), le64_to_cpu(sync_hdr->MessageId), rsp->PersistentFileId, rsp->VolatileFileId); |
9150c3adb CIFS: Close open ... |
869 870 |
if (rc) cifs_put_tcon(tcon); |
38bd49064 Handle mismatched... |
871 |
|
9150c3adb CIFS: Close open ... |
872 |
return rc; |
38bd49064 Handle mismatched... |
873 |
} |
8bd68c6e4 CIFS: implement v... |
874 |
|
8bd68c6e4 CIFS: implement v... |
875 876 877 878 879 880 881 882 883 884 885 886 |
/** * smb311_update_preauth_hash - update @ses hash with the packet data in @iov * * Assumes @iov does not contain the rfc1002 length and iov[0] has the * SMB2 header. */ int smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec) { int i, rc; struct sdesc *d; struct smb2_sync_hdr *hdr; |
d70e9fa55 cifs: try opening... |
887 |
struct TCP_Server_Info *server = cifs_ses_server(ses); |
8bd68c6e4 CIFS: implement v... |
888 |
|
d70e9fa55 cifs: try opening... |
889 890 891 892 |
hdr = (struct smb2_sync_hdr *)iov[0].iov_base; /* neg prot are always taken */ if (hdr->Command == SMB2_NEGOTIATE) goto ok; |
8bd68c6e4 CIFS: implement v... |
893 |
|
d70e9fa55 cifs: try opening... |
894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 |
/* * If we process a command which wasn't a negprot it means the * neg prot was already done, so the server dialect was set * and we can test it. Preauth requires 3.1.1 for now. */ if (server->dialect != SMB311_PROT_ID) return 0; if (hdr->Command != SMB2_SESSION_SETUP) return 0; /* skip last sess setup response */ if ((hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) && (hdr->Status == NT_STATUS_OK || (hdr->Status != cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)))) return 0; |
8bd68c6e4 CIFS: implement v... |
911 |
|
d70e9fa55 cifs: try opening... |
912 913 |
ok: rc = smb311_crypto_shash_allocate(server); |
8bd68c6e4 CIFS: implement v... |
914 915 |
if (rc) return rc; |
d70e9fa55 cifs: try opening... |
916 |
d = server->secmech.sdescsha512; |
8bd68c6e4 CIFS: implement v... |
917 918 |
rc = crypto_shash_init(&d->shash); if (rc) { |
a0a3036b8 cifs: Standardize... |
919 920 |
cifs_dbg(VFS, "%s: Could not init sha512 shash ", __func__); |
8bd68c6e4 CIFS: implement v... |
921 922 923 924 925 926 |
return rc; } rc = crypto_shash_update(&d->shash, ses->preauth_sha_hash, SMB2_PREAUTH_HASH_SIZE); if (rc) { |
a0a3036b8 cifs: Standardize... |
927 928 |
cifs_dbg(VFS, "%s: Could not update sha512 shash ", __func__); |
8bd68c6e4 CIFS: implement v... |
929 930 931 932 933 934 935 |
return rc; } for (i = 0; i < nvec; i++) { rc = crypto_shash_update(&d->shash, iov[i].iov_base, iov[i].iov_len); if (rc) { |
a0a3036b8 cifs: Standardize... |
936 937 |
cifs_dbg(VFS, "%s: Could not update sha512 shash ", |
8bd68c6e4 CIFS: implement v... |
938 939 940 941 942 943 944 |
__func__); return rc; } } rc = crypto_shash_final(&d->shash, ses->preauth_sha_hash); if (rc) { |
a0a3036b8 cifs: Standardize... |
945 946 |
cifs_dbg(VFS, "%s: Could not finalize sha512 shash ", |
8bd68c6e4 CIFS: implement v... |
947 948 949 950 951 952 |
__func__); return rc; } return 0; } |