Blame view

fs/cifs/smb2misc.c 24.1 KB
093b2bdad   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Separate SM...
31
  #include "smb2glob.h"
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
32
33
  
  static int
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
34
  check_smb2_hdr(struct smb2_sync_hdr *shdr, __u64 mid)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
35
  {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
36
  	__u64 wire_mid = le64_to_cpu(shdr->MessageId);
9235d0987   Sachin Prabhu   Convert MessageID...
37

093b2bdad   Pavel Shilovsky   CIFS: Make demult...
38
39
40
41
  	/*
  	 * Make sure that this really is an SMB, that it is a response,
  	 * and that the message ids match.
  	 */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
42
  	if ((shdr->ProtocolId == SMB2_PROTO_NUMBER) &&
9235d0987   Sachin Prabhu   Convert MessageID...
43
  	    (mid == wire_mid)) {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
44
  		if (shdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
45
46
47
  			return 0;
  		else {
  			/* only one valid case where server sends us request */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
48
  			if (shdr->Command == SMB2_OPLOCK_BREAK)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
49
50
  				return 0;
  			else
f96637be0   Joe Perches   [CIFS] cifs: Rena...
51
52
  				cifs_dbg(VFS, "Received Request not response
  ");
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
53
54
  		}
  	} else { /* bad signature or mid */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
55
  		if (shdr->ProtocolId != SMB2_PROTO_NUMBER)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
56
57
  			cifs_dbg(VFS, "Bad protocol string signature header %x
  ",
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
58
  				 le32_to_cpu(shdr->ProtocolId));
9235d0987   Sachin Prabhu   Convert MessageID...
59
  		if (mid != wire_mid)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
60
61
  			cifs_dbg(VFS, "Mids do not match: %llu and %llu
  ",
9235d0987   Sachin Prabhu   Convert MessageID...
62
  				 mid, wire_mid);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
63
  	}
9235d0987   Sachin Prabhu   Convert MessageID...
64
65
  	cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu
  ", wire_mid);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
66
67
68
69
70
71
72
73
74
75
76
  	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   Fabian Frederick   fs/cifs: remove o...
77
78
79
80
81
82
83
84
85
86
87
88
  	/* 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   Pavel Shilovsky   CIFS: Make demult...
89
  	/* BB CHECK this ... not listed in documentation */
bc09d141e   Fabian Frederick   fs/cifs: remove o...
90
91
92
93
94
95
  	/* 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   Pavel Shilovsky   CIFS: Make demult...
96
  	/* BB FIXME can also be 44 for lease break */
bc09d141e   Fabian Frederick   fs/cifs: remove o...
97
  	/* SMB2_OPLOCK_BREAK */ cpu_to_le16(24)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
98
  };
98170fb53   Ronnie Sahlberg   cifs: update smb2...
99
  static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
100
  			      __u32 non_ctxlen)
136ff1b4b   Steve French   SMB3: Fix length ...
101
102
103
104
105
106
107
108
109
110
111
112
113
  {
  	__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);
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
114
  	if (nc_offset < non_ctxlen) {
136ff1b4b   Steve French   SMB3: Fix length ...
115
116
117
118
  		printk_once(KERN_WARNING "invalid negotiate context offset
  ");
  		return 0;
  	}
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
119
  	size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen;
136ff1b4b   Steve French   SMB3: Fix length ...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  
  	/* Verify that at least minimal negotiate contexts fit within frame */
  	if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) {
  		printk_once(KERN_WARNING "negotiate context goes beyond end
  ");
  		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   Steve French   SMB3: Fix length ...
135

093b2bdad   Pavel Shilovsky   CIFS: Make demult...
136
  int
98170fb53   Ronnie Sahlberg   cifs: update smb2...
137
  smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
138
  {
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
139
  	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
98170fb53   Ronnie Sahlberg   cifs: update smb2...
140
  	struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
373512ec5   Steve French   Prepare for encry...
141
  	__u64 mid;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
142
143
  	__u32 clc_len;  /* calculated length */
  	int command;
98170fb53   Ronnie Sahlberg   cifs: update smb2...
144
145
  	int pdu_size = sizeof(struct smb2_sync_pdu);
  	int hdr_size = sizeof(struct smb2_sync_hdr);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
146
147
148
149
150
  
  	/*
  	 * Add function to do table lookup of StructureSize by command
  	 * ie Validate the wct via smb2_struct_sizes table above
  	 */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
151
  	if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
373512ec5   Steve French   Prepare for encry...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  		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   Pavel Shilovsky   CIFS: Separate SM...
173
  	mid = le64_to_cpu(shdr->MessageId);
98170fb53   Ronnie Sahlberg   cifs: update smb2...
174
175
  	if (len < pdu_size) {
  		if ((len >= hdr_size)
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
176
  		    && (shdr->Status != 0)) {
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
177
178
179
180
181
182
183
  			pdu->StructureSize2 = 0;
  			/*
  			 * As with SMB/CIFS, on some error cases servers may
  			 * not return wct properly
  			 */
  			return 0;
  		} else {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
184
185
  			cifs_dbg(VFS, "Length less than SMB header size
  ");
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
186
187
188
  		}
  		return 1;
  	}
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
189
  	if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
190
191
192
  		cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu
  ",
  			 mid);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
193
194
  		return 1;
  	}
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
195
  	if (check_smb2_hdr(shdr, mid))
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
196
  		return 1;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
197
  	if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
198
199
  		cifs_dbg(VFS, "Illegal structure size %u
  ",
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
200
  			 le16_to_cpu(shdr->StructureSize));
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
201
202
  		return 1;
  	}
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
203
  	command = le16_to_cpu(shdr->Command);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
204
  	if (command >= NUMBER_OF_SMB2_COMMANDS) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
205
206
  		cifs_dbg(VFS, "Illegal SMB2 command %d
  ", command);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
207
208
209
210
  		return 1;
  	}
  
  	if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
211
  		if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 ||
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
212
  		    pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) {
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
213
  			/* error packets have 9 byte structure size */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
214
215
216
  			cifs_dbg(VFS, "Illegal response size %u for command %d
  ",
  				 le16_to_cpu(pdu->StructureSize2), command);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
217
  			return 1;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
218
219
  		} else if (command == SMB2_OPLOCK_BREAK_HE
  			   && (shdr->Status == 0)
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
220
221
222
  			   && (le16_to_cpu(pdu->StructureSize2) != 44)
  			   && (le16_to_cpu(pdu->StructureSize2) != 36)) {
  			/* special case for SMB2.1 lease break message */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
223
224
225
  			cifs_dbg(VFS, "Illegal response size %d for oplock break
  ",
  				 le16_to_cpu(pdu->StructureSize2));
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
226
  			return 1;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
227
228
  		}
  	}
