Blame view

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

093b2bdad   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Separate SM...
43
  	if ((shdr->ProtocolId == SMB2_PROTO_NUMBER) &&
9235d0987   Sachin Prabhu   Convert MessageID...
44
  	    (mid == wire_mid)) {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
45
  		if (shdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
46
47
48
  			return 0;
  		else {
  			/* only one valid case where server sends us request */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
49
  			if (shdr->Command == SMB2_OPLOCK_BREAK)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
50
51
  				return 0;
  			else
f96637be0   Joe Perches   [CIFS] cifs: Rena...
52
53
  				cifs_dbg(VFS, "Received Request not response
  ");
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
54
55
  		}
  	} else { /* bad signature or mid */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
56
  		if (shdr->ProtocolId != SMB2_PROTO_NUMBER)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
57
58
  			cifs_dbg(VFS, "Bad protocol string signature header %x
  ",
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
59
  				 le32_to_cpu(shdr->ProtocolId));
9235d0987   Sachin Prabhu   Convert MessageID...
60
  		if (mid != wire_mid)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
61
62
  			cifs_dbg(VFS, "Mids do not match: %llu and %llu
  ",
9235d0987   Sachin Prabhu   Convert MessageID...
63
  				 mid, wire_mid);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
64
  	}
9235d0987   Sachin Prabhu   Convert MessageID...
65
66
  	cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu
  ", wire_mid);
093b2bdad   Pavel Shilovsky   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   Fabian Frederick   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   Pavel Shilovsky   CIFS: Make demult...
90
  	/* BB CHECK this ... not listed in documentation */
bc09d141e   Fabian Frederick   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   Pavel Shilovsky   CIFS: Make demult...
97
  	/* BB FIXME can also be 44 for lease break */
bc09d141e   Fabian Frederick   fs/cifs: remove o...
98
  	/* SMB2_OPLOCK_BREAK */ cpu_to_le16(24)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
99
  };
639fd3819   Steve French   SMB3.1.1: remove ...
100
  #define SMB311_NEGPROT_BASE_SIZE (sizeof(struct smb2_sync_hdr) + sizeof(struct smb2_negotiate_rsp))
98170fb53   Ronnie Sahlberg   cifs: update smb2...
101
  static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
102
  			      __u32 non_ctxlen)
136ff1b4b   Steve French   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   Steve French   SMB3.1.1: remove ...
116
117
118
  	if (nc_offset + 1 < non_ctxlen) {
  		pr_warn_once("Invalid negotiate context offset %d
  ", nc_offset);
136ff1b4b   Steve French   SMB3: Fix length ...
119
  		return 0;
639fd3819   Steve French   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   Steve French   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   Joe Perches   cifs: Standardize...
132
133
  		pr_warn_once("negotiate context goes beyond end
  ");
136ff1b4b   Steve French   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   Steve French   SMB3: Fix length ...
144

093b2bdad   Pavel Shilovsky   CIFS: Make demult...
145
  int
98170fb53   Ronnie Sahlberg   cifs: update smb2...
146
  smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
147
  {
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
148
  	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
98170fb53   Ronnie Sahlberg   cifs: update smb2...
149
  	struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
373512ec5   Steve French   Prepare for encry...
150
  	__u64 mid;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
151
152
  	__u32 clc_len;  /* calculated length */
  	int command;
98170fb53   Ronnie Sahlberg   cifs: update smb2...
153
154
  	int pdu_size = sizeof(struct smb2_sync_pdu);
  	int hdr_size = sizeof(struct smb2_sync_hdr);
093b2bdad   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Separate SM...
160
  	if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
373512ec5   Steve French   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   Pavel Shilovsky   CIFS: Separate SM...
182
  	mid = le64_to_cpu(shdr->MessageId);
98170fb53   Ronnie Sahlberg   cifs: update smb2...
183
184
  	if (len < pdu_size) {
  		if ((len >= hdr_size)
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
185
  		    && (shdr->Status != 0)) {
093b2bdad   Pavel Shilovsky   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   Joe Perches   [CIFS] cifs: Rena...
193
194
  			cifs_dbg(VFS, "Length less than SMB header size
  ");
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
195
196
197
  		}
  		return 1;
  	}
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
198
  	if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
199
200
201
  		cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu
  ",
  			 mid);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
202
203
  		return 1;
  	}
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
204
  	if (check_smb2_hdr(shdr, mid))
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
205
  		return 1;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
206
  	if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
a0a3036b8   Joe Perches   cifs: Standardize...
207
208
  		cifs_dbg(VFS, "Invalid structure size %u
  ",
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
209
  			 le16_to_cpu(shdr->StructureSize));
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
210
211
  		return 1;
  	}
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
212
  	command = le16_to_cpu(shdr->Command);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
213
  	if (command >= NUMBER_OF_SMB2_COMMANDS) {
a0a3036b8   Joe Perches   cifs: Standardize...
214
215
  		cifs_dbg(VFS, "Invalid SMB2 command %d
  ", command);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
216
217
218
219
  		return 1;
  	}
  
  	if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
220
  		if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 ||
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
221
  		    pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) {
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
222
  			/* error packets have 9 byte structure size */
a0a3036b8   Joe Perches   cifs: Standardize...
223
224
  			cifs_dbg(VFS, "Invalid response size %u for command %d
  ",
f96637be0   Joe Perches   [CIFS] cifs: Rena...
225
  				 le16_to_cpu(pdu->StructureSize2), command);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
226
  			return 1;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
227
228
  		} else if (command == SMB2_OPLOCK_BREAK_HE
  			   && (shdr->Status == 0)
0822f5142   Pavel Shilovsky   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   Joe Perches   cifs: Standardize...
232
233
  			cifs_dbg(VFS, "Invalid response size %d for oplock break
  ",
f96637be0   Joe Perches   [CIFS] cifs: Rena...
234
  				 le16_to_cpu(pdu->StructureSize2));
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
235
  			return 1;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
236
237
  		}
  	}
98170fb53   Ronnie Sahlberg   cifs: update smb2...
238
  	clc_len = smb2_calc_size(buf, srvr);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
239

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

98170fb53   Ronnie Sahlberg   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   Pavel Shilovsky   CIFS: Implement f...
247
248
  		/* create failed on symlink */
  		if (command == SMB2_CREATE_HE &&
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
249
  		    shdr->Status == STATUS_STOPPED_ON_SYMLINK)
b42bf8882   Pavel Shilovsky   CIFS: Implement f...
250
  			return 0;
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
251
  		/* Windows 7 server returns 24 bytes more */
98170fb53   Ronnie Sahlberg   cifs: update smb2...
252
  		if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE)
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
253
  			return 0;
754789a1c   Steve French   [CIFS] Workaround...
254
  		/* server can return one byte more due to implied bcc[0] */
98170fb53   Ronnie Sahlberg   cifs: update smb2...
255
  		if (clc_len == len + 1)
741128608   Pavel Shilovsky   CIFS: Fix log mes...
256
  			return 0;
754789a1c   Steve French   [CIFS] Workaround...
257
258
  
  		/*
e6c47dd0d   Ronnie Sahlberg   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   Steve French   [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   Steve French   smb3: minor debug...
269
  		 * Some windows servers also pad up to 8 bytes when compounding.
754789a1c   Steve French   [CIFS] Workaround...
270
  		 */
037d05072   Steve French   smb3: remove conf...
271
  		if (clc_len < len)
754789a1c   Steve French   [CIFS] Workaround...
272
  			return 0;
037d05072   Steve French   smb3: remove conf...
273

25f257351   Steve French   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   Steve French   [CIFS] Workaround...
278

093b2bdad   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Add capabil...
315
  char *
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
316
  smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