98170fb53   Ronnie Sahlberg   cifs: update smb2...
229
  	clc_len = smb2_calc_size(buf, srvr);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
230

136ff1b4b   Steve French   SMB3: Fix length ...
231
  	if (shdr->Command == SMB2_NEGOTIATE)
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
232
  		clc_len += get_neg_ctxt_len(shdr, len, clc_len);
0fdfef9aa   Steve French   smb3: simplify co...
233

98170fb53   Ronnie Sahlberg   cifs: update smb2...
234
235
236
237
  	if (len != clc_len) {
  		cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu
  ",
  			 clc_len, len, mid);
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
238
239
  		/* create failed on symlink */
  		if (command == SMB2_CREATE_HE &&
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
240
  		    shdr->Status == STATUS_STOPPED_ON_SYMLINK)
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
241
  			return 0;
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
242
  		/* Windows 7 server returns 24 bytes more */
98170fb53   Ronnie Sahlberg   cifs: update smb2...
243
  		if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE)
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
244
  			return 0;
754789a1c   Steve French   [CIFS] Workaround...
245
  		/* server can return one byte more due to implied bcc[0] */
98170fb53   Ronnie Sahlberg   cifs: update smb2...
246
  		if (clc_len == len + 1)
741128608   Pavel Shilovsky   CIFS: Fix log mes...
247
  			return 0;
754789a1c   Steve French   [CIFS] Workaround...
248
249
  
  		/*
e6c47dd0d   Ronnie Sahlberg   cifs: check if SM...
250
251
252
253
254
255
256
  		 * 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   Steve French   [CIFS] Workaround...
257
258
259
  		 * 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   Steve French   smb3: minor debug...
260
261
262
  		 * Some windows servers also pad up to 8 bytes when compounding.
  		 * If pad is longer than eight bytes, log the server behavior
  		 * (once), since may indicate a problem but allow it and continue
754789a1c   Steve French   [CIFS] Workaround...
263
264
  		 * since the frame is parseable.
  		 */