317
318
319
320
321
  {
  	*off = 0;
  	*len = 0;
  
  	/* error responses do not have data area */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
322
  	if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
323
  	    (((struct smb2_err_rsp *)shdr)->StructureSize) ==
093b2bdad   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Separate SM...
332
  	switch (shdr->Command) {
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
333
  	case SMB2_NEGOTIATE:
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
334
  		*off = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
335
  		  ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferOffset);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
336
  		*len = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
337
  		  ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferLength);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
338
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
339
  	case SMB2_SESSION_SETUP:
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
340
  		*off = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
341
  		  ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
342
  		*len = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
343
  		  ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
344
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
345
  	case SMB2_CREATE:
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
346
  		*off = le32_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
347
  		    ((struct smb2_create_rsp *)shdr)->CreateContextsOffset);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
348
  		*len = le32_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
349
  		    ((struct smb2_create_rsp *)shdr)->CreateContextsLength);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
350
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
351
  	case SMB2_QUERY_INFO:
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
352
  		*off = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
353
  		    ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
354
  		*len = le32_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
355
  		    ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
356
357
  		break;
  	case SMB2_READ:
e4dc31fe9   Ronnie Sahlberg   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   Pavel Shilovsky   CIFS: Add SMB2 su...
361
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
362
  	case SMB2_QUERY_DIRECTORY:
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
363
  		*off = le16_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
364
  		  ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
365
  		*len = le32_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
366
  		  ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
367
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
368
  	case SMB2_IOCTL:
4a72dafa1   Steve French   SMB2 FSCTL and IO...
369
  		*off = le32_to_cpu(
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
370
371
372
  		  ((struct smb2_ioctl_rsp *)shdr)->OutputOffset);
  		*len = le32_to_cpu(
  		  ((struct smb2_ioctl_rsp *)shdr)->OutputCount);
4a72dafa1   Steve French   SMB2 FSCTL and IO...
373
  		break;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
374
  	case SMB2_CHANGE_NOTIFY:
8668115cf   Steve French   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   Pavel Shilovsky   CIFS: Make demult...
380
  	default:
8668115cf   Steve French   smb3: fix unneede...
381
382
  		cifs_dbg(VFS, "no length check for command %d
  ", le16_to_cpu(shdr->Command));
093b2bdad   Pavel Shilovsky   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   Joe Perches   [CIFS] cifs: Rena...
391
392
  		cifs_dbg(VFS, "offset %d too large, data area ignored
  ", *off);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
393
394
395
  		*len = 0;
  		*off = 0;
  	} else if (*off < 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
396
397
398
  		cifs_dbg(VFS, "negative offset %d to data invalid ignore data area
  ",
  			 *off);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
399
400
401
  		*off = 0;
  		*len = 0;
  	} else if (*len < 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
402
403
404
  		cifs_dbg(VFS, "negative data length %d invalid, data area ignored
  ",
  			 *len);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
405
406
  		*len = 0;
  	} else if (*len > 128 * 1024) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
407
408
  		cifs_dbg(VFS, "data area larger than 128K: %d
  ", *len);
093b2bdad   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Separate SM...
414
  		return (char *)shdr + *off;
093b2bdad   Pavel Shilovsky   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   Ronnie Sahlberg   cifs: update calc...
424
  smb2_calc_size(void *buf, struct TCP_Server_Info *srvr)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
425
  {
84f0cbfba   Ronnie Sahlberg   cifs: update smb2...
426
427
  	struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf;
  	struct smb2_sync_hdr *shdr = &pdu->sync_hdr;
093b2bdad   Pavel Shilovsky   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   Ronnie Sahlberg   cifs: remove head...
431
  	int len = le16_to_cpu(shdr->StructureSize);
093b2bdad   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Separate SM...
438
  	if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
439
  		goto calc_size_exit;
e4dc31fe9   Ronnie Sahlberg   cifs: change smb2...
440
  	smb2_get_data_area_len(&offset, &data_length, shdr);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
441
442
  	cifs_dbg(FYI, "SMB2 data length %d offset %d
  ", data_length, offset);
093b2bdad   Pavel Shilovsky   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   Ronnie Sahlberg   cifs: update smb2...
449
  		 * so we must add one to the calculation.
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
450
  		 */
1fc6ad2f1   Ronnie Sahlberg   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   Pavel Shilovsky   CIFS: Make demult...
455
456
  			data_length = 0;
  		} else {
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
457
  			len = offset + data_length;
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
458
459
460
  		}
  	}
  calc_size_exit:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
461
462
  	cifs_dbg(FYI, "SMB2 len %d
  ", len);
093b2bdad   Pavel Shilovsky   CIFS: Make demult...
463
464
  	return len;
  }
2503a0dba   Pavel Shilovsky   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   Steve French   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   Pavel Shilovsky   CIFS: Add SMB2 su...
481
482
483
484
  
  	/* Windows doesn't allow paths beginning with \ */
  	if (from[0] == '\\')
  		start_of_path = from + 1;
0fdfef9aa   Steve French   smb3: simplify co...
485

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

2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
494
  	to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
a4153cb1d   Steve French   Allow conversion ...
495
  				   cifs_sb->local_nls, map_type);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
496
497
  	return to;
  }
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
498

0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
499
500
501
  __le32
  smb2_get_lease_state(struct cifsInodeInfo *cinode)
  {
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
502
  	__le32 lease = 0;
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
503

53ef1016f   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Add SMB2.1 ...
511
  }
233839b1d   Pavel Shilovsky   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   Ronnie Sahlberg   cifs: add lease t...
524
  	int rc = 0;
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
525
526
527
  
  	rc = SMB2_lease_break(0, tlink_tcon(lw->tlink), lw->lease_key,
  			      lw->lease_state);
a93864d93   Ronnie Sahlberg   cifs: add lease t...
528

f96637be0   Joe Perches   [CIFS] cifs: Rena...
529
530
  	cifs_dbg(FYI, "Lease release rc %d
  ", rc);
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
531
532
533
  	cifs_put_tlink(lw->tlink);
  	kfree(lw);
  }
baf57b56d   Paul Aurich   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   Pavel Shilovsky   CIFS: Add SMB2.1 ...
552
  static bool
baf57b56d   Paul Aurich   cifs: Fix leak wh...
553
  smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp)
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
554
  {
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
555
556
557
  	__u8 lease_state;
  	struct list_head *tmp;
  	struct cifsFileInfo *cfile;
933d4b365   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Store lease...
561
  	lease_state = le32_to_cpu(rsp->NewLeaseState);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
562
563
564
  
  	list_for_each(tmp, &tcon->openFileList) {
  		cfile = list_entry(tmp, struct cifsFileInfo, tlist);
2b0143b5c   David Howells   VFS: normal files...
565
  		cinode = CIFS_I(d_inode(cfile->dentry));
933d4b365   Pavel Shilovsky   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   Steve French   [CIFS] Fix incorr...
573
574
  		cifs_dbg(FYI, "lease key match, lease break 0x%x
  ",
9bd454083   Pavel Shilovsky   CIFS: Properly pr...
575
  			 lease_state);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
576

933d4b365   Pavel Shilovsky   CIFS: Fix missing...
577
578
579
580
  		if (ack_req)
  			cfile->oplock_break_cancelled = false;
  		else
  			cfile->oplock_break_cancelled = true;
7b9b9edb4   Pavel Shilovsky   CIFS: Do not rese...
581
  		set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
9bd454083   Pavel Shilovsky   CIFS: Properly pr...
582
583
  		cfile->oplock_epoch = le16_to_cpu(rsp->Epoch);
  		cfile->oplock_level = lease_state;
7b9b9edb4   Pavel Shilovsky   CIFS: Do not rese...
584

b98749cac   Aurelien Aptel   CIFS: keep FileIn...
585
  		cifs_queue_oplock_break(cfile);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
586
587
  		return true;
  	}
baf57b56d   Paul Aurich   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   Pavel Shilovsky   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   Paul Aurich   cifs: Fix leak wh...
606
  			found = open;
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
607
608
609
610
  		}
  
  		cifs_dbg(FYI, "found in the pending open list
  ");
59b04c5df   Steve French   [CIFS] Fix incorr...
611
612
  		cifs_dbg(FYI, "lease key match, lease break 0x%x
  ",
9bd454083   Pavel Shilovsky   CIFS: Properly pr...
613
  			 lease_state);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
614
615
616
  
  		open->oplock = lease_state;
  	}