98170fb53   Ronnie Sahlberg   cifs: update smb2...
265
  		if (clc_len < len) {
25f257351   Steve French   smb3: minor debug...
266
267
268
269
  			pr_warn_once(
  			     "srv rsp padded more than expected. Length %d not %d for cmd:%d mid:%llu
  ",
  			     len, clc_len, command, mid);
754789a1c   Steve French   [CIFS] Workaround...
270
271
  			return 0;
  		}
25f257351   Steve French   smb3: minor debug...
272
273
274
275
  		pr_warn_once(
  			"srv rsp too short, len %d not %d. cmd:%d mid:%llu
  ",
  			len, clc_len, command, mid);
754789a1c   Steve French   [CIFS] Workaround...
276

093b2bdad   Pavel Shilovsky   CIFS: Make demult...
277
278
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
  		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   Pavel Shilovsky   CIFS: Add capabil...
313
  char *
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
314
  smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
315
316
317
318
319
  {
  	*off = 0;
  	*len = 0;
  
  	/* error responses do not have data area */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
320
  	if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
321
  	    (((struct smb2_err_rsp *)shdr)->StructureSize) ==
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
322
323
324
325
326
327
328
329
  						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   Pavel Shilovsky   CIFS: Separate SM...
330
  	switch (shdr->Command) {
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
331
  	case SMB2_NEGOTIATE:
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
332
  		*off = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
333
  		  ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferOffset);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
334
  		*len = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
335
  		  ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferLength);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
336
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
337
  	case SMB2_SESSION_SETUP:
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
338
  		*off = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
339
  		  ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
340
  		*len = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
341
  		  ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
342
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
343
  	case SMB2_CREATE:
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
344
  		*off = le32_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
345
  		    ((struct smb2_create_rsp *)shdr)->CreateContextsOffset);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
346
  		*len = le32_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
347
  		    ((struct smb2_create_rsp *)shdr)->CreateContextsLength);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
348
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
349
  	case SMB2_QUERY_INFO:
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
350
  		*off = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
351
  		    ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
352
  		*len = le32_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
353
  		    ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
354
355
  		break;
  	case SMB2_READ:
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
356
357
358
  		/* TODO: is this a bug ? */
  		*off = ((struct smb2_read_rsp *)shdr)->DataOffset;
  		*len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength);
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
359
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
360
  	case SMB2_QUERY_DIRECTORY:
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
361
  		*off = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
362
  		  ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
363
  		*len = le32_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
364
  		  ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
365
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
366
  	case SMB2_IOCTL:
4a72dafa1   Steve French   SMB2 FSCTL and IO...
367
  		*off = le32_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
368
369
370
  		  ((struct smb2_ioctl_rsp *)shdr)->OutputOffset);
  		*len = le32_to_cpu(
  		  ((struct smb2_ioctl_rsp *)shdr)->OutputCount);
4a72dafa1   Steve French   SMB2 FSCTL and IO...
371
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
372
373
374
  	case SMB2_CHANGE_NOTIFY:
  	default:
  		/* BB FIXME for unimplemented cases above */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