a93864d93   Ronnie Sahlberg   cifs: add lease t...
617

933d4b365   Pavel Shilovsky   CIFS: Fix missing...
618
619
620
621
622
  	return found;
  }
  
  static bool
  smb2_is_valid_lease_break(char *buffer)
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
623
624
625
  {
  	struct smb2_lease_break *rsp = (struct smb2_lease_break *)buffer;
  	struct list_head *tmp, *tmp1, *tmp2;
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
626
  	struct TCP_Server_Info *server;
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
627
628
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon;
baf57b56d   Paul Aurich   cifs: Fix leak wh...
629
  	struct cifs_pending_open *open;
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
630

f96637be0   Joe Perches   [CIFS] cifs: Rena...
631
632
  	cifs_dbg(FYI, "Checking for lease break
  ");
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
633
634
635
  
  	/* look up tcon based on tid & uid */
  	spin_lock(&cifs_tcp_ses_lock);
933d4b365   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Add SMB2.1 ...
638

933d4b365   Pavel Shilovsky   CIFS: Fix missing...
639
640
  		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 ...
641

933d4b365   Pavel Shilovsky   CIFS: Fix missing...
642
643
644
  			list_for_each(tmp2, &ses->tcon_list) {
  				tcon = list_entry(tmp2, struct cifs_tcon,
  						  tcon_list);
3afca265b   Steve French   Clarify locking o...
645
  				spin_lock(&tcon->open_file_lock);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
646
647
  				cifs_stats_inc(
  				    &tcon->stats.cifs_stats.num_oplock_brks);
baf57b56d   Paul Aurich   cifs: Fix leak wh...
648
  				if (smb2_tcon_has_lease(tcon, rsp)) {
3afca265b   Steve French   Clarify locking o...
649
  					spin_unlock(&tcon->open_file_lock);
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
650
651
  					spin_unlock(&cifs_tcp_ses_lock);
  					return true;
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
652
  				}
baf57b56d   Paul Aurich   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   Steve French   Clarify locking o...
669
  				spin_unlock(&tcon->open_file_lock);
a93864d93   Ronnie Sahlberg   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   Pavel Shilovsky   CIFS: Fix fast le...
682
  			}
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
683
684
685
  		}
  	}
  	spin_unlock(&cifs_tcp_ses_lock);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
686
687
  	cifs_dbg(FYI, "Can not process lease break - no lease matched
  ");
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
688
689
  	return false;
  }
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
690
691
692
  bool
  smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
  {
0d5a288d2   Ronnie Sahlberg   cifs: remove stru...
693
  	struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
983c88a49   Pavel Shilovsky   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   Joe Perches   [CIFS] cifs: Rena...
699
700
  	cifs_dbg(FYI, "Checking for oplock break
  ");
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
701

0d5a288d2   Ronnie Sahlberg   cifs: remove stru...
702
  	if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
703
  		return false;
12e8a2082   Steve French   Trivial endian fixes
704
  	if (rsp->StructureSize !=
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
705
  				smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
706
  		if (le16_to_cpu(rsp->StructureSize) == 44)
933d4b365   Pavel Shilovsky   CIFS: Fix missing...
707
  			return smb2_is_valid_lease_break(buffer);
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
708
709
  		else
  			return false;
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
710
  	}
59b04c5df   Steve French   [CIFS] Fix incorr...
711
712
  	cifs_dbg(FYI, "oplock level 0x%x
  ", rsp->OplockLevel);
983c88a49   Pavel Shilovsky   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   Pavel Shilovsky   CIFS: Fix SMB2 op...
718

983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
719
720
  		list_for_each(tmp1, &ses->tcon_list) {
  			tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
3afca265b   Steve French   Clarify locking o...
721
  			spin_lock(&tcon->open_file_lock);
983c88a49   Pavel Shilovsky   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   Joe Perches   [CIFS] cifs: Rena...
730
731
  				cifs_dbg(FYI, "file id match, oplock break
  ");
fa9c23624   Pavel Shilovsky   CIFS: Fix SMB2 op...
732
733
  				cifs_stats_inc(
  				    &tcon->stats.cifs_stats.num_oplock_brks);
2b0143b5c   David Howells   VFS: normal files...
734
  				cinode = CIFS_I(d_inode(cfile->dentry));
3afca265b   Steve French   Clarify locking o...
735
  				spin_lock(&cfile->file_info_lock);
18cceb6a7   Pavel Shilovsky   CIFS: Replace cli...
736
  				if (!CIFS_CACHE_WRITE(cinode) &&
983c88a49   Pavel Shilovsky   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   Sachin Prabhu   cifs: Wait for wr...
741
742
  				set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
  					&cinode->flags);
9bd454083   Pavel Shilovsky   CIFS: Properly pr...
743
744
  				cfile->oplock_epoch = 0;
  				cfile->oplock_level = rsp->OplockLevel;
3afca265b   Steve French   Clarify locking o...
745
  				spin_unlock(&cfile->file_info_lock);
b98749cac   Aurelien Aptel   CIFS: keep FileIn...
746
747
  
  				cifs_queue_oplock_break(cfile);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
748

3afca265b   Steve French   Clarify locking o...
749
  				spin_unlock(&tcon->open_file_lock);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
750
751
752
  				spin_unlock(&cifs_tcp_ses_lock);
  				return true;
  			}
3afca265b   Steve French   Clarify locking o...
753
  			spin_unlock(&tcon->open_file_lock);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
754
755
756
  		}
  	}
  	spin_unlock(&cifs_tcp_ses_lock);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
757
758
  	cifs_dbg(FYI, "Can not process oplock break for non-existent connection
  ");
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
759
760
  	return false;
  }
38bd49064   Sachin Prabhu   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   Ronnie Sahlberg   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   Sachin Prabhu   Handle mismatched...
777

87bc2376f   Ronnie Sahlberg   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   Sachin Prabhu   Handle mismatched...
783

87bc2376f   Ronnie Sahlberg   smb3: add debug m...
784
  	cifs_put_tcon(tcon);
38bd49064   Sachin Prabhu   Handle mismatched...
785
786
  	kfree(cancelled);
  }
87bc2376f   Ronnie Sahlberg   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   Pavel Shilovsky   CIFS: Close open ...
795
  static int
87bc2376f   Ronnie Sahlberg   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   Pavel Shilovsky   CIFS: Close open ...
798
799
  {
  	struct close_cancelled_open *cancelled;
0a5a98863   Paulo Alcantara (SUSE)   cifs: Fix memory ...
800
  	cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC);
9150c3adb   Pavel Shilovsky   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   Ronnie Sahlberg   smb3: add debug m...
807
808
  	cancelled->cmd = cmd;
  	cancelled->mid = mid;
9150c3adb   Pavel Shilovsky   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   Aurelien Aptel   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   Pavel Shilovsky   CIFS: Close open ...
839
840
  	tcon->tc_count++;
  	spin_unlock(&cifs_tcp_ses_lock);
87bc2376f   Ronnie Sahlberg   smb3: add debug m...
841
842
  	rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0,
  					 persistent_fid, volatile_fid);