375
376
  		cifs_dbg(VFS, "no length check for command
  ");
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
377
378
379
380
381
382
383
384
  		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   Joe Perches   [CIFS] cifs: Rena...
385
386
  		cifs_dbg(VFS, "offset %d too large, data area ignored
  ", *off);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
387
388
389
  		*len = 0;
  		*off = 0;
  	} else if (*off < 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
390
391
392
  		cifs_dbg(VFS, "negative offset %d to data invalid ignore data area
  ",
  			 *off);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
393
394
395
  		*off = 0;
  		*len = 0;
  	} else if (*len < 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
396
397
398
  		cifs_dbg(VFS, "negative data length %d invalid, data area ignored
  ",
  			 *len);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
399
400
  		*len = 0;
  	} else if (*len > 128 * 1024) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
401
402
  		cifs_dbg(VFS, "data area larger than 128K: %d
  ", *len);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
403
404
405
406
407
  		*len = 0;
  	}
  
  	/* return pointer to beginning of data area, ie offset from SMB start */
  	if ((*off != 0) && (*len != 0))
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
408
  		return (char *)shdr + *off;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
409
410
411
412
413
414
415
416
417
  	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   Ronnie Sahlberg   cifs: update calc...
418
  smb2_calc_size(void *buf, struct TCP_Server_Info *srvr)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
419
  {
84f0cbfba   Ronnie Sahlberg   cifs: update smb2...
420
421
  	struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf;
  	struct smb2_sync_hdr *shdr = &pdu->sync_hdr;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
422
423
424
  	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   Ronnie Sahlberg   cifs: remove head...
425
  	int len = le16_to_cpu(shdr->StructureSize);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
426
427
428
429
430
431
  
  	/*
  	 * 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   Pavel Shilovsky   CIFS: Separate SM...
432
  	if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
433
  		goto calc_size_exit;
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
434
  	smb2_get_data_area_len(&offset, &data_length, shdr);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
435
436
  	cifs_dbg(FYI, "SMB2 data length %d offset %d
  ", data_length, offset);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
437
438
439
440
441
442
  
  	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   Ronnie Sahlberg   cifs: update smb2...
443
  		 * so we must add one to the calculation.
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
444
  		 */
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
445
446
447
448
  		if (offset + 1 < len) {
  			cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d
  ",
  				 offset + 1, len);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
449
450
  			data_length = 0;
  		} else {
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
451
  			len = offset + data_length;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
452
453
454
  		}
  	}
  calc_size_exit:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
455
456
  	cifs_dbg(FYI, "SMB2 len %d
  ", len);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
457
458
  	return len;
  }
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
459
460
461
462
463
464
465
466
  
  /* 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   Steve French   Allow conversion ...
467
468
469
470
471
472
473
474
  	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   Pavel Shilovsky   CIFS: Add SMB2 su...
475
476
477
478
  
  	/* Windows doesn't allow paths beginning with \ */
  	if (from[0] == '\\')
  		start_of_path = from + 1;
0fdfef9aa   Steve French   smb3: simplify co...
479

ce558b0e1   Steve French   smb3: Add posix c...
480
  	/* SMB311 POSIX extensions paths do not include leading slash */
8ddecf5fd   Aurelien Aptel   CIFS: Fix NULL pt...
481
  	else if (cifs_sb_master_tlink(cifs_sb) &&
d819d298c   Steve French   smb3: fix corrupt...
482
483
  		 cifs_sb_master_tcon(cifs_sb)->posix_extensions &&
  		 (from[0] == '/')) {
ce558b0e1   Steve French   smb3: Add posix c...
484
  		start_of_path = from + 1;
0fdfef9aa   Steve French   smb3: simplify co...
485
  	} else
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
486
  		start_of_path = from;
ce558b0e1   Steve French   smb3: Add posix c...
487

2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
488
  	to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
a4153cb1d   Steve French   Allow conversion ...
489
  				   cifs_sb->local_nls, map_type);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
490
491
  	return to;
  }
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
492

0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
493
494
495
  __le32
  smb2_get_lease_state(struct cifsInodeInfo *cinode)
  {
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
496
  	__le32 lease = 0;
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
497

53ef1016f   Pavel Shilovsky   CIFS: Store lease...
498
499
500
501
502
503
504
  	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   Pavel Shilovsky   CIFS: Add SMB2.1 ...
505
  }
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
506
507
508
509
510
511
512
513
514
515
516
517
  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   Ronnie Sahlberg   cifs: add lease t...
518
  	int rc = 0;
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
519
520
521
  
  	rc = SMB2_lease_break(0, tlink_tcon(lw->tlink), lw->lease_key,
  			      lw->lease_state);
a93864d93   Ronnie Sahlberg   cifs: add lease t...
522