9150c3adb   Pavel Shilovsky   CIFS: Close open ...
843
844
845
846
847
  	if (rc)
  		cifs_put_tcon(tcon);
  
  	return rc;
  }
38bd49064   Sachin Prabhu   Handle mismatched...
848
849
850
  int
  smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
  {
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
851
  	struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer;
38bd49064   Sachin Prabhu   Handle mismatched...
852
853
  	struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
  	struct cifs_tcon *tcon;
9150c3adb   Pavel Shilovsky   CIFS: Close open ...
854
  	int rc;
38bd49064   Sachin Prabhu   Handle mismatched...
855
856
857
858
  
  	if (sync_hdr->Command != SMB2_CREATE ||
  	    sync_hdr->Status != STATUS_SUCCESS)
  		return 0;
38bd49064   Sachin Prabhu   Handle mismatched...
859
860
  	tcon = smb2_find_smb_tcon(server, sync_hdr->SessionId,
  				  sync_hdr->TreeId);
9150c3adb   Pavel Shilovsky   CIFS: Close open ...
861
  	if (!tcon)
38bd49064   Sachin Prabhu   Handle mismatched...
862
  		return -ENOENT;
38bd49064   Sachin Prabhu   Handle mismatched...
863

87bc2376f   Ronnie Sahlberg   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   Pavel Shilovsky   CIFS: Close open ...
869
870
  	if (rc)
  		cifs_put_tcon(tcon);
38bd49064   Sachin Prabhu   Handle mismatched...
871

9150c3adb   Pavel Shilovsky   CIFS: Close open ...
872
  	return rc;
38bd49064   Sachin Prabhu   Handle mismatched...
873
  }
8bd68c6e4   Aurelien Aptel   CIFS: implement v...
874

8bd68c6e4   Aurelien Aptel   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   Aurelien Aptel   cifs: try opening...
887
  	struct TCP_Server_Info *server = cifs_ses_server(ses);
8bd68c6e4   Aurelien Aptel   CIFS: implement v...
888

d70e9fa55   Aurelien Aptel   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   Aurelien Aptel   CIFS: implement v...
893

d70e9fa55   Aurelien Aptel   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   Aurelien Aptel   CIFS: implement v...
911

d70e9fa55   Aurelien Aptel   cifs: try opening...
912
913
  ok:
  	rc = smb311_crypto_shash_allocate(server);
8bd68c6e4   Aurelien Aptel   CIFS: implement v...
914
915
  	if (rc)
  		return rc;
d70e9fa55   Aurelien Aptel   cifs: try opening...
916
  	d = server->secmech.sdescsha512;
8bd68c6e4   Aurelien Aptel   CIFS: implement v...
917
918
  	rc = crypto_shash_init(&d->shash);
  	if (rc) {
a0a3036b8   Joe Perches   cifs: Standardize...
919
920
  		cifs_dbg(VFS, "%s: Could not init sha512 shash
  ", __func__);
8bd68c6e4   Aurelien Aptel   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   Joe Perches   cifs: Standardize...
927
928
  		cifs_dbg(VFS, "%s: Could not update sha512 shash
  ", __func__);
8bd68c6e4   Aurelien Aptel   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   Joe Perches   cifs: Standardize...
936
937
  			cifs_dbg(VFS, "%s: Could not update sha512 shash
  ",
8bd68c6e4   Aurelien Aptel   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   Joe Perches   cifs: Standardize...
945
946
  		cifs_dbg(VFS, "%s: Could not finalize sha512 shash
  ",
8bd68c6e4   Aurelien Aptel   CIFS: implement v...
947
948
949
950
951
952
  			 __func__);
  		return rc;
  	}
  
  	return 0;
  }