f96637be0   Joe Perches   [CIFS] cifs: Rena...
523
524
  	cifs_dbg(FYI, "Lease release rc %d
  ", rc);
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
525
526
527
  	cifs_put_tlink(lw->tlink);
  	kfree(lw);
  }
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
528
  static bool
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
529
530
531
532
533
534
535
536
537
538
539
  smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp,
  		    struct smb2_lease_break_work *lw)
  {
  	bool found;
  	__u8 lease_state;
  	struct list_head *tmp;
  	struct cifsFileInfo *cfile;
  	struct cifs_pending_open *open;
  	struct cifsInodeInfo *cinode;
  	int ack_req = le32_to_cpu(rsp->Flags &
  				  SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
540
  	lease_state = le32_to_cpu(rsp->NewLeaseState);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
541
542
543
  
  	list_for_each(tmp, &tcon->openFileList) {
  		cfile = list_entry(tmp, struct cifsFileInfo, tlist);
2b0143b5c   David Howells   VFS: normal files...
544
  		cinode = CIFS_I(d_inode(cfile->dentry));
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
545
546
547
548
549
550
551
  
  		if (memcmp(cinode->lease_key, rsp->LeaseKey,
  							SMB2_LEASE_KEY_SIZE))
  			continue;
  
  		cifs_dbg(FYI, "found in the open list
  ");
59b04c5df   Steve French   [CIFS] Fix incorr...
552
553
  		cifs_dbg(FYI, "lease key match, lease break 0x%x
  ",
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
554
  			 le32_to_cpu(rsp->NewLeaseState));
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
555
556
557
558
  		if (ack_req)
  			cfile->oplock_break_cancelled = false;
  		else
  			cfile->oplock_break_cancelled = true;
3ed9f22e2   Pavel Shilovsky   CIFS: Do not rese...
559
560
561
562
563
564
565
566
567
568
569
570
571
  		set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
  
  		/*
  		 * Set or clear flags depending on the lease state being READ.
  		 * HANDLE caching flag should be added when the client starts
  		 * to defer closing remote file handles with HANDLE leases.
  		 */
  		if (lease_state & SMB2_LEASE_READ_CACHING_HE)
  			set_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
  				&cinode->flags);
  		else
  			clear_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
  				  &cinode->flags);
3998e6b87   Rabin Vincent   CIFS: fix oplock ...
572
  		queue_work(cifsoplockd_wq, &cfile->oplock_break);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
  		kfree(lw);
  		return true;
  	}
  
  	found = false;
  	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) {
  			found = true;
  			memcpy(lw->lease_key, open->lease_key,
  			       SMB2_LEASE_KEY_SIZE);
  			lw->tlink = cifs_get_tlink(open->tlink);
  			queue_work(cifsiod_wq, &lw->lease_break);
  		}
  
  		cifs_dbg(FYI, "found in the pending open list
  ");
59b04c5df   Steve French   [CIFS] Fix incorr...
593
594
  		cifs_dbg(FYI, "lease key match, lease break 0x%x
  ",
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
595
596
597
598
  			 le32_to_cpu(rsp->NewLeaseState));
  
  		open->oplock = lease_state;
  	}
a93864d93   Ronnie Sahlberg   cifs: add lease t...
599

933d4b365   Pavel Shilovsky   CIFS: Fix missing...
600
601
602
603
604
  	return found;
  }
  
  static bool
  smb2_is_valid_lease_break(char *buffer)
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
605
606
607
  {
  	struct smb2_lease_break *rsp = (struct smb2_lease_break *)buffer;
  	struct list_head *tmp, *tmp1, *tmp2;
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
608
  	struct TCP_Server_Info *server;
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
609
610
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon;
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
611
  	struct smb2_lease_break_work *lw;
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
612
613
  
  	lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
614
  	if (!lw)
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
615
  		return false;
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
616
617
618
  
  	INIT_WORK(&lw->lease_break, cifs_ses_oplock_break);
  	lw->lease_state = rsp->NewLeaseState;
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
619

f96637be0   Joe Perches   [CIFS] cifs: Rena...
620
621
  	cifs_dbg(FYI, "Checking for lease break
  ");
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
622
623
624
  
  	/* look up tcon based on tid & uid */
  	spin_lock(&cifs_tcp_ses_lock);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
625
626
  	list_for_each(tmp, &cifs_tcp_ses_list) {
  		server = list_entry(tmp, struct TCP_Server_Info, tcp_ses_list);
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
627

933d4b365   Pavel Shilovsky   CIFS: Fix missing...
628
629
  		list_for_each(tmp1, &server->smb_ses_list) {
  			ses = list_entry(tmp1, struct cifs_ses, smb_ses_list);
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
630

933d4b365   Pavel Shilovsky   CIFS: Fix missing...
631
632
633
  			list_for_each(tmp2, &ses->tcon_list) {
  				tcon = list_entry(tmp2, struct cifs_tcon,
  						  tcon_list);
3afca265b   Steve French   Clarify locking o...
634
  				spin_lock(&tcon->open_file_lock);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
635
636
637
  				cifs_stats_inc(
  				    &tcon->stats.cifs_stats.num_oplock_brks);
  				if (smb2_tcon_has_lease(tcon, rsp, lw)) {
3afca265b   Steve French   Clarify locking o...
638
  					spin_unlock(&tcon->open_file_lock);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
639
640
  					spin_unlock(&cifs_tcp_ses_lock);
  					return true;
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
641
  				}
3afca265b   Steve French   Clarify locking o...
642
  				spin_unlock(&tcon->open_file_lock);
a93864d93   Ronnie Sahlberg   cifs: add lease t...
643
644
645
646
647
648
649
650
651
652
653
654
  
  				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   Pavel Shilovsky   CIFS: Fix fast le...
655
  			}
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
656
657
658
  		}
  	}
  	spin_unlock(&cifs_tcp_ses_lock);
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
659
  	kfree(lw);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
660
661
  	cifs_dbg(FYI, "Can not process lease break - no lease matched
  ");
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
662
663
  	return false;
  }
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
664
665
666
  bool
  smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
  {
0d5a288d2   Ronnie Sahlberg   cifs: remove stru...
667
  	struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
668
669
670
671
672
  	struct list_head *tmp, *tmp1, *tmp2;
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon;
  	struct cifsInodeInfo *cinode;
  	struct cifsFileInfo *cfile;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
673
674
  	cifs_dbg(FYI, "Checking for oplock break
  ");
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
675

0d5a288d2   Ronnie Sahlberg   cifs: remove stru...
676
  	if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
677
  		return false;
06d9f9872   Ronnie Sahlberg   smb3: add credits...
678
679
680
681
682
683
  	if (rsp->sync_hdr.CreditRequest) {
  		spin_lock(&server->req_lock);
  		server->credits += le16_to_cpu(rsp->sync_hdr.CreditRequest);
  		spin_unlock(&server->req_lock);
  		wake_up(&server->request_q);
  	}
12e8a2082   Steve French   Trivial endian fixes
684
  	if (rsp->StructureSize !=
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
685
  				smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
686
  		if (le16_to_cpu(rsp->StructureSize) == 44)
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
687
  			return smb2_is_valid_lease_break(buffer);
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
688
689
  		else
  			return false;
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
690
  	}
59b04c5df   Steve French   [CIFS] Fix incorr...
691
692
  	cifs_dbg(FYI, "oplock level 0x%x
  ", rsp->OplockLevel);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
693
694
695
696
697
698
699
700
701
  
  	/* 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);
  		list_for_each(tmp1, &ses->tcon_list) {
  			tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
  
  			cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
3afca265b   Steve French   Clarify locking o...
702
  			spin_lock(&tcon->open_file_lock);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
703
704
705
706
707
708
709
710
  			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   Joe Perches   [CIFS] cifs: Rena...
711
712
  				cifs_dbg(FYI, "file id match, oplock break
  ");
2b0143b5c   David Howells   VFS: normal files...
713
  				cinode = CIFS_I(d_inode(cfile->dentry));
3afca265b   Steve French   Clarify locking o...
714
  				spin_lock(&cfile->file_info_lock);
18cceb6a7   Pavel Shilovsky   CIFS: Replace cli...
715
  				if (!CIFS_CACHE_WRITE(cinode) &&
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
716
717
718
719
  				    rsp->OplockLevel == SMB2_OPLOCK_LEVEL_NONE)
  					cfile->oplock_break_cancelled = true;
  				else
  					cfile->oplock_break_cancelled = false;
c11f1df50   Sachin Prabhu   cifs: Wait for wr...
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
  				set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
  					&cinode->flags);
  
  				/*
  				 * Set flag if the server downgrades the oplock
  				 * to L2 else clear.
  				 */
  				if (rsp->OplockLevel)
  					set_bit(
  					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
  					   &cinode->flags);
  				else
  					clear_bit(
  					   CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2,
  					   &cinode->flags);
3afca265b   Steve French   Clarify locking o...
735
  				spin_unlock(&cfile->file_info_lock);
3998e6b87   Rabin Vincent   CIFS: fix oplock ...
736
737
  				queue_work(cifsoplockd_wq,
  					   &cfile->oplock_break);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
738

3afca265b   Steve French   Clarify locking o...
739
  				spin_unlock(&tcon->open_file_lock);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
740
741
742
  				spin_unlock(&cifs_tcp_ses_lock);
  				return true;
  			}
3afca265b   Steve French   Clarify locking o...
743
  			spin_unlock(&tcon->open_file_lock);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
744
  			spin_unlock(&cifs_tcp_ses_lock);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
745
746
  			cifs_dbg(FYI, "No matching file for oplock break
  ");
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
747
748
749
750
  			return true;
  		}
  	}
  	spin_unlock(&cifs_tcp_ses_lock);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
751
752
  	cifs_dbg(FYI, "Can not process oplock break for non-existent connection
  ");
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
753
754
  	return false;
  }
38bd49064   Sachin Prabhu   Handle mismatched...
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
  
  void
  smb2_cancelled_close_fid(struct work_struct *work)
  {
  	struct close_cancelled_open *cancelled = container_of(work,
  					struct close_cancelled_open, work);
  
  	cifs_dbg(VFS, "Close unmatched open
  ");
  
  	SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid,
  		   cancelled->fid.volatile_fid);
  	cifs_put_tcon(cancelled->tcon);
  	kfree(cancelled);
  }
  
  int
  smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
  {
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
774
  	struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer;
38bd49064   Sachin Prabhu   Handle mismatched...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
  	struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
  	struct cifs_tcon *tcon;
  	struct close_cancelled_open *cancelled;
  
  	if (sync_hdr->Command != SMB2_CREATE ||
  	    sync_hdr->Status != STATUS_SUCCESS)
  		return 0;
  
  	cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
  	if (!cancelled)
  		return -ENOMEM;
  
  	tcon = smb2_find_smb_tcon(server, sync_hdr->SessionId,
  				  sync_hdr->TreeId);
  	if (!tcon) {
  		kfree(cancelled);
  		return -ENOENT;
  	}
  
  	cancelled->fid.persistent_fid = rsp->PersistentFileId;
  	cancelled->fid.volatile_fid = rsp->VolatileFileId;
  	cancelled->tcon = tcon;
  	INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
  	queue_work(cifsiod_wq, &cancelled->work);
  
  	return 0;
  }
8bd68c6e4   Aurelien Aptel   CIFS: implement v...
802

8bd68c6e4   Aurelien Aptel   CIFS: implement v...
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
  /**
   * 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;
  
  	if (ses->server->tcpStatus == CifsGood) {
  		/* skip non smb311 connections */
  		if (ses->server->dialect != SMB311_PROT_ID)
  			return 0;
  
  		/* skip last sess setup response */
  		hdr = (struct smb2_sync_hdr *)iov[0].iov_base;
  		if (hdr->Flags & SMB2_FLAGS_SIGNED)
  			return 0;
  	}
  
  	rc = smb311_crypto_shash_allocate(ses->server);
  	if (rc)
  		return rc;
  
  	d = ses->server->secmech.sdescsha512;
  	rc = crypto_shash_init(&d->shash);
  	if (rc) {
  		cifs_dbg(VFS, "%s: could not init sha512 shash
  ", __func__);
  		return rc;
  	}
  
  	rc = crypto_shash_update(&d->shash, ses->preauth_sha_hash,
  				 SMB2_PREAUTH_HASH_SIZE);
  	if (rc) {
  		cifs_dbg(VFS, "%s: could not update sha512 shash
  ", __func__);
  		return rc;
  	}
  
  	for (i = 0; i < nvec; i++) {
  		rc = crypto_shash_update(&d->shash,
  					 iov[i].iov_base, iov[i].iov_len);
  		if (rc) {
  			cifs_dbg(VFS, "%s: could not update sha512 shash
  ",
  				 __func__);
  			return rc;
  		}
  	}
  
  	rc = crypto_shash_final(&d->shash, ses->preauth_sha_hash);
  	if (rc) {
  		cifs_dbg(VFS, "%s: could not finalize sha512 shash
  ",
  			 __func__);
  		return rc;
  	}
  
  	return 0;
  }