Blame view

fs/cifs/smb2pdu.c 121 KB
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
1
2
3
  /*
   *   fs/cifs/smb2pdu.c
   *
2b80d049e   Steve French   Charge at least o...
4
   *   Copyright (C) International Business Machines  Corp., 2009, 2013
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
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
31
32
33
   *                 Etersoft, 2012
   *   Author(s): Steve French (sfrench@us.ibm.com)
   *              Pavel Shilovsky (pshilovsky@samba.org) 2012
   *
   *   Contains the routines for constructing the SMB2 PDUs themselves
   *
   *   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
   */
  
   /* SMB2 PDU handling routines here - except for leftovers (eg session setup) */
   /* Note that there are handle based routines which must be		      */
   /* treated slightly differently for reconnection purposes since we never     */
   /* want to reuse a stale file handle and only the caller knows the file info */
  
  #include <linux/fs.h>
  #include <linux/kernel.h>
  #include <linux/vfs.h>
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
34
  #include <linux/task_io_accounting_ops.h>
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
35
  #include <linux/uaccess.h>
c6e970a04   Andrew Lunn   net: break includ...
36
  #include <linux/uuid.h>
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
37
  #include <linux/pagemap.h>
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
38
39
40
41
42
43
44
45
46
47
  #include <linux/xattr.h>
  #include "smb2pdu.h"
  #include "cifsglob.h"
  #include "cifsacl.h"
  #include "cifsproto.h"
  #include "smb2proto.h"
  #include "cifs_unicode.h"
  #include "cifs_debug.h"
  #include "ntlmssp.h"
  #include "smb2status.h"
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
48
  #include "smb2glob.h"
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
49
  #include "cifspdu.h"
ceb1b0b9b   Steve French   [SMB3] Fix sec=kr...
50
  #include "cifs_spnego.h"
db223a590   Long Li   CIFS: SMBD: Upper...
51
  #include "smbdirect.h"
eccb4422c   Steve French   smb3: Add ftrace ...
52
  #include "trace.h"
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  
  /*
   *  The following table defines the expected "StructureSize" of SMB2 requests
   *  in order by SMB2 command.  This is similar to "wct" in SMB/CIFS requests.
   *
   *  Note that commands are defined in smb2pdu.h in le16 but the array below is
   *  indexed by command in host byte order.
   */
  static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
  	/* SMB2_NEGOTIATE */ 36,
  	/* SMB2_SESSION_SETUP */ 25,
  	/* SMB2_LOGOFF */ 4,
  	/* SMB2_TREE_CONNECT */	9,
  	/* SMB2_TREE_DISCONNECT */ 4,
  	/* SMB2_CREATE */ 57,
  	/* SMB2_CLOSE */ 24,
  	/* SMB2_FLUSH */ 24,
  	/* SMB2_READ */	49,
  	/* SMB2_WRITE */ 49,
  	/* SMB2_LOCK */	48,
  	/* SMB2_IOCTL */ 57,
  	/* SMB2_CANCEL */ 4,
  	/* SMB2_ECHO */ 4,
  	/* SMB2_QUERY_DIRECTORY */ 33,
  	/* SMB2_CHANGE_NOTIFY */ 32,
  	/* SMB2_QUERY_INFO */ 41,
  	/* SMB2_SET_INFO */ 33,
  	/* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */
  };
730928c8f   Ronnie Sahlberg   cifs: update smb2...
82
  int smb3_encryption_required(const struct cifs_tcon *tcon)
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
83
  {
ae6f8dd4d   Pavel Shilovsky   CIFS: Allow to sw...
84
85
  	if (!tcon)
  		return 0;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
86
87
88
  	if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
  	    (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
  		return 1;
ae6f8dd4d   Pavel Shilovsky   CIFS: Allow to sw...
89
90
91
  	if (tcon->seal &&
  	    (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
  		return 1;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
92
93
  	return 0;
  }
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
94
95
  
  static void
cb200bd62   Pavel Shilovsky   CIFS: Separate SM...
96
  smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd,
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
97
98
  		  const struct cifs_tcon *tcon)
  {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
99
100
101
  	shdr->ProtocolId = SMB2_PROTO_NUMBER;
  	shdr->StructureSize = cpu_to_le16(64);
  	shdr->Command = smb2_cmd;
7d414f396   Ross Lagerwall   cifs: Limit the o...
102
103
104
105
106
  	if (tcon && tcon->ses && tcon->ses->server) {
  		struct TCP_Server_Info *server = tcon->ses->server;
  
  		spin_lock(&server->req_lock);
  		/* Request up to 2 credits but don't go over the limit. */
141891f47   Steve French   SMB3: Add mount p...
107
  		if (server->credits >= server->max_credits)
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
108
  			shdr->CreditRequest = cpu_to_le16(0);
7d414f396   Ross Lagerwall   cifs: Limit the o...
109
  		else
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
110
  			shdr->CreditRequest = cpu_to_le16(
141891f47   Steve French   SMB3: Add mount p...
111
  				min_t(int, server->max_credits -
7d414f396   Ross Lagerwall   cifs: Limit the o...
112
113
114
  						server->credits, 2));
  		spin_unlock(&server->req_lock);
  	} else {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
115
  		shdr->CreditRequest = cpu_to_le16(2);
7d414f396   Ross Lagerwall   cifs: Limit the o...
116
  	}
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
117
  	shdr->ProcessId = cpu_to_le32((__u16)current->tgid);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
118
119
120
  
  	if (!tcon)
  		goto out;
2b80d049e   Steve French   Charge at least o...
121
122
  	/* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */
  	/* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */
1dc92c450   Steve French   [cifs] fix null p...
123
  	if ((tcon->ses) && (tcon->ses->server) &&
84ceeb962   Steve French   [CIFS] fix static...
124
  	    (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
125
  		shdr->CreditCharge = cpu_to_le16(1);
2b80d049e   Steve French   Charge at least o...
126
  	/* else CreditCharge MBZ */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
127
  	shdr->TreeId = tcon->tid;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
128
129
  	/* Uid is not converted */
  	if (tcon->ses)
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
130
  		shdr->SessionId = tcon->ses->Suid;
f87ab88b4   Steve French   [CIFS] Do not set...
131
132
133
134
135
136
137
138
139
140
141
142
  
  	/*
  	 * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have
  	 * to pass the path on the Open SMB prefixed by \\server\share.
  	 * Not sure when we would need to do the augmented path (if ever) and
  	 * setting this flag breaks the SMB2 open operation since it is
  	 * illegal to send an empty path name (without \\server\share prefix)
  	 * when the DFS flag is set in the SMB open header. We could
  	 * consider setting the flag on all operations other than open
  	 * but it is safer to net set it for now.
  	 */
  /*	if (tcon->share_flags & SHI1005_FLAGS_DFS)
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
143
  		shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */
f87ab88b4   Steve French   [CIFS] Do not set...
144

7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
145
  	if (tcon->ses && tcon->ses->server && tcon->ses->server->sign &&
5a77e75fe   Steve French   smb3: rename encr...
146
  	    !smb3_encryption_required(tcon))
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
147
  		shdr->Flags |= SMB2_FLAGS_SIGNED;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
148
  out:
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
149
150
151
152
153
154
  	return;
  }
  
  static int
  smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
  {
7ffbe6557   Paulo Alcantara   cifs: Fix infinit...
155
  	int rc;
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
156
157
158
159
160
161
162
163
164
165
  	struct nls_table *nls_codepage;
  	struct cifs_ses *ses;
  	struct TCP_Server_Info *server;
  
  	/*
  	 * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
  	 * check for tcp and smb session status done differently
  	 * for those three - in the calling routine.
  	 */
  	if (tcon == NULL)
7ffbe6557   Paulo Alcantara   cifs: Fix infinit...
166
  		return 0;
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
167
168
  
  	if (smb2_command == SMB2_TREE_CONNECT)
7ffbe6557   Paulo Alcantara   cifs: Fix infinit...
169
  		return 0;
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
170
171
172
173
174
175
176
177
178
179
  
  	if (tcon->tidStatus == CifsExiting) {
  		/*
  		 * only tree disconnect, open, and write,
  		 * (and ulogoff which does not have tcon)
  		 * are allowed as we start force umount.
  		 */
  		if ((smb2_command != SMB2_WRITE) &&
  		   (smb2_command != SMB2_CREATE) &&
  		   (smb2_command != SMB2_TREE_DISCONNECT)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
180
181
182
  			cifs_dbg(FYI, "can not send cmd %d while umounting
  ",
  				 smb2_command);
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  			return -ENODEV;
  		}
  	}
  	if ((!tcon->ses) || (tcon->ses->status == CifsExiting) ||
  	    (!tcon->ses->server))
  		return -EIO;
  
  	ses = tcon->ses;
  	server = ses->server;
  
  	/*
  	 * Give demultiplex thread up to 10 seconds to reconnect, should be
  	 * greater than cifs socket timeout which is 7 seconds
  	 */
  	while (server->tcpStatus == CifsNeedReconnect) {
  		/*
  		 * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE
  		 * here since they are implicitly done when session drops.
  		 */
  		switch (smb2_command) {
  		/*
  		 * BB Should we keep oplock break and add flush to exceptions?
  		 */
  		case SMB2_TREE_DISCONNECT:
  		case SMB2_CANCEL:
  		case SMB2_CLOSE:
  		case SMB2_OPLOCK_BREAK:
  			return -EAGAIN;
  		}
7ffbe6557   Paulo Alcantara   cifs: Fix infinit...
212
213
214
215
216
217
218
219
220
  		rc = wait_event_interruptible_timeout(server->response_q,
  						      (server->tcpStatus != CifsNeedReconnect),
  						      10 * HZ);
  		if (rc < 0) {
  			cifs_dbg(FYI, "%s: aborting reconnect due to a received"
  				 " signal by the process
  ", __func__);
  			return -ERESTARTSYS;
  		}
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
221
222
223
224
225
226
227
228
229
230
231
  
  		/* are we still trying to reconnect? */
  		if (server->tcpStatus != CifsNeedReconnect)
  			break;
  
  		/*
  		 * on "soft" mounts we wait once. Hard mounts keep
  		 * retrying until process is killed or server comes
  		 * back on-line
  		 */
  		if (!tcon->retry) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
232
233
  			cifs_dbg(FYI, "gave up waiting on reconnect in smb_init
  ");
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
234
235
236
237
238
  			return -EHOSTDOWN;
  		}
  	}
  
  	if (!tcon->ses->need_reconnect && !tcon->need_reconnect)
7ffbe6557   Paulo Alcantara   cifs: Fix infinit...
239
  		return 0;
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
240
241
242
243
244
245
246
247
  
  	nls_codepage = load_nls_default();
  
  	/*
  	 * need to prevent multiple threads trying to simultaneously reconnect
  	 * the same SMB session
  	 */
  	mutex_lock(&tcon->ses->session_mutex);
76e752701   Samuel Cabrero   cifs: Check for t...
248
249
250
251
252
253
254
255
256
257
258
  
  	/*
  	 * Recheck after acquire mutex. If another thread is negotiating
  	 * and the server never sends an answer the socket will be closed
  	 * and tcpStatus set to reconnect.
  	 */
  	if (server->tcpStatus == CifsNeedReconnect) {
  		rc = -EHOSTDOWN;
  		mutex_unlock(&tcon->ses->session_mutex);
  		goto out;
  	}
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
259
260
261
262
263
264
265
266
267
268
  	rc = cifs_negotiate_protocol(0, tcon->ses);
  	if (!rc && tcon->ses->need_reconnect)
  		rc = cifs_setup_session(0, tcon->ses, nls_codepage);
  
  	if (rc || !tcon->need_reconnect) {
  		mutex_unlock(&tcon->ses->session_mutex);
  		goto out;
  	}
  
  	cifs_mark_open_files_invalid(tcon);
96a988ffe   Pavel Shilovsky   CIFS: Fix a possi...
269
270
  	if (tcon->use_persistent)
  		tcon->need_reopen_files = true;
52ace1ef1   Steve French   fs/cifs: reopen p...
271

aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
272
273
  	rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage);
  	mutex_unlock(&tcon->ses->session_mutex);
52ace1ef1   Steve French   fs/cifs: reopen p...
274

f96637be0   Joe Perches   [CIFS] cifs: Rena...
275
276
  	cifs_dbg(FYI, "reconnect tcon rc = %d
  ", rc);
c318e6c26   Steve French   SMB3: Log at leas...
277
278
279
280
  	if (rc) {
  		/* If sess reconnected but tcon didn't, something strange ... */
  		printk_once(KERN_WARNING "reconnect tcon failed rc = %d
  ", rc);
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
281
  		goto out;
c318e6c26   Steve French   SMB3: Log at leas...
282
  	}
96a988ffe   Pavel Shilovsky   CIFS: Fix a possi...
283
284
285
  
  	if (smb2_command != SMB2_INTERNAL_CMD)
  		queue_delayed_work(cifsiod_wq, &server->reconnect, 0);
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
286
  	atomic_inc(&tconInfoReconnectCount);
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  out:
  	/*
  	 * Check if handle based operation so we know whether we can continue
  	 * or not without returning to caller to reset file handle.
  	 */
  	/*
  	 * BB Is flush done by server on drop of tcp session? Should we special
  	 * case it and skip above?
  	 */
  	switch (smb2_command) {
  	case SMB2_FLUSH:
  	case SMB2_READ:
  	case SMB2_WRITE:
  	case SMB2_LOCK:
  	case SMB2_IOCTL:
  	case SMB2_QUERY_DIRECTORY:
  	case SMB2_CHANGE_NOTIFY:
  	case SMB2_QUERY_INFO:
  	case SMB2_SET_INFO:
4772c7959   Pavel Shilovsky   CIFS: Fix missing...
306
  		rc = -EAGAIN;
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
307
308
  	}
  	unload_nls(nls_codepage);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
309
310
  	return rc;
  }
cb200bd62   Pavel Shilovsky   CIFS: Separate SM...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  static void
  fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf,
  	       unsigned int *total_len)
  {
  	struct smb2_sync_pdu *spdu = (struct smb2_sync_pdu *)buf;
  	/* lookup word count ie StructureSize from table */
  	__u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_command)];
  
  	/*
  	 * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of
  	 * largest operations (Create)
  	 */
  	memset(buf, 0, 256);
  
  	smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon);
  	spdu->StructureSize2 = cpu_to_le16(parmsize);
  
  	*total_len = parmsize + sizeof(struct smb2_sync_hdr);
  }
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
330
331
332
  /*
   * Allocate and return pointer to an SMB request hdr, and set basic
   * SMB information in the SMB header. If the return code is zero, this
305428acf   Ronnie Sahlberg   cifs: remove smal...
333
   * function must have filled in request_buf pointer.
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
334
335
   */
  static int
305428acf   Ronnie Sahlberg   cifs: remove smal...
336
337
  smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
  		    void **request_buf, unsigned int *total_len)
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
338
  {
cb200bd62   Pavel Shilovsky   CIFS: Separate SM...
339
  	int rc;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
340
341
342
343
344
345
  
  	rc = smb2_reconnect(smb2_command, tcon);
  	if (rc)
  		return rc;
  
  	/* BB eventually switch this to SMB2 specific small buf size */
f46ecbd97   Stefano Brivio   cifs: Fix slab-ou...
346
347
348
349
  	if (smb2_command == SMB2_SET_INFO)
  		*request_buf = cifs_buf_get();
  	else
  		*request_buf = cifs_small_buf_get();
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
350
351
352
353
  	if (*request_buf == NULL) {
  		/* BB should we add a retry in here if not a writepage? */
  		return -ENOMEM;
  	}
305428acf   Ronnie Sahlberg   cifs: remove smal...
354
355
356
  	fill_small_buf(smb2_command, tcon,
  		       (struct smb2_sync_hdr *)(*request_buf),
  		       total_len);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
357
358
  
  	if (tcon != NULL) {
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
359
360
  		uint16_t com_code = le16_to_cpu(smb2_command);
  		cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
361
362
363
364
365
  		cifs_stats_inc(&tcon->num_smbs_sent);
  	}
  
  	return rc;
  }
0fdfef9aa   Steve French   smb3: simplify co...
366

13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
367
368
  /* offset is sizeof smb2_negotiate_req but rounded up to 8 bytes */
  #define OFFSET_OF_NEG_CONTEXT 0x68  /* sizeof(struct smb2_negotiate_req) */
ebb3a9d4b   Steve French   Update negotiate ...
369
370
371
372
  
  
  #define SMB2_PREAUTH_INTEGRITY_CAPABILITIES	cpu_to_le16(1)
  #define SMB2_ENCRYPTION_CAPABILITIES		cpu_to_le16(2)
fcef0db6d   Steve French   smb3: add support...
373
  #define SMB2_POSIX_EXTENSIONS_AVAILABLE		cpu_to_le16(0x100)
ebb3a9d4b   Steve French   Update negotiate ...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  
  static void
  build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt)
  {
  	pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES;
  	pneg_ctxt->DataLength = cpu_to_le16(38);
  	pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1);
  	pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE);
  	get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE);
  	pneg_ctxt->HashAlgorithms = SMB2_PREAUTH_INTEGRITY_SHA512;
  }
  
  static void
  build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
  {
  	pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
23657ad73   Steve French   SMB3: Fix 3.11 en...
390
391
392
393
  	pneg_ctxt->DataLength = cpu_to_le16(4); /* Cipher Count + le16 cipher */
  	pneg_ctxt->CipherCount = cpu_to_le16(1);
  /* pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;*/ /* not supported yet */
  	pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_CCM;
ebb3a9d4b   Steve French   Update negotiate ...
394
395
396
  }
  
  static void
fcef0db6d   Steve French   smb3: add support...
397
398
399
400
401
402
403
  build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
  {
  	pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE;
  	pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
  }
  
  static void
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
404
405
  assemble_neg_contexts(struct smb2_negotiate_req *req,
  		      unsigned int *total_len)
ebb3a9d4b   Steve French   Update negotiate ...
406
  {
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
407
  	char *pneg_ctxt = (char *)req + OFFSET_OF_NEG_CONTEXT;
fcef0db6d   Steve French   smb3: add support...
408
  	unsigned int ctxt_len;
ebb3a9d4b   Steve French   Update negotiate ...
409

fcef0db6d   Steve French   smb3: add support...
410
  	*total_len += 2; /* Add 2 due to round to 8 byte boundary for 1st ctxt */
ebb3a9d4b   Steve French   Update negotiate ...
411
  	build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt);
fcef0db6d   Steve French   smb3: add support...
412
413
414
  	ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8;
  	*total_len += ctxt_len;
  	pneg_ctxt += ctxt_len;
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
415

ebb3a9d4b   Steve French   Update negotiate ...
416
  	build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt);
fcef0db6d   Steve French   smb3: add support...
417
418
419
420
421
422
  	ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_encryption_neg_context), 8) * 8;
  	*total_len += ctxt_len;
  	pneg_ctxt += ctxt_len;
  
  	build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
  	*total_len += sizeof(struct smb2_posix_neg_context);
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
423

fcef0db6d   Steve French   smb3: add support...
424
425
  	req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
  	req->NegotiateContextCount = cpu_to_le16(3);
ebb3a9d4b   Steve French   Update negotiate ...
426
  }
5100d8a3f   Steve French   SMB311: Improve c...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
  
  static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
  {
  	unsigned int len = le16_to_cpu(ctxt->DataLength);
  
  	/* If invalid preauth context warn but use what we requested, SHA-512 */
  	if (len < MIN_PREAUTH_CTXT_DATA_LEN) {
  		printk_once(KERN_WARNING "server sent bad preauth context
  ");
  		return;
  	}
  	if (le16_to_cpu(ctxt->HashAlgorithmCount) != 1)
  		printk_once(KERN_WARNING "illegal SMB3 hash algorithm count
  ");
  	if (ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
  		printk_once(KERN_WARNING "unknown SMB3 hash algorithm
  ");
  }
  
  static int decode_encrypt_ctx(struct TCP_Server_Info *server,
  			      struct smb2_encryption_neg_context *ctxt)
  {
  	unsigned int len = le16_to_cpu(ctxt->DataLength);
  
  	cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d
  ", len);
  	if (len < MIN_ENCRYPT_CTXT_DATA_LEN) {
  		printk_once(KERN_WARNING "server sent bad crypto ctxt len
  ");
  		return -EINVAL;
  	}
  
  	if (le16_to_cpu(ctxt->CipherCount) != 1) {
  		printk_once(KERN_WARNING "illegal SMB3.11 cipher count
  ");
  		return -EINVAL;
  	}
  	cifs_dbg(FYI, "SMB311 cipher type:%d
  ", le16_to_cpu(ctxt->Ciphers[0]));
  	if ((ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_CCM) &&
  	    (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_GCM)) {
  		printk_once(KERN_WARNING "invalid SMB3.11 cipher returned
  ");
  		return -EINVAL;
  	}
  	server->cipher_type = ctxt->Ciphers[0];
23657ad73   Steve French   SMB3: Fix 3.11 en...
473
  	server->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
5100d8a3f   Steve French   SMB311: Improve c...
474
475
476
477
  	return 0;
  }
  
  static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
977b61704   Ronnie Sahlberg   cifs: remove rfc1...
478
479
  				     struct TCP_Server_Info *server,
  				     unsigned int len_of_smb)
5100d8a3f   Steve French   SMB311: Improve c...
480
481
482
483
  {
  	struct smb2_neg_context *pctx;
  	unsigned int offset = le32_to_cpu(rsp->NegotiateContextOffset);
  	unsigned int ctxt_cnt = le16_to_cpu(rsp->NegotiateContextCount);
5100d8a3f   Steve French   SMB311: Improve c...
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  	unsigned int len_of_ctxts, i;
  	int rc = 0;
  
  	cifs_dbg(FYI, "decoding %d negotiate contexts
  ", ctxt_cnt);
  	if (len_of_smb <= offset) {
  		cifs_dbg(VFS, "Invalid response: negotiate context offset
  ");
  		return -EINVAL;
  	}
  
  	len_of_ctxts = len_of_smb - offset;
  
  	for (i = 0; i < ctxt_cnt; i++) {
  		int clen;
  		/* check that offset is not beyond end of SMB */
  		if (len_of_ctxts == 0)
  			break;
  
  		if (len_of_ctxts < sizeof(struct smb2_neg_context))
  			break;
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
505
  		pctx = (struct smb2_neg_context *)(offset + (char *)rsp);
5100d8a3f   Steve French   SMB311: Improve c...
506
507
508
509
510
511
512
513
514
515
  		clen = le16_to_cpu(pctx->DataLength);
  		if (clen > len_of_ctxts)
  			break;
  
  		if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES)
  			decode_preauth_context(
  				(struct smb2_preauth_neg_context *)pctx);
  		else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES)
  			rc = decode_encrypt_ctx(server,
  				(struct smb2_encryption_neg_context *)pctx);
fcef0db6d   Steve French   smb3: add support...
516
517
  		else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE)
  			server->posix_ext_supported = true;
5100d8a3f   Steve French   SMB311: Improve c...
518
519
520
521
522
523
524
525
526
527
528
529
530
531
  		else
  			cifs_dbg(VFS, "unknown negcontext of type %d ignored
  ",
  				le16_to_cpu(pctx->ContextType));
  
  		if (rc)
  			break;
  		/* offsets must be 8 byte aligned */
  		clen = (clen + 7) & ~0x7;
  		offset += clen + sizeof(struct smb2_neg_context);
  		len_of_ctxts -= clen;
  	}
  	return rc;
  }
ce558b0e1   Steve French   smb3: Add posix c...
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
  static struct create_posix *
  create_posix_buf(umode_t mode)
  {
  	struct create_posix *buf;
  
  	buf = kzalloc(sizeof(struct create_posix),
  			GFP_KERNEL);
  	if (!buf)
  		return NULL;
  
  	buf->ccontext.DataOffset =
  		cpu_to_le16(offsetof(struct create_posix, Mode));
  	buf->ccontext.DataLength = cpu_to_le32(4);
  	buf->ccontext.NameOffset =
  		cpu_to_le16(offsetof(struct create_posix, Name));
  	buf->ccontext.NameLength = cpu_to_le16(16);
  
  	/* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
  	buf->Name[0] = 0x93;
  	buf->Name[1] = 0xAD;
  	buf->Name[2] = 0x25;
  	buf->Name[3] = 0x50;
  	buf->Name[4] = 0x9C;
  	buf->Name[5] = 0xB4;
  	buf->Name[6] = 0x11;
  	buf->Name[7] = 0xE7;
  	buf->Name[8] = 0xB4;
  	buf->Name[9] = 0x23;
  	buf->Name[10] = 0x83;
  	buf->Name[11] = 0xDE;
  	buf->Name[12] = 0x96;
  	buf->Name[13] = 0x8B;
  	buf->Name[14] = 0xCD;
  	buf->Name[15] = 0x7C;
  	buf->Mode = cpu_to_le32(mode);
  	cifs_dbg(FYI, "mode on posix create 0%o", mode);
  	return buf;
  }
  
  static int
  add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
  {
  	struct smb2_create_req *req = iov[0].iov_base;
  	unsigned int num = *num_iovec;
  
  	iov[num].iov_base = create_posix_buf(mode);
  	if (iov[num].iov_base == NULL)
  		return -ENOMEM;
  	iov[num].iov_len = sizeof(struct create_posix);
  	if (!req->CreateContextsOffset)
  		req->CreateContextsOffset = cpu_to_le32(
  				sizeof(struct smb2_create_req) +
  				iov[num - 1].iov_len);
  	le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_posix));
  	*num_iovec = num + 1;
  	return 0;
  }
ebb3a9d4b   Steve French   Update negotiate ...
589

ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
  /*
   *
   *	SMB2 Worker functions follow:
   *
   *	The general structure of the worker functions is:
   *	1) Call smb2_init (assembles SMB2 header)
   *	2) Initialize SMB2 command specific fields in fixed length area of SMB
   *	3) Call smb_sendrcv2 (sends request on socket and waits for response)
   *	4) Decode SMB2 command specific fields in the fixed length area
   *	5) Decode variable length data area (if any for this SMB2 command type)
   *	6) Call free smb buffer
   *	7) return
   *
   */
  
  int
  SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
608
  	struct smb_rqst rqst;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
609
610
611
  	struct smb2_negotiate_req *req;
  	struct smb2_negotiate_rsp *rsp;
  	struct kvec iov[1];
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
612
  	struct kvec rsp_iov;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
613
614
  	int rc = 0;
  	int resp_buftype;
3534b8508   Jeff Layton   cifs: throw a war...
615
  	struct TCP_Server_Info *server = ses->server;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
616
617
618
  	int blob_offset, blob_length;
  	char *security_blob;
  	int flags = CIFS_NEG_OP;
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
619
  	unsigned int total_len;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
620

f96637be0   Joe Perches   [CIFS] cifs: Rena...
621
622
  	cifs_dbg(FYI, "Negotiate protocol
  ");
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
623

3534b8508   Jeff Layton   cifs: throw a war...
624
625
626
627
  	if (!server) {
  		WARN(1, "%s: server is NULL!
  ", __func__);
  		return -EIO;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
628
  	}
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
629
  	rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, (void **) &req, &total_len);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
630
631
  	if (rc)
  		return rc;
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
632
  	req->sync_hdr.SessionId = 0;
0fdfef9aa   Steve French   smb3: simplify co...
633

8bd68c6e4   Aurelien Aptel   CIFS: implement v...
634
635
  	memset(server->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
  	memset(ses->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
636

9764c02fc   Steve French   SMB3: Add support...
637
638
639
640
641
  	if (strcmp(ses->server->vals->version_string,
  		   SMB3ANY_VERSION_STRING) == 0) {
  		req->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
  		req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
  		req->DialectCount = cpu_to_le16(2);
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
642
  		total_len += 4;
9764c02fc   Steve French   SMB3: Add support...
643
644
645
646
647
648
  	} else if (strcmp(ses->server->vals->version_string,
  		   SMBDEFAULT_VERSION_STRING) == 0) {
  		req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
  		req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
  		req->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
  		req->DialectCount = cpu_to_le16(3);
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
649
  		total_len += 6;
9764c02fc   Steve French   SMB3: Add support...
650
651
652
653
  	} else {
  		/* otherwise send specific dialect */
  		req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id);
  		req->DialectCount = cpu_to_le16(1);
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
654
  		total_len += 2;
9764c02fc   Steve French   SMB3: Add support...
655
  	}
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
656
657
  
  	/* only one of SMB2 signing flags may be set in SMB2 request */
38d77c50b   Jeff Layton   cifs: track the e...
658
  	if (ses->sign)
9cd2e62c4   Steve French   Fix endian error ...
659
  		req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
38d77c50b   Jeff Layton   cifs: track the e...
660
  	else if (global_secflags & CIFSSEC_MAY_SIGN)
9cd2e62c4   Steve French   Fix endian error ...
661
  		req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
38d77c50b   Jeff Layton   cifs: track the e...
662
663
  	else
  		req->SecurityMode = 0;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
664

e4aa25e78   Steve French   [CIFS] Fix SMB2 n...
665
  	req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
666

3c5f9be10   Steve French   Do not send Clien...
667
668
669
  	/* ClientGUID must be zero for SMB2.02 dialect */
  	if (ses->server->vals->protocol_id == SMB20_PROT_ID)
  		memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE);
ebb3a9d4b   Steve French   Update negotiate ...
670
  	else {
3c5f9be10   Steve French   Do not send Clien...
671
672
  		memcpy(req->ClientGUID, server->client_guid,
  			SMB2_CLIENT_GUID_SIZE);
ebb3a9d4b   Steve French   Update negotiate ...
673
  		if (ses->server->vals->protocol_id == SMB311_PROT_ID)
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
674
  			assemble_neg_contexts(req, &total_len);
ebb3a9d4b   Steve French   Update negotiate ...
675
  	}
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
676
  	iov[0].iov_base = (char *)req;
13cacea7b   Ronnie Sahlberg   cifs: remove rfc1...
677
  	iov[0].iov_len = total_len;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
678

40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
679
680
681
682
683
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 1;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
684
685
  	cifs_small_buf_release(req);
  	rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
686
687
688
689
  	/*
  	 * No tcon so can't do
  	 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
  	 */
7e682f766   Steve French   Fix warning messa...
690
691
  	if (rc == -EOPNOTSUPP) {
  		cifs_dbg(VFS, "Dialect not supported by server. Consider "
9764c02fc   Steve French   SMB3: Add support...
692
  			"specifying vers=1.0 or vers=2.0 on mount for accessing"
7e682f766   Steve French   Fix warning messa...
693
694
695
696
  			" older servers
  ");
  		goto neg_exit;
  	} else if (rc != 0)
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
697
  		goto neg_exit;
9764c02fc   Steve French   SMB3: Add support...
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
  	if (strcmp(ses->server->vals->version_string,
  		   SMB3ANY_VERSION_STRING) == 0) {
  		if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
  			cifs_dbg(VFS,
  				"SMB2 dialect returned but not requested
  ");
  			return -EIO;
  		} else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
  			cifs_dbg(VFS,
  				"SMB2.1 dialect returned but not requested
  ");
  			return -EIO;
  		}
  	} else if (strcmp(ses->server->vals->version_string,
  		   SMBDEFAULT_VERSION_STRING) == 0) {
  		if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
  			cifs_dbg(VFS,
  				"SMB2 dialect returned but not requested
  ");
  			return -EIO;
  		} else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
  			/* ops set to 3.0 by default for default so update */
  			ses->server->ops = &smb21_operations;
  		}
590d08d3d   Steve French   SMB3: Fix endian ...
722
723
  	} else if (le16_to_cpu(rsp->DialectRevision) !=
  				ses->server->vals->protocol_id) {
9764c02fc   Steve French   SMB3: Add support...
724
725
726
  		/* if requested single dialect ensure returned dialect matched */
  		cifs_dbg(VFS, "Illegal 0x%x dialect returned: not requested
  ",
590d08d3d   Steve French   SMB3: Fix endian ...
727
  			le16_to_cpu(rsp->DialectRevision));
9764c02fc   Steve French   SMB3: Add support...
728
729
  		return -EIO;
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
730
731
  	cifs_dbg(FYI, "mode 0x%x
  ", rsp->SecurityMode);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
732

e4aa25e78   Steve French   [CIFS] Fix SMB2 n...
733
  	if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID))
f96637be0   Joe Perches   [CIFS] cifs: Rena...
734
735
  		cifs_dbg(FYI, "negotiated smb2.0 dialect
  ");
e4aa25e78   Steve French   [CIFS] Fix SMB2 n...
736
  	else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID))
f96637be0   Joe Perches   [CIFS] cifs: Rena...
737
738
  		cifs_dbg(FYI, "negotiated smb2.1 dialect
  ");
e4aa25e78   Steve French   [CIFS] Fix SMB2 n...
739
  	else if (rsp->DialectRevision == cpu_to_le16(SMB30_PROT_ID))
f96637be0   Joe Perches   [CIFS] cifs: Rena...
740
741
  		cifs_dbg(FYI, "negotiated smb3.0 dialect
  ");
20b6d8b42   Steve French   Add SMB3.02 diale...
742
743
744
  	else if (rsp->DialectRevision == cpu_to_le16(SMB302_PROT_ID))
  		cifs_dbg(FYI, "negotiated smb3.02 dialect
  ");
5f7fbf733   Steve French   Allow parsing ver...
745
746
747
  	else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID))
  		cifs_dbg(FYI, "negotiated smb3.1.1 dialect
  ");
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
748
  	else {
f799d6234   Steve French   Make dialect nego...
749
750
  		cifs_dbg(VFS, "Illegal dialect returned by server 0x%x
  ",
f96637be0   Joe Perches   [CIFS] cifs: Rena...
751
  			 le16_to_cpu(rsp->DialectRevision));
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
752
753
754
755
  		rc = -EIO;
  		goto neg_exit;
  	}
  	server->dialect = le16_to_cpu(rsp->DialectRevision);
8bd68c6e4   Aurelien Aptel   CIFS: implement v...
756
757
758
759
760
761
762
  	/*
  	 * Keep a copy of the hash after negprot. This hash will be
  	 * the starting hash value for all sessions made from this
  	 * server.
  	 */
  	memcpy(server->preauth_sha_hash, ses->preauth_sha_hash,
  	       SMB2_PREAUTH_HASH_SIZE);
0fdfef9aa   Steve French   smb3: simplify co...
763

e598d1d8f   Jeff Layton   cifs: track the f...
764
765
  	/* SMB2 only has an extended negflavor */
  	server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
2365c4eaf   Pavel Shilovsky   CIFS: Fix too big...
766
767
768
  	/* set it to the maximum buffer size value we can send with 1 credit */
  	server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize),
  			       SMB2_MAX_BUFFER_SIZE);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
769
770
  	server->max_read = le32_to_cpu(rsp->MaxReadSize);
  	server->max_write = le32_to_cpu(rsp->MaxWriteSize);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
771
  	server->sec_mode = le16_to_cpu(rsp->SecurityMode);
07108d0e7   Steve French   cifs: Add minor d...
772
773
774
775
  	if ((server->sec_mode & SMB2_SEC_MODE_FLAGS_ALL) != server->sec_mode)
  		cifs_dbg(FYI, "Server returned unexpected security mode 0x%x
  ",
  				server->sec_mode);
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
776
  	server->capabilities = le32_to_cpu(rsp->Capabilities);
29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
777
778
  	/* Internal types */
  	server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
779
780
  
  	security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
781
  					       (struct smb2_sync_hdr *)rsp);
5d875cc92   Steve French   When server doesn...
782
783
784
785
786
787
788
  	/*
  	 * See MS-SMB2 section 2.2.4: if no blob, client picks default which
  	 * for us will be
  	 *	ses->sectype = RawNTLMSSP;
  	 * but for time being this is our only auth choice so doesn't matter.
  	 * We just found a server which sets blob length to zero expecting raw.
  	 */
67dbea2ce   Pavel Shilovsky   CIFS: Fix SMB3 mo...
789
  	if (blob_length == 0) {
5d875cc92   Steve French   When server doesn...
790
791
  		cifs_dbg(FYI, "missing security blob on negprot
  ");
67dbea2ce   Pavel Shilovsky   CIFS: Fix SMB3 mo...
792
793
  		server->sec_ntlmssp = true;
  	}
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
794

38d77c50b   Jeff Layton   cifs: track the e...
795
  	rc = cifs_enable_signing(server, ses->sign);
9ddec5613   Jeff Layton   cifs: move handli...
796
797
  	if (rc)
  		goto neg_exit;
ceb1b0b9b   Steve French   [SMB3] Fix sec=kr...
798
  	if (blob_length) {
ebdd207e2   Steve French   decode_negTokenIn...
799
  		rc = decode_negTokenInit(security_blob, blob_length, server);
ceb1b0b9b   Steve French   [SMB3] Fix sec=kr...
800
801
802
803
  		if (rc == 1)
  			rc = 0;
  		else if (rc == 0)
  			rc = -EIO;
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
804
  	}
5100d8a3f   Steve French   SMB311: Improve c...
805

5100d8a3f   Steve French   SMB311: Improve c...
806
807
  	if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
  		if (rsp->NegotiateContextCount)
977b61704   Ronnie Sahlberg   cifs: remove rfc1...
808
809
  			rc = smb311_decode_neg_context(rsp, server,
  						       rsp_iov.iov_len);
5100d8a3f   Steve French   SMB311: Improve c...
810
811
812
813
  		else
  			cifs_dbg(VFS, "Missing expected negotiate contexts
  ");
  	}
ec2e4523f   Pavel Shilovsky   CIFS: Add capabil...
814
815
816
817
  neg_exit:
  	free_rsp_buf(resp_buftype, rsp);
  	return rc;
  }
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
818

ff1c038ad   Steve French   Check SMB3 dialec...
819
820
  int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
  {
2796d303e   Long Li   cifs: Allocate va...
821
822
  	int rc;
  	struct validate_negotiate_info_req *pneg_inbuf;
fe83bebc0   David Disseldorp   SMB: fix leak of ...
823
  	struct validate_negotiate_info_rsp *pneg_rsp = NULL;
ff1c038ad   Steve French   Check SMB3 dialec...
824
  	u32 rsplen;
9764c02fc   Steve French   SMB3: Add support...
825
  	u32 inbuflen; /* max of 4 dialects */
ff1c038ad   Steve French   Check SMB3 dialec...
826
827
828
  
  	cifs_dbg(FYI, "validate negotiate
  ");
8bd68c6e4   Aurelien Aptel   CIFS: implement v...
829
830
831
  	/* In SMB3.11 preauth integrity supersedes validate negotiate */
  	if (tcon->ses->server->dialect == SMB311_PROT_ID)
  		return 0;
ff1c038ad   Steve French   Check SMB3 dialec...
832
833
  	/*
  	 * validation ioctl must be signed, so no point sending this if we
0603c96f3   Steve French   SMB: Validate neg...
834
835
  	 * can not sign it (ie are not known user).  Even if signing is not
  	 * required (enabled but not negotiated), in those cases we selectively
ff1c038ad   Steve French   Check SMB3 dialec...
836
  	 * sign just this, the first and only signed request on a connection.
0603c96f3   Steve French   SMB: Validate neg...
837
  	 * Having validation of negotiate info  helps reduce attack vectors.
ff1c038ad   Steve French   Check SMB3 dialec...
838
  	 */
0603c96f3   Steve French   SMB: Validate neg...
839
  	if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
ff1c038ad   Steve French   Check SMB3 dialec...
840
  		return 0; /* validation requires signing */
0603c96f3   Steve French   SMB: Validate neg...
841
842
843
844
845
846
847
848
849
  	if (tcon->ses->user_name == NULL) {
  		cifs_dbg(FYI, "Can't validate negotiate: null user mount
  ");
  		return 0; /* validation requires signing */
  	}
  
  	if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
  		cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server
  ");
2796d303e   Long Li   cifs: Allocate va...
850
851
852
853
854
  	pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS);
  	if (!pneg_inbuf)
  		return -ENOMEM;
  
  	pneg_inbuf->Capabilities =
ff1c038ad   Steve French   Check SMB3 dialec...
855
  			cpu_to_le32(tcon->ses->server->vals->req_capabilities);
2796d303e   Long Li   cifs: Allocate va...
856
  	memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid,
39552ea81   Sachin Prabhu   cifs: Set client ...
857
  					SMB2_CLIENT_GUID_SIZE);
ff1c038ad   Steve French   Check SMB3 dialec...
858
859
  
  	if (tcon->ses->sign)
2796d303e   Long Li   cifs: Allocate va...
860
  		pneg_inbuf->SecurityMode =
ff1c038ad   Steve French   Check SMB3 dialec...
861
862
  			cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
  	else if (global_secflags & CIFSSEC_MAY_SIGN)
2796d303e   Long Li   cifs: Allocate va...
863
  		pneg_inbuf->SecurityMode =
ff1c038ad   Steve French   Check SMB3 dialec...
864
865
  			cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
  	else
2796d303e   Long Li   cifs: Allocate va...
866
  		pneg_inbuf->SecurityMode = 0;
ff1c038ad   Steve French   Check SMB3 dialec...
867

9764c02fc   Steve French   SMB3: Add support...
868
869
870
  
  	if (strcmp(tcon->ses->server->vals->version_string,
  		SMB3ANY_VERSION_STRING) == 0) {
2796d303e   Long Li   cifs: Allocate va...
871
872
873
  		pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
  		pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
  		pneg_inbuf->DialectCount = cpu_to_le16(2);
9764c02fc   Steve French   SMB3: Add support...
874
  		/* structure is big enough for 3 dialects, sending only 2 */
2796d303e   Long Li   cifs: Allocate va...
875
876
  		inbuflen = sizeof(*pneg_inbuf) -
  				sizeof(pneg_inbuf->Dialects[0]);
9764c02fc   Steve French   SMB3: Add support...
877
878
  	} else if (strcmp(tcon->ses->server->vals->version_string,
  		SMBDEFAULT_VERSION_STRING) == 0) {
2796d303e   Long Li   cifs: Allocate va...
879
880
881
882
  		pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
  		pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
  		pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
  		pneg_inbuf->DialectCount = cpu_to_le16(3);
9764c02fc   Steve French   SMB3: Add support...
883
  		/* structure is big enough for 3 dialects */
2796d303e   Long Li   cifs: Allocate va...
884
  		inbuflen = sizeof(*pneg_inbuf);
9764c02fc   Steve French   SMB3: Add support...
885
886
  	} else {
  		/* otherwise specific dialect was requested */
2796d303e   Long Li   cifs: Allocate va...
887
  		pneg_inbuf->Dialects[0] =
9764c02fc   Steve French   SMB3: Add support...
888
  			cpu_to_le16(tcon->ses->server->vals->protocol_id);
2796d303e   Long Li   cifs: Allocate va...
889
  		pneg_inbuf->DialectCount = cpu_to_le16(1);
9764c02fc   Steve French   SMB3: Add support...
890
  		/* structure is big enough for 3 dialects, sending only 1 */
2796d303e   Long Li   cifs: Allocate va...
891
892
  		inbuflen = sizeof(*pneg_inbuf) -
  				sizeof(pneg_inbuf->Dialects[0]) * 2;
9764c02fc   Steve French   SMB3: Add support...
893
  	}
ff1c038ad   Steve French   Check SMB3 dialec...
894
895
896
  
  	rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
  		FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
2796d303e   Long Li   cifs: Allocate va...
897
  		(char *)pneg_inbuf, inbuflen, (char **)&pneg_rsp, &rsplen);
d579b4eae   Namjae Jeon   cifs: Accept vali...
898
899
900
901
902
903
904
905
906
  	if (rc == -EOPNOTSUPP) {
  		/*
  		 * Old Windows versions or Netapp SMB server can return
  		 * not supported error. Client should accept it.
  		 */
  		cifs_dbg(VFS, "Server does not support validate negotiate
  ");
  		return 0;
  	} else if (rc != 0) {
ff1c038ad   Steve French   Check SMB3 dialec...
907
908
  		cifs_dbg(VFS, "validate protocol negotiate failed: %d
  ", rc);
2796d303e   Long Li   cifs: Allocate va...
909
910
  		rc = -EIO;
  		goto out_free_inbuf;
ff1c038ad   Steve French   Check SMB3 dialec...
911
  	}
2796d303e   Long Li   cifs: Allocate va...
912
913
  	rc = -EIO;
  	if (rsplen != sizeof(*pneg_rsp)) {
7db0a6efd   Steve French   SMB3: Work around...
914
915
916
917
918
  		cifs_dbg(VFS, "invalid protocol negotiate response size: %d
  ",
  			 rsplen);
  
  		/* relax check since Mac returns max bufsize allowed on ioctl */
2796d303e   Long Li   cifs: Allocate va...
919
920
  		if (rsplen > CIFSMaxBufSize || rsplen < sizeof(*pneg_rsp))
  			goto out_free_rsp;
ff1c038ad   Steve French   Check SMB3 dialec...
921
922
923
  	}
  
  	/* check validate negotiate info response matches what we got earlier */
9aca7e454   Daniel N Pettersson   cifs: Fix autoneg...
924
  	if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect))
ff1c038ad   Steve French   Check SMB3 dialec...
925
926
927
928
929
930
931
932
933
934
935
936
  		goto vneg_out;
  
  	if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode))
  		goto vneg_out;
  
  	/* do not validate server guid because not saved at negprot time yet */
  
  	if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND |
  	      SMB2_LARGE_FILES) != tcon->ses->server->capabilities)
  		goto vneg_out;
  
  	/* validate negotiate successful */
2796d303e   Long Li   cifs: Allocate va...
937
  	rc = 0;
ff1c038ad   Steve French   Check SMB3 dialec...
938
939
  	cifs_dbg(FYI, "validate negotiate info successful
  ");
2796d303e   Long Li   cifs: Allocate va...
940
  	goto out_free_rsp;
ff1c038ad   Steve French   Check SMB3 dialec...
941
942
943
944
  
  vneg_out:
  	cifs_dbg(VFS, "protocol revalidation - security settings mismatch
  ");
2796d303e   Long Li   cifs: Allocate va...
945
  out_free_rsp:
fe83bebc0   David Disseldorp   SMB: fix leak of ...
946
  	kfree(pneg_rsp);
2796d303e   Long Li   cifs: Allocate va...
947
948
949
  out_free_inbuf:
  	kfree(pneg_inbuf);
  	return rc;
ff1c038ad   Steve French   Check SMB3 dialec...
950
  }
ef65aaede   Sachin Prabhu   smb2: Enforce sec...
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
  enum securityEnum
  smb2_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
  {
  	switch (requested) {
  	case Kerberos:
  	case RawNTLMSSP:
  		return requested;
  	case NTLMv2:
  		return RawNTLMSSP;
  	case Unspecified:
  		if (server->sec_ntlmssp &&
  			(global_secflags & CIFSSEC_MAY_NTLMSSP))
  			return RawNTLMSSP;
  		if ((server->sec_kerberos || server->sec_mskerberos) &&
  			(global_secflags & CIFSSEC_MAY_KRB5))
  			return Kerberos;
  		/* Fallthrough */
  	default:
  		return Unspecified;
  	}
  }
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
  struct SMB2_sess_data {
  	unsigned int xid;
  	struct cifs_ses *ses;
  	struct nls_table *nls_cp;
  	void (*func)(struct SMB2_sess_data *);
  	int result;
  	u64 previous_session;
  
  	/* we will send the SMB in three pieces:
  	 * a fixed length beginning part, an optional
  	 * SPNEGO blob (which can be zero length), and a
  	 * last part which will include the strings
  	 * and rest of bcc area. This allows us to avoid
  	 * a large buffer 17K allocation
  	 */
  	int buf0_type;
  	struct kvec iov[2];
  };
  
  static int
  SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
  {
  	int rc;
  	struct cifs_ses *ses = sess_data->ses;
  	struct smb2_sess_setup_req *req;
  	struct TCP_Server_Info *server = ses->server;
88ea5cb7d   Ronnie Sahlberg   cifs: remove rfc1...
998
  	unsigned int total_len;
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
999

88ea5cb7d   Ronnie Sahlberg   cifs: remove rfc1...
1000
1001
  	rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, (void **) &req,
  			     &total_len);
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1002
1003
  	if (rc)
  		return rc;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
1004
  	/* First session, not a reauthenticate */
88ea5cb7d   Ronnie Sahlberg   cifs: remove rfc1...
1005
  	req->sync_hdr.SessionId = 0;
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1006
1007
1008
1009
1010
  
  	/* if reconnect, we need to send previous sess id, otherwise it is 0 */
  	req->PreviousSessionId = sess_data->previous_session;
  
  	req->Flags = 0; /* MBZ */
d409014e4   Steve French   smb3: increase in...
1011
1012
1013
  
  	/* enough to enable echos and oplocks and one max size write */
  	req->sync_hdr.CreditRequest = cpu_to_le16(130);
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
  
  	/* only one of SMB2 signing flags may be set in SMB2 request */
  	if (server->sign)
  		req->SecurityMode = SMB2_NEGOTIATE_SIGNING_REQUIRED;
  	else if (global_secflags & CIFSSEC_MAY_SIGN) /* one flag unlike MUST_ */
  		req->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED;
  	else
  		req->SecurityMode = 0;
  
  	req->Capabilities = 0;
  	req->Channel = 0; /* MBZ */
  
  	sess_data->iov[0].iov_base = (char *)req;
88ea5cb7d   Ronnie Sahlberg   cifs: remove rfc1...
1027
1028
  	/* 1 for pad */
  	sess_data->iov[0].iov_len = total_len - 1;
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
  	/*
  	 * This variable will be used to clear the buffer
  	 * allocated above in case of any error in the calling function.
  	 */
  	sess_data->buf0_type = CIFS_SMALL_BUFFER;
  
  	return 0;
  }
  
  static void
  SMB2_sess_free_buffer(struct SMB2_sess_data *sess_data)
  {
  	free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base);
  	sess_data->buf0_type = CIFS_NO_BUFFER;
  }
  
  static int
  SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
  {
  	int rc;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
1049
  	struct smb_rqst rqst;
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1050
  	struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base;
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
1051
  	struct kvec rsp_iov = { NULL, 0 };
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1052
1053
1054
  
  	/* Testing shows that buffer offset must be at location of Buffer[0] */
  	req->SecurityBufferOffset =
88ea5cb7d   Ronnie Sahlberg   cifs: remove rfc1...
1055
  		cpu_to_le16(sizeof(struct smb2_sess_setup_req) - 1 /* pad */);
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1056
  	req->SecurityBufferLength = cpu_to_le16(sess_data->iov[1].iov_len);
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
1057
1058
1059
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = sess_data->iov;
  	rqst.rq_nvec = 2;
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1060

40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
1061
1062
1063
  	/* BB add code to build os and lm fields */
  	rc = cifs_send_recv(sess_data->xid, sess_data->ses,
  			    &rqst,
88ea5cb7d   Ronnie Sahlberg   cifs: remove rfc1...
1064
1065
  			    &sess_data->buf0_type,
  			    CIFS_LOG_ERROR | CIFS_NEG_OP, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
1066
1067
  	cifs_small_buf_release(sess_data->iov[0].iov_base);
  	memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
  
  	return rc;
  }
  
  static int
  SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
  {
  	int rc = 0;
  	struct cifs_ses *ses = sess_data->ses;
  
  	mutex_lock(&ses->server->srv_mutex);
cabfb3680   Pavel Shilovsky   CIFS: Enable encr...
1079
  	if (ses->server->ops->generate_signingkey) {
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1080
  		rc = ses->server->ops->generate_signingkey(ses);
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1081
1082
1083
1084
1085
  		if (rc) {
  			cifs_dbg(FYI,
  				"SMB3 session key generation failed
  ");
  			mutex_unlock(&ses->server->srv_mutex);
cabfb3680   Pavel Shilovsky   CIFS: Enable encr...
1086
  			return rc;
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
  		}
  	}
  	if (!ses->server->session_estab) {
  		ses->server->sequence_number = 0x2;
  		ses->server->session_estab = true;
  	}
  	mutex_unlock(&ses->server->srv_mutex);
  
  	cifs_dbg(FYI, "SMB2/3 session established successfully
  ");
  	spin_lock(&GlobalMid_Lock);
  	ses->status = CifsGood;
  	ses->need_reconnect = false;
  	spin_unlock(&GlobalMid_Lock);
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
  	return rc;
  }
  
  #ifdef CONFIG_CIFS_UPCALL
  static void
  SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
  {
  	int rc;
  	struct cifs_ses *ses = sess_data->ses;
  	struct cifs_spnego_msg *msg;
  	struct key *spnego_key = NULL;
  	struct smb2_sess_setup_rsp *rsp = NULL;
  
  	rc = SMB2_sess_alloc_buffer(sess_data);
  	if (rc)
  		goto out;
  
  	spnego_key = cifs_get_spnego_key(ses);
  	if (IS_ERR(spnego_key)) {
  		rc = PTR_ERR(spnego_key);
  		spnego_key = NULL;
  		goto out;
  	}
  
  	msg = spnego_key->payload.data[0];
  	/*
  	 * check version field to make sure that cifs.upcall is
  	 * sending us a response in an expected form
  	 */
  	if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
  		cifs_dbg(VFS,
  			  "bad cifs.upcall version. Expected %d got %d",
  			  CIFS_SPNEGO_UPCALL_VERSION, msg->version);
  		rc = -EKEYREJECTED;
  		goto out_put_spnego_key;
  	}
  
  	ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
  					 GFP_KERNEL);
  	if (!ses->auth_key.response) {
  		cifs_dbg(VFS,
  			"Kerberos can't allocate (%u bytes) memory",
  			msg->sesskey_len);
  		rc = -ENOMEM;
  		goto out_put_spnego_key;
  	}
  	ses->auth_key.len = msg->sesskey_len;
  
  	sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
  	sess_data->iov[1].iov_len = msg->secblob_len;
  
  	rc = SMB2_sess_sendreceive(sess_data);
  	if (rc)
  		goto out_put_spnego_key;
  
  	rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
1157
  	ses->Suid = rsp->sync_hdr.SessionId;
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1158
1159
  
  	ses->session_flags = le16_to_cpu(rsp->SessionFlags);
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
  
  	rc = SMB2_sess_establish_session(sess_data);
  out_put_spnego_key:
  	key_invalidate(spnego_key);
  	key_put(spnego_key);
  out:
  	sess_data->result = rc;
  	sess_data->func = NULL;
  	SMB2_sess_free_buffer(sess_data);
  }
  #else
  static void
  SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
  {
  	cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!
  ");
  	sess_data->result = -EOPNOTSUPP;
  	sess_data->func = NULL;
  }
  #endif
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1180
1181
1182
1183
1184
  static void
  SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data);
  
  static void
  SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1185
  {
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1186
1187
  	int rc;
  	struct cifs_ses *ses = sess_data->ses;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1188
  	struct smb2_sess_setup_rsp *rsp = NULL;
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1189
  	char *ntlmssp_blob = NULL;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1190
  	bool use_spnego = false; /* else use raw ntlmssp */
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1191
  	u16 blob_length = 0;
d4e63bd6e   Shirish Pargaonkar   cifs: Process pos...
1192
1193
  
  	/*
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1194
1195
1196
1197
  	 * If memory allocation is successful, caller of this function
  	 * frees it.
  	 */
  	ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1198
1199
1200
1201
  	if (!ses->ntlmssp) {
  		rc = -ENOMEM;
  		goto out_err;
  	}
5c234aa5e   Shirish Pargaonkar   cifs: Add a varia...
1202
  	ses->ntlmssp->sesskey_per_smbsess = true;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1203

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1204
  	rc = SMB2_sess_alloc_buffer(sess_data);
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1205
  	if (rc)
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1206
  		goto out_err;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1207

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1208
1209
1210
1211
1212
1213
  	ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE),
  			       GFP_KERNEL);
  	if (ntlmssp_blob == NULL) {
  		rc = -ENOMEM;
  		goto out;
  	}
c2afb8147   Steve French   Set previous sess...
1214

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
  	build_ntlmssp_negotiate_blob(ntlmssp_blob, ses);
  	if (use_spnego) {
  		/* BB eventually need to add this */
  		cifs_dbg(VFS, "spnego not supported for SMB2 yet
  ");
  		rc = -EOPNOTSUPP;
  		goto out;
  	} else {
  		blob_length = sizeof(struct _NEGOTIATE_MESSAGE);
  		/* with raw NTLMSSP we don't encapsulate in SPNEGO */
  	}
  	sess_data->iov[1].iov_base = ntlmssp_blob;
  	sess_data->iov[1].iov_len = blob_length;
c2afb8147   Steve French   Set previous sess...
1228

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1229
1230
  	rc = SMB2_sess_sendreceive(sess_data);
  	rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1231

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1232
1233
  	/* If true, rc here is expected and not an error */
  	if (sess_data->buf0_type != CIFS_NO_BUFFER &&
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
1234
  		rsp->sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1235
  		rc = 0;
38d77c50b   Jeff Layton   cifs: track the e...
1236

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1237
1238
  	if (rc)
  		goto out;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1239

1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
1240
  	if (offsetof(struct smb2_sess_setup_rsp, Buffer) !=
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1241
1242
1243
1244
  			le16_to_cpu(rsp->SecurityBufferOffset)) {
  		cifs_dbg(VFS, "Invalid security buffer offset %d
  ",
  			le16_to_cpu(rsp->SecurityBufferOffset));
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1245
  		rc = -EIO;
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1246
  		goto out;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1247
  	}
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1248
1249
1250
1251
  	rc = decode_ntlmssp_challenge(rsp->Buffer,
  			le16_to_cpu(rsp->SecurityBufferLength), ses);
  	if (rc)
  		goto out;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1252

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1253
1254
  	cifs_dbg(FYI, "rawntlmssp session setup challenge phase
  ");
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1255

5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1256

49f466bdb   Ronnie Sahlberg   cifs: remove stru...
1257
  	ses->Suid = rsp->sync_hdr.SessionId;
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1258
  	ses->session_flags = le16_to_cpu(rsp->SessionFlags);
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
  
  out:
  	kfree(ntlmssp_blob);
  	SMB2_sess_free_buffer(sess_data);
  	if (!rc) {
  		sess_data->result = 0;
  		sess_data->func = SMB2_sess_auth_rawntlmssp_authenticate;
  		return;
  	}
  out_err:
  	kfree(ses->ntlmssp);
  	ses->ntlmssp = NULL;
  	sess_data->result = rc;
  	sess_data->func = NULL;
  }
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1274

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
  static void
  SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
  {
  	int rc;
  	struct cifs_ses *ses = sess_data->ses;
  	struct smb2_sess_setup_req *req;
  	struct smb2_sess_setup_rsp *rsp = NULL;
  	unsigned char *ntlmssp_blob = NULL;
  	bool use_spnego = false; /* else use raw ntlmssp */
  	u16 blob_length = 0;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1285

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1286
1287
1288
  	rc = SMB2_sess_alloc_buffer(sess_data);
  	if (rc)
  		goto out;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1289

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1290
  	req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base;
88ea5cb7d   Ronnie Sahlberg   cifs: remove rfc1...
1291
  	req->sync_hdr.SessionId = ses->Suid;
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1292
1293
1294
1295
1296
1297
1298
  
  	rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses,
  					sess_data->nls_cp);
  	if (rc) {
  		cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d
  ", rc);
  		goto out;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1299
  	}
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1300
1301
1302
1303
1304
1305
1306
1307
1308
  	if (use_spnego) {
  		/* BB eventually need to add this */
  		cifs_dbg(VFS, "spnego not supported for SMB2 yet
  ");
  		rc = -EOPNOTSUPP;
  		goto out;
  	}
  	sess_data->iov[1].iov_base = ntlmssp_blob;
  	sess_data->iov[1].iov_len = blob_length;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1309

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1310
1311
1312
1313
1314
  	rc = SMB2_sess_sendreceive(sess_data);
  	if (rc)
  		goto out;
  
  	rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
1315
  	ses->Suid = rsp->sync_hdr.SessionId;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1316
  	ses->session_flags = le16_to_cpu(rsp->SessionFlags);
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1317

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1318
1319
1320
1321
1322
1323
1324
1325
1326
  	rc = SMB2_sess_establish_session(sess_data);
  out:
  	kfree(ntlmssp_blob);
  	SMB2_sess_free_buffer(sess_data);
  	kfree(ses->ntlmssp);
  	ses->ntlmssp = NULL;
  	sess_data->result = rc;
  	sess_data->func = NULL;
  }
d4e63bd6e   Shirish Pargaonkar   cifs: Process pos...
1327

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1328
1329
1330
  static int
  SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data)
  {
ef65aaede   Sachin Prabhu   smb2: Enforce sec...
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
  	int type;
  
  	type = smb2_select_sectype(ses->server, ses->sectype);
  	cifs_dbg(FYI, "sess setup type %d
  ", type);
  	if (type == Unspecified) {
  		cifs_dbg(VFS,
  			"Unable to select appropriate authentication method!");
  		return -EINVAL;
  	}
d4e63bd6e   Shirish Pargaonkar   cifs: Process pos...
1341

ef65aaede   Sachin Prabhu   smb2: Enforce sec...
1342
  	switch (type) {
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1343
1344
1345
1346
1347
1348
1349
  	case Kerberos:
  		sess_data->func = SMB2_auth_kerberos;
  		break;
  	case RawNTLMSSP:
  		sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate;
  		break;
  	default:
ef65aaede   Sachin Prabhu   smb2: Enforce sec...
1350
1351
  		cifs_dbg(VFS, "secType %d not supported!
  ", type);
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1352
  		return -EOPNOTSUPP;
d4e63bd6e   Shirish Pargaonkar   cifs: Process pos...
1353
  	}
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
  	return 0;
  }
  
  int
  SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
  		const struct nls_table *nls_cp)
  {
  	int rc = 0;
  	struct TCP_Server_Info *server = ses->server;
  	struct SMB2_sess_data *sess_data;
  
  	cifs_dbg(FYI, "Session Setup
  ");
  
  	if (!server) {
  		WARN(1, "%s: server is NULL!
  ", __func__);
  		return -EIO;
d4e63bd6e   Shirish Pargaonkar   cifs: Process pos...
1372
  	}
d4e63bd6e   Shirish Pargaonkar   cifs: Process pos...
1373

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
  	sess_data = kzalloc(sizeof(struct SMB2_sess_data), GFP_KERNEL);
  	if (!sess_data)
  		return -ENOMEM;
  
  	rc = SMB2_select_sec(ses, sess_data);
  	if (rc)
  		goto out;
  	sess_data->xid = xid;
  	sess_data->ses = ses;
  	sess_data->buf0_type = CIFS_NO_BUFFER;
  	sess_data->nls_cp = (struct nls_table *) nls_cp;
b2adf22fd   Steve French   smb3: on reconnec...
1385
  	sess_data->previous_session = ses->Suid;
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1386

8bd68c6e4   Aurelien Aptel   CIFS: implement v...
1387
1388
1389
1390
1391
  	/*
  	 * Initialize the session hash with the server one.
  	 */
  	memcpy(ses->preauth_sha_hash, ses->server->preauth_sha_hash,
  	       SMB2_PREAUTH_HASH_SIZE);
8bd68c6e4   Aurelien Aptel   CIFS: implement v...
1392

166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1393
1394
  	while (sess_data->func)
  		sess_data->func(sess_data);
c721c3895   Steve French   SMB3: Warn user i...
1395
1396
1397
  	if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign))
  		cifs_dbg(VFS, "signing requested but authenticated as guest
  ");
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1398
  	rc = sess_data->result;
166cea4dc   Sachin Prabhu   SMB2: Separate Ra...
1399
  out:
3baf1a7b9   Sachin Prabhu   SMB2: Separate Ke...
1400
1401
  	kfree(sess_data);
  	return rc;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1402
1403
1404
1405
1406
  }
  
  int
  SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
1407
  	struct smb_rqst rqst;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1408
1409
1410
  	struct smb2_logoff_req *req; /* response is also trivial struct */
  	int rc = 0;
  	struct TCP_Server_Info *server;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
1411
  	int flags = 0;
45305eda6   Ronnie Sahlberg   cifs: remove rfc1...
1412
1413
1414
1415
  	unsigned int total_len;
  	struct kvec iov[1];
  	struct kvec rsp_iov;
  	int resp_buf_type;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1416

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1417
1418
  	cifs_dbg(FYI, "disconnect session %p
  ", ses);
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1419
1420
1421
1422
1423
  
  	if (ses && (ses->server))
  		server = ses->server;
  	else
  		return -EIO;
eb4c7df6c   Shirish Pargaonkar   cifs: Avoid umoun...
1424
1425
1426
  	/* no need to send SMB logoff if uid already closed due to reconnect */
  	if (ses->need_reconnect)
  		goto smb2_session_already_dead;
45305eda6   Ronnie Sahlberg   cifs: remove rfc1...
1427
  	rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, (void **) &req, &total_len);
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1428
1429
1430
1431
  	if (rc)
  		return rc;
  
  	 /* since no tcon, smb2_init can not do this, so do here */
45305eda6   Ronnie Sahlberg   cifs: remove rfc1...
1432
  	req->sync_hdr.SessionId = ses->Suid;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
1433
1434
1435
1436
  
  	if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
  		flags |= CIFS_TRANSFORM_REQ;
  	else if (server->sign)
45305eda6   Ronnie Sahlberg   cifs: remove rfc1...
1437
1438
1439
1440
1441
1442
  		req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
  
  	flags |= CIFS_NO_RESP;
  
  	iov[0].iov_base = (char *)req;
  	iov[0].iov_len = total_len;
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1443

40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
1444
1445
1446
1447
1448
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 1;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
1449
  	cifs_small_buf_release(req);
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1450
1451
1452
1453
  	/*
  	 * No tcon so can't do
  	 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
  	 */
eb4c7df6c   Shirish Pargaonkar   cifs: Avoid umoun...
1454
1455
  
  smb2_session_already_dead:
5478f9ba9   Pavel Shilovsky   CIFS: Add session...
1456
1457
  	return rc;
  }
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1458
1459
1460
  
  static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code)
  {
d60622eb5   Pavel Shilovsky   CIFS: Allow SMB2 ...
1461
  	cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_failed[code]);
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1462
1463
1464
  }
  
  #define MAX_SHARENAME_LENGTH (255 /* server */ + 80 /* share */ + 1 /* NULL */)
de9f68df6   Steve French   [CIFS] Set copych...
1465
1466
1467
1468
1469
1470
1471
  /* These are similar values to what Windows uses */
  static inline void init_copy_chunk_defaults(struct cifs_tcon *tcon)
  {
  	tcon->max_chunks = 256;
  	tcon->max_bytes_chunk = 1048576;
  	tcon->max_bytes_copy = 16777216;
  }
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1472
1473
1474
1475
  int
  SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
  	  struct cifs_tcon *tcon, const struct nls_table *cp)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
1476
  	struct smb_rqst rqst;
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1477
1478
1479
  	struct smb2_tree_connect_req *req;
  	struct smb2_tree_connect_rsp *rsp = NULL;
  	struct kvec iov[2];
db3b5474f   Aurélien Aptel   CIFS: Fix NULL po...
1480
  	struct kvec rsp_iov = { NULL, 0 };
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1481
1482
1483
  	int rc = 0;
  	int resp_buftype;
  	int unc_path_len;
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1484
  	__le16 *unc_path = NULL;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
1485
  	int flags = 0;
661bb943a   Ronnie Sahlberg   cifs: remove rfc1...
1486
  	unsigned int total_len;
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1487

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1488
1489
  	cifs_dbg(FYI, "TCON
  ");
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1490

68a6afa7f   Christos Gkekas   cifs: Clean up un...
1491
  	if (!(ses->server) || !tree)
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1492
  		return -EIO;
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
  	unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
  	if (unc_path == NULL)
  		return -ENOMEM;
  
  	unc_path_len = cifs_strtoUTF16(unc_path, tree, strlen(tree), cp) + 1;
  	unc_path_len *= 2;
  	if (unc_path_len < 2) {
  		kfree(unc_path);
  		return -EINVAL;
  	}
806a28efe   Jan-Marek Glogowski   Reset TreeId to z...
1503
  	/* SMB2 TREE_CONNECT request must be called with TreeId == 0 */
b327a717e   Aurelien Aptel   CIFS: make IPC a ...
1504
  	tcon->tid = 0;
806a28efe   Jan-Marek Glogowski   Reset TreeId to z...
1505

661bb943a   Ronnie Sahlberg   cifs: remove rfc1...
1506
1507
  	rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, (void **) &req,
  			     &total_len);
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1508
1509
1510
1511
  	if (rc) {
  		kfree(unc_path);
  		return rc;
  	}
5a77e75fe   Steve French   smb3: rename encr...
1512
  	if (smb3_encryption_required(tcon))
ae6f8dd4d   Pavel Shilovsky   CIFS: Allow to sw...
1513
  		flags |= CIFS_TRANSFORM_REQ;
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1514
1515
  
  	iov[0].iov_base = (char *)req;
661bb943a   Ronnie Sahlberg   cifs: remove rfc1...
1516
1517
  	/* 1 for pad */
  	iov[0].iov_len = total_len - 1;
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1518
1519
1520
  
  	/* Testing shows that buffer offset must be at location of Buffer[0] */
  	req->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req)
661bb943a   Ronnie Sahlberg   cifs: remove rfc1...
1521
  			- 1 /* pad */);
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1522
1523
1524
  	req->PathLength = cpu_to_le16(unc_path_len - 2);
  	iov[1].iov_base = unc_path;
  	iov[1].iov_len = unc_path_len;
14c52acaa   Ronnie Sahlberg   cifs: allow guest...
1525
1526
1527
  	/*
  	 * 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1
  	 * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1
38bd575b9   Steve French   SMB3: Fix SMB3.1....
1528
  	 * (Samba servers don't always set the flag so also check if null user)
14c52acaa   Ronnie Sahlberg   cifs: allow guest...
1529
  	 */
6188f28bf   Steve French   Tree connect for ...
1530
  	if ((ses->server->dialect == SMB311_PROT_ID) &&
14c52acaa   Ronnie Sahlberg   cifs: allow guest...
1531
  	    !smb3_encryption_required(tcon) &&
38bd575b9   Steve French   SMB3: Fix SMB3.1....
1532
1533
1534
  	    !(ses->session_flags &
  		    (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) &&
  	    ((ses->user_name != NULL) || (ses->sectype == Kerberos)))
6188f28bf   Steve French   Tree connect for ...
1535
  		req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
1536
1537
1538
1539
1540
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 2;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
1541
1542
  	cifs_small_buf_release(req);
  	rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base;
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1543
1544
1545
1546
1547
1548
1549
1550
  
  	if (rc != 0) {
  		if (tcon) {
  			cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE);
  			tcon->need_reconnect = true;
  		}
  		goto tcon_error_exit;
  	}
cd1230070   Christophe JAILLET   SMB2: Fix share t...
1551
1552
  	switch (rsp->ShareType) {
  	case SMB2_SHARE_TYPE_DISK:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1553
1554
  		cifs_dbg(FYI, "connection to disk share
  ");
cd1230070   Christophe JAILLET   SMB2: Fix share t...
1555
1556
  		break;
  	case SMB2_SHARE_TYPE_PIPE:
b327a717e   Aurelien Aptel   CIFS: make IPC a ...
1557
  		tcon->pipe = true;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1558
1559
  		cifs_dbg(FYI, "connection to pipe share
  ");
cd1230070   Christophe JAILLET   SMB2: Fix share t...
1560
1561
  		break;
  	case SMB2_SHARE_TYPE_PRINT:
b327a717e   Aurelien Aptel   CIFS: make IPC a ...
1562
  		tcon->print = true;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1563
1564
  		cifs_dbg(FYI, "connection to printer
  ");
cd1230070   Christophe JAILLET   SMB2: Fix share t...
1565
1566
  		break;
  	default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1567
1568
  		cifs_dbg(VFS, "unknown share type %d
  ", rsp->ShareType);
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1569
1570
1571
1572
1573
  		rc = -EOPNOTSUPP;
  		goto tcon_error_exit;
  	}
  
  	tcon->share_flags = le32_to_cpu(rsp->ShareFlags);
769ee6a40   Steve French   Add ability to di...
1574
  	tcon->capabilities = rsp->Capabilities; /* we keep caps little endian */
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1575
1576
1577
  	tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
  	tcon->tidStatus = CifsGood;
  	tcon->need_reconnect = false;
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
1578
  	tcon->tid = rsp->sync_hdr.TreeId;
46b51d083   Zhao Hongjiang   cifs: using strlc...
1579
  	strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1580
1581
1582
  
  	if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
  	    ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1583
1584
  		cifs_dbg(VFS, "DFS capability contradicts DFS flag
  ");
ae6f8dd4d   Pavel Shilovsky   CIFS: Allow to sw...
1585
1586
1587
1588
1589
  
  	if (tcon->seal &&
  	    !(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
  		cifs_dbg(VFS, "Encryption is requested but not supported
  ");
de9f68df6   Steve French   [CIFS] Set copych...
1590
  	init_copy_chunk_defaults(tcon);
ff1c038ad   Steve French   Check SMB3 dialec...
1591
1592
  	if (tcon->ses->server->ops->validate_negotiate)
  		rc = tcon->ses->server->ops->validate_negotiate(xid, tcon);
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1593
1594
1595
1596
1597
1598
  tcon_exit:
  	free_rsp_buf(resp_buftype, rsp);
  	kfree(unc_path);
  	return rc;
  
  tcon_error_exit:
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
1599
  	if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1600
1601
  		cifs_dbg(VFS, "BAD_NETWORK_NAME: %s
  ", tree);
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1602
1603
1604
1605
1606
1607
1608
  	}
  	goto tcon_exit;
  }
  
  int
  SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
1609
  	struct smb_rqst rqst;
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1610
1611
  	struct smb2_tree_disconnect_req *req; /* response is trivial */
  	int rc = 0;
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1612
  	struct cifs_ses *ses = tcon->ses;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
1613
  	int flags = 0;
4eecf4cfe   Ronnie Sahlberg   cifs: remove rfc1...
1614
1615
1616
1617
  	unsigned int total_len;
  	struct kvec iov[1];
  	struct kvec rsp_iov;
  	int resp_buf_type;
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1618

f96637be0   Joe Perches   [CIFS] cifs: Rena...
1619
1620
  	cifs_dbg(FYI, "Tree Disconnect
  ");
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1621

68a6afa7f   Christos Gkekas   cifs: Clean up un...
1622
  	if (!ses || !(ses->server))
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1623
1624
1625
1626
  		return -EIO;
  
  	if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
  		return 0;
4eecf4cfe   Ronnie Sahlberg   cifs: remove rfc1...
1627
1628
  	rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, (void **) &req,
  			     &total_len);
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1629
1630
  	if (rc)
  		return rc;
5a77e75fe   Steve French   smb3: rename encr...
1631
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
1632
  		flags |= CIFS_TRANSFORM_REQ;
4eecf4cfe   Ronnie Sahlberg   cifs: remove rfc1...
1633
1634
1635
1636
  	flags |= CIFS_NO_RESP;
  
  	iov[0].iov_base = (char *)req;
  	iov[0].iov_len = total_len;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
1637
1638
1639
1640
1641
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 1;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
1642
  	cifs_small_buf_release(req);
faaf946a7   Pavel Shilovsky   CIFS: Add tree co...
1643
1644
1645
1646
1647
  	if (rc)
  		cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE);
  
  	return rc;
  }
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
1648

b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
1649

63eb3def3   Pavel Shilovsky   CIFS: Request dur...
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
  static struct create_durable *
  create_durable_buf(void)
  {
  	struct create_durable *buf;
  
  	buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL);
  	if (!buf)
  		return NULL;
  
  	buf->ccontext.DataOffset = cpu_to_le16(offsetof
9cbc0b733   Pavel Shilovsky   CIFS: Reconnect d...
1660
  					(struct create_durable, Data));
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
1661
1662
1663
1664
  	buf->ccontext.DataLength = cpu_to_le32(16);
  	buf->ccontext.NameOffset = cpu_to_le16(offsetof
  				(struct create_durable, Name));
  	buf->ccontext.NameLength = cpu_to_le16(4);
12197a7fd   Steve French   Clarify SMB2/SMB3...
1665
  	/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
1666
1667
1668
1669
1670
1671
  	buf->Name[0] = 'D';
  	buf->Name[1] = 'H';
  	buf->Name[2] = 'n';
  	buf->Name[3] = 'Q';
  	return buf;
  }
9cbc0b733   Pavel Shilovsky   CIFS: Reconnect d...
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
  static struct create_durable *
  create_reconnect_durable_buf(struct cifs_fid *fid)
  {
  	struct create_durable *buf;
  
  	buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL);
  	if (!buf)
  		return NULL;
  
  	buf->ccontext.DataOffset = cpu_to_le16(offsetof
  					(struct create_durable, Data));
  	buf->ccontext.DataLength = cpu_to_le32(16);
  	buf->ccontext.NameOffset = cpu_to_le16(offsetof
  				(struct create_durable, Name));
  	buf->ccontext.NameLength = cpu_to_le16(4);
  	buf->Data.Fid.PersistentFileId = fid->persistent_fid;
  	buf->Data.Fid.VolatileFileId = fid->volatile_fid;
12197a7fd   Steve French   Clarify SMB2/SMB3...
1689
  	/* SMB2_CREATE_DURABLE_HANDLE_RECONNECT is "DHnC" */
9cbc0b733   Pavel Shilovsky   CIFS: Reconnect d...
1690
1691
1692
1693
1694
1695
  	buf->Name[0] = 'D';
  	buf->Name[1] = 'H';
  	buf->Name[2] = 'n';
  	buf->Name[3] = 'C';
  	return buf;
  }
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
1696
  static __u8
42873b0a2   Pavel Shilovsky   CIFS: Respect epo...
1697
  parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
96164ab2d   Ronnie Sahlberg   cifs: store the l...
1698
  		  unsigned int *epoch, char *lease_key)
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
1699
1700
  {
  	char *data_offset;
b5c7cde3f   Pavel Shilovsky   CIFS: Move parsin...
1701
  	struct create_context *cc;
deb7deff2   Justin Maggard   cifs: fix out-of-...
1702
1703
  	unsigned int next;
  	unsigned int remaining;
fd5543963   Pavel Shilovsky   CIFS: Fix lease c...
1704
  	char *name;
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
1705

1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
1706
  	data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
deb7deff2   Justin Maggard   cifs: fix out-of-...
1707
  	remaining = le32_to_cpu(rsp->CreateContextsLength);
b5c7cde3f   Pavel Shilovsky   CIFS: Move parsin...
1708
  	cc = (struct create_context *)data_offset;
deb7deff2   Justin Maggard   cifs: fix out-of-...
1709
  	while (remaining >= sizeof(struct create_context)) {
b5c7cde3f   Pavel Shilovsky   CIFS: Move parsin...
1710
  		name = le16_to_cpu(cc->NameOffset) + (char *)cc;
deb7deff2   Justin Maggard   cifs: fix out-of-...
1711
1712
  		if (le16_to_cpu(cc->NameLength) == 4 &&
  		    strncmp(name, "RqLs", 4) == 0)
96164ab2d   Ronnie Sahlberg   cifs: store the l...
1713
1714
  			return server->ops->parse_lease_buf(cc, epoch,
  							    lease_key);
deb7deff2   Justin Maggard   cifs: fix out-of-...
1715
1716
1717
1718
1719
1720
1721
  
  		next = le32_to_cpu(cc->Next);
  		if (!next)
  			break;
  		remaining -= next;
  		cc = (struct create_context *)((char *)cc + next);
  	}
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
1722

b5c7cde3f   Pavel Shilovsky   CIFS: Move parsin...
1723
  	return 0;
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
1724
  }
d22cbfecb   Pavel Shilovsky   CIFS: Simplify SM...
1725
  static int
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
1726
  add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
729c0c9dd   Stefano Brivio   cifs: Fix stack o...
1727
  		  unsigned int *num_iovec, u8 *lease_key, __u8 *oplock)
d22cbfecb   Pavel Shilovsky   CIFS: Simplify SM...
1728
1729
1730
  {
  	struct smb2_create_req *req = iov[0].iov_base;
  	unsigned int num = *num_iovec;
729c0c9dd   Stefano Brivio   cifs: Fix stack o...
1731
  	iov[num].iov_base = server->ops->create_lease_buf(lease_key, *oplock);
d22cbfecb   Pavel Shilovsky   CIFS: Simplify SM...
1732
1733
  	if (iov[num].iov_base == NULL)
  		return -ENOMEM;
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
1734
  	iov[num].iov_len = server->vals->create_lease_size;
d22cbfecb   Pavel Shilovsky   CIFS: Simplify SM...
1735
1736
1737
  	req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
  	if (!req->CreateContextsOffset)
  		req->CreateContextsOffset = cpu_to_le32(
4f33bc358   Ronnie Sahlberg   cifs: remove rfc1...
1738
  				sizeof(struct smb2_create_req) +
d22cbfecb   Pavel Shilovsky   CIFS: Simplify SM...
1739
  				iov[num - 1].iov_len);
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
1740
1741
  	le32_add_cpu(&req->CreateContextsLength,
  		     server->vals->create_lease_size);
d22cbfecb   Pavel Shilovsky   CIFS: Simplify SM...
1742
1743
1744
  	*num_iovec = num + 1;
  	return 0;
  }
b56eae4df   Steve French   [SMB3] Send durab...
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
  static struct create_durable_v2 *
  create_durable_v2_buf(struct cifs_fid *pfid)
  {
  	struct create_durable_v2 *buf;
  
  	buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL);
  	if (!buf)
  		return NULL;
  
  	buf->ccontext.DataOffset = cpu_to_le16(offsetof
  					(struct create_durable_v2, dcontext));
  	buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_context_v2));
  	buf->ccontext.NameOffset = cpu_to_le16(offsetof
  				(struct create_durable_v2, Name));
  	buf->ccontext.NameLength = cpu_to_le16(4);
  
  	buf->dcontext.Timeout = 0; /* Should this be configurable by workload */
  	buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
fa70b87cc   Steve French   SMB3: GUIDs shoul...
1763
  	generate_random_uuid(buf->dcontext.CreateGuid);
b56eae4df   Steve French   [SMB3] Send durab...
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
  	memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
  
  	/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
  	buf->Name[0] = 'D';
  	buf->Name[1] = 'H';
  	buf->Name[2] = '2';
  	buf->Name[3] = 'Q';
  	return buf;
  }
  
  static struct create_durable_handle_reconnect_v2 *
  create_reconnect_durable_v2_buf(struct cifs_fid *fid)
  {
  	struct create_durable_handle_reconnect_v2 *buf;
  
  	buf = kzalloc(sizeof(struct create_durable_handle_reconnect_v2),
  			GFP_KERNEL);
  	if (!buf)
  		return NULL;
  
  	buf->ccontext.DataOffset =
  		cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
  				     dcontext));
  	buf->ccontext.DataLength =
  		cpu_to_le32(sizeof(struct durable_reconnect_context_v2));
  	buf->ccontext.NameOffset =
  		cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
  			    Name));
  	buf->ccontext.NameLength = cpu_to_le16(4);
  
  	buf->dcontext.Fid.PersistentFileId = fid->persistent_fid;
  	buf->dcontext.Fid.VolatileFileId = fid->volatile_fid;
  	buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
  	memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16);
  
  	/* SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is "DH2C" */
  	buf->Name[0] = 'D';
  	buf->Name[1] = 'H';
  	buf->Name[2] = '2';
  	buf->Name[3] = 'C';
  	return buf;
  }
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
1806
  static int
b56eae4df   Steve French   [SMB3] Send durab...
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
  add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec,
  		    struct cifs_open_parms *oparms)
  {
  	struct smb2_create_req *req = iov[0].iov_base;
  	unsigned int num = *num_iovec;
  
  	iov[num].iov_base = create_durable_v2_buf(oparms->fid);
  	if (iov[num].iov_base == NULL)
  		return -ENOMEM;
  	iov[num].iov_len = sizeof(struct create_durable_v2);
  	if (!req->CreateContextsOffset)
  		req->CreateContextsOffset =
4f33bc358   Ronnie Sahlberg   cifs: remove rfc1...
1819
  			cpu_to_le32(sizeof(struct smb2_create_req) +
b56eae4df   Steve French   [SMB3] Send durab...
1820
1821
  								iov[1].iov_len);
  	le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable_v2));
b56eae4df   Steve French   [SMB3] Send durab...
1822
1823
1824
1825
1826
1827
  	*num_iovec = num + 1;
  	return 0;
  }
  
  static int
  add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec,
9cbc0b733   Pavel Shilovsky   CIFS: Reconnect d...
1828
  		    struct cifs_open_parms *oparms)
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
1829
1830
1831
  {
  	struct smb2_create_req *req = iov[0].iov_base;
  	unsigned int num = *num_iovec;
b56eae4df   Steve French   [SMB3] Send durab...
1832
1833
1834
1835
1836
1837
1838
1839
1840
  	/* indicate that we don't need to relock the file */
  	oparms->reconnect = false;
  
  	iov[num].iov_base = create_reconnect_durable_v2_buf(oparms->fid);
  	if (iov[num].iov_base == NULL)
  		return -ENOMEM;
  	iov[num].iov_len = sizeof(struct create_durable_handle_reconnect_v2);
  	if (!req->CreateContextsOffset)
  		req->CreateContextsOffset =
4f33bc358   Ronnie Sahlberg   cifs: remove rfc1...
1841
  			cpu_to_le32(sizeof(struct smb2_create_req) +
b56eae4df   Steve French   [SMB3] Send durab...
1842
1843
1844
  								iov[1].iov_len);
  	le32_add_cpu(&req->CreateContextsLength,
  			sizeof(struct create_durable_handle_reconnect_v2));
b56eae4df   Steve French   [SMB3] Send durab...
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
  	*num_iovec = num + 1;
  	return 0;
  }
  
  static int
  add_durable_context(struct kvec *iov, unsigned int *num_iovec,
  		    struct cifs_open_parms *oparms, bool use_persistent)
  {
  	struct smb2_create_req *req = iov[0].iov_base;
  	unsigned int num = *num_iovec;
  
  	if (use_persistent) {
  		if (oparms->reconnect)
  			return add_durable_reconnect_v2_context(iov, num_iovec,
  								oparms);
  		else
  			return add_durable_v2_context(iov, num_iovec, oparms);
  	}
9cbc0b733   Pavel Shilovsky   CIFS: Reconnect d...
1863
1864
1865
1866
1867
1868
  	if (oparms->reconnect) {
  		iov[num].iov_base = create_reconnect_durable_buf(oparms->fid);
  		/* indicate that we don't need to relock the file */
  		oparms->reconnect = false;
  	} else
  		iov[num].iov_base = create_durable_buf();
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
1869
1870
1871
1872
1873
  	if (iov[num].iov_base == NULL)
  		return -ENOMEM;
  	iov[num].iov_len = sizeof(struct create_durable);
  	if (!req->CreateContextsOffset)
  		req->CreateContextsOffset =
4f33bc358   Ronnie Sahlberg   cifs: remove rfc1...
1874
  			cpu_to_le32(sizeof(struct smb2_create_req) +
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
1875
  								iov[1].iov_len);
31f92e9a8   Wei Yongjun   CIFS: convert to ...
1876
  	le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable));
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
1877
1878
1879
  	*num_iovec = num + 1;
  	return 0;
  }
cdeaf9d04   Steve French   smb3: allow previ...
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
  /* See MS-SMB2 2.2.13.2.7 */
  static struct crt_twarp_ctxt *
  create_twarp_buf(__u64 timewarp)
  {
  	struct crt_twarp_ctxt *buf;
  
  	buf = kzalloc(sizeof(struct crt_twarp_ctxt), GFP_KERNEL);
  	if (!buf)
  		return NULL;
  
  	buf->ccontext.DataOffset = cpu_to_le16(offsetof
  					(struct crt_twarp_ctxt, Timestamp));
  	buf->ccontext.DataLength = cpu_to_le32(8);
  	buf->ccontext.NameOffset = cpu_to_le16(offsetof
  				(struct crt_twarp_ctxt, Name));
  	buf->ccontext.NameLength = cpu_to_le16(4);
  	/* SMB2_CREATE_TIMEWARP_TOKEN is "TWrp" */
  	buf->Name[0] = 'T';
  	buf->Name[1] = 'W';
  	buf->Name[2] = 'r';
  	buf->Name[3] = 'p';
  	buf->Timestamp = cpu_to_le64(timewarp);
  	return buf;
  }
  
  /* See MS-SMB2 2.2.13.2.7 */
  static int
  add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
  {
  	struct smb2_create_req *req = iov[0].iov_base;
  	unsigned int num = *num_iovec;
  
  	iov[num].iov_base = create_twarp_buf(timewarp);
  	if (iov[num].iov_base == NULL)
  		return -ENOMEM;
  	iov[num].iov_len = sizeof(struct crt_twarp_ctxt);
  	if (!req->CreateContextsOffset)
  		req->CreateContextsOffset = cpu_to_le32(
  				sizeof(struct smb2_create_req) +
  				iov[num - 1].iov_len);
  	le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_twarp_ctxt));
  	*num_iovec = num + 1;
  	return 0;
  }
f0712928b   Aurelien Aptel   CIFS: use DFS pat...
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
  static int
  alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
  			    const char *treename, const __le16 *path)
  {
  	int treename_len, path_len;
  	struct nls_table *cp;
  	const __le16 sep[] = {cpu_to_le16('\\'), cpu_to_le16(0x0000)};
  
  	/*
  	 * skip leading "\\"
  	 */
  	treename_len = strlen(treename);
  	if (treename_len < 2 || !(treename[0] == '\\' && treename[1] == '\\'))
  		return -EINVAL;
  
  	treename += 2;
  	treename_len -= 2;
  
  	path_len = UniStrnlen((wchar_t *)path, PATH_MAX);
  
  	/*
  	 * make room for one path separator between the treename and
  	 * path
  	 */
  	*out_len = treename_len + 1 + path_len;
  
  	/*
  	 * final path needs to be null-terminated UTF16 with a
  	 * size aligned to 8
  	 */
  
  	*out_size = roundup((*out_len+1)*2, 8);
  	*out_path = kzalloc(*out_size, GFP_KERNEL);
  	if (!*out_path)
  		return -ENOMEM;
  
  	cp = load_nls_default();
  	cifs_strtoUTF16(*out_path, treename, treename_len, cp);
  	UniStrcat(*out_path, sep);
  	UniStrcat(*out_path, path);
  	unload_nls(cp);
  
  	return 0;
  }
bea851b8b   Steve French   smb3: Fix mode on...
1968
1969
1970
1971
1972
1973
1974
  int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
  			       umode_t mode, struct cifs_tcon *tcon,
  			       const char *full_path,
  			       struct cifs_sb_info *cifs_sb)
  {
  	struct smb_rqst rqst;
  	struct smb2_create_req *req;
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
1975
  	struct smb2_create_rsp *rsp = NULL;
bea851b8b   Steve French   smb3: Fix mode on...
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
  	struct TCP_Server_Info *server;
  	struct cifs_ses *ses = tcon->ses;
  	struct kvec iov[3]; /* make sure at least one for each open context */
  	struct kvec rsp_iov = {NULL, 0};
  	int resp_buftype;
  	int uni_path_len;
  	__le16 *copy_path = NULL;
  	int copy_size;
  	int rc = 0;
  	unsigned int n_iov = 2;
  	__u32 file_attributes = 0;
  	char *pc_buf = NULL;
  	int flags = 0;
  	unsigned int total_len;
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
1990
  	__le16 *utf16_path = NULL;
bea851b8b   Steve French   smb3: Fix mode on...
1991
1992
1993
  
  	cifs_dbg(FYI, "mkdir
  ");
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
1994
1995
1996
1997
  	/* resource #1: path allocation */
  	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
  	if (!utf16_path)
  		return -ENOMEM;
bea851b8b   Steve French   smb3: Fix mode on...
1998
1999
  	if (ses && (ses->server))
  		server = ses->server;
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2000
2001
2002
2003
  	else {
  		rc = -EIO;
  		goto err_free_path;
  	}
bea851b8b   Steve French   smb3: Fix mode on...
2004

256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2005
  	/* resource #2: request */
bea851b8b   Steve French   smb3: Fix mode on...
2006
  	rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len);
bea851b8b   Steve French   smb3: Fix mode on...
2007
  	if (rc)
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2008
  		goto err_free_path;
bea851b8b   Steve French   smb3: Fix mode on...
2009
2010
2011
  
  	if (smb3_encryption_required(tcon))
  		flags |= CIFS_TRANSFORM_REQ;
bea851b8b   Steve French   smb3: Fix mode on...
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
  	req->ImpersonationLevel = IL_IMPERSONATION;
  	req->DesiredAccess = cpu_to_le32(FILE_WRITE_ATTRIBUTES);
  	/* File attributes ignored on open (used in create though) */
  	req->FileAttributes = cpu_to_le32(file_attributes);
  	req->ShareAccess = FILE_SHARE_ALL_LE;
  	req->CreateDisposition = cpu_to_le32(FILE_CREATE);
  	req->CreateOptions = cpu_to_le32(CREATE_NOT_FILE);
  
  	iov[0].iov_base = (char *)req;
  	/* -1 since last byte is buf[0] which is sent below (path) */
  	iov[0].iov_len = total_len - 1;
  
  	req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req));
  
  	/* [MS-SMB2] 2.2.13 NameOffset:
  	 * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
  	 * the SMB2 header, the file name includes a prefix that will
  	 * be processed during DFS name normalization as specified in
  	 * section 3.3.5.9. Otherwise, the file name is relative to
  	 * the share that is identified by the TreeId in the SMB2
  	 * header.
  	 */
  	if (tcon->share_flags & SHI1005_FLAGS_DFS) {
  		int name_len;
  
  		req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
  		rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
  						 &name_len,
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2040
2041
2042
  						 tcon->treeName, utf16_path);
  		if (rc)
  			goto err_free_req;
bea851b8b   Steve French   smb3: Fix mode on...
2043
2044
  		req->NameLength = cpu_to_le16(name_len * 2);
  		uni_path_len = copy_size;
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2045
2046
2047
  		/* free before overwriting resource */
  		kfree(utf16_path);
  		utf16_path = copy_path;
bea851b8b   Steve French   smb3: Fix mode on...
2048
  	} else {
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2049
  		uni_path_len = (2 * UniStrnlen((wchar_t *)utf16_path, PATH_MAX)) + 2;
bea851b8b   Steve French   smb3: Fix mode on...
2050
2051
2052
2053
2054
2055
  		/* MUST set path len (NameLength) to 0 opening root of share */
  		req->NameLength = cpu_to_le16(uni_path_len - 2);
  		if (uni_path_len % 8 != 0) {
  			copy_size = roundup(uni_path_len, 8);
  			copy_path = kzalloc(copy_size, GFP_KERNEL);
  			if (!copy_path) {
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2056
2057
  				rc = -ENOMEM;
  				goto err_free_req;
bea851b8b   Steve French   smb3: Fix mode on...
2058
  			}
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2059
  			memcpy((char *)copy_path, (const char *)utf16_path,
bea851b8b   Steve French   smb3: Fix mode on...
2060
2061
  			       uni_path_len);
  			uni_path_len = copy_size;
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2062
2063
2064
  			/* free before overwriting resource */
  			kfree(utf16_path);
  			utf16_path = copy_path;
bea851b8b   Steve French   smb3: Fix mode on...
2065
2066
2067
2068
  		}
  	}
  
  	iov[1].iov_len = uni_path_len;
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2069
  	iov[1].iov_base = utf16_path;
bea851b8b   Steve French   smb3: Fix mode on...
2070
2071
2072
  	req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE;
  
  	if (tcon->posix_extensions) {
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2073
  		/* resource #3: posix buf */
bea851b8b   Steve French   smb3: Fix mode on...
2074
  		rc = add_posix_context(iov, &n_iov, mode);
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2075
2076
  		if (rc)
  			goto err_free_req;
bea851b8b   Steve French   smb3: Fix mode on...
2077
2078
2079
2080
2081
2082
2083
  		pc_buf = iov[n_iov-1].iov_base;
  	}
  
  
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = n_iov;
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2084
2085
2086
  	/* resource #4: response buffer */
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
  	if (rc) {
bea851b8b   Steve French   smb3: Fix mode on...
2087
2088
  		cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
  		trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid,
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2089
2090
2091
2092
2093
2094
2095
2096
2097
  					   CREATE_NOT_FILE,
  					   FILE_WRITE_ATTRIBUTES, rc);
  		goto err_free_rsp_buf;
  	}
  
  	rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
  	trace_smb3_posix_mkdir_done(xid, rsp->PersistentFileId, tcon->tid,
  				    ses->Suid, CREATE_NOT_FILE,
  				    FILE_WRITE_ATTRIBUTES);
bea851b8b   Steve French   smb3: Fix mode on...
2098
2099
2100
2101
  
  	SMB2_close(xid, tcon, rsp->PersistentFileId, rsp->VolatileFileId);
  
  	/* Eventually save off posix specific response info and timestaps */
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2102
  err_free_rsp_buf:
bea851b8b   Steve French   smb3: Fix mode on...
2103
  	free_rsp_buf(resp_buftype, rsp);
256b4c3f0   Aurelien Aptel   CIFS: fix memory ...
2104
2105
2106
2107
2108
  	kfree(pc_buf);
  err_free_req:
  	cifs_small_buf_release(req);
  err_free_path:
  	kfree(utf16_path);
bea851b8b   Steve French   smb3: Fix mode on...
2109
  	return rc;
bea851b8b   Steve French   smb3: Fix mode on...
2110
  }
bea851b8b   Steve French   smb3: Fix mode on...
2111

2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2112
  int
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2113
2114
  SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock,
  	       struct cifs_open_parms *oparms, __le16 *path)
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2115
  {
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2116
  	struct TCP_Server_Info *server = tcon->ses->server;
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2117
  	struct smb2_create_req *req;
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2118
  	unsigned int n_iov = 2;
ca81983fe   Pavel Shilovsky   CIFS: Respect cre...
2119
  	__u32 file_attributes = 0;
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2120
2121
  	int copy_size;
  	int uni_path_len;
4f33bc358   Ronnie Sahlberg   cifs: remove rfc1...
2122
  	unsigned int total_len;
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2123
2124
2125
  	struct kvec *iov = rqst->rq_iov;
  	__le16 *copy_path;
  	int rc;
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2126

4f33bc358   Ronnie Sahlberg   cifs: remove rfc1...
2127
  	rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2128
2129
  	if (rc)
  		return rc;
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2130
2131
2132
  	iov[0].iov_base = (char *)req;
  	/* -1 since last byte is buf[0] which is sent below (path) */
  	iov[0].iov_len = total_len - 1;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
2133

064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
2134
  	if (oparms->create_options & CREATE_OPTION_READONLY)
ca81983fe   Pavel Shilovsky   CIFS: Respect cre...
2135
  		file_attributes |= ATTR_READONLY;
db8b631d4   Steve French   Allow mknod and m...
2136
2137
  	if (oparms->create_options & CREATE_OPTION_SPECIAL)
  		file_attributes |= ATTR_SYSTEM;
ca81983fe   Pavel Shilovsky   CIFS: Respect cre...
2138

2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2139
  	req->ImpersonationLevel = IL_IMPERSONATION;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
2140
  	req->DesiredAccess = cpu_to_le32(oparms->desired_access);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2141
2142
2143
  	/* File attributes ignored on open (used in create though) */
  	req->FileAttributes = cpu_to_le32(file_attributes);
  	req->ShareAccess = FILE_SHARE_ALL_LE;
064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
2144
2145
  	req->CreateDisposition = cpu_to_le32(oparms->disposition);
  	req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK);
4f33bc358   Ronnie Sahlberg   cifs: remove rfc1...
2146
  	req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req));
f0712928b   Aurelien Aptel   CIFS: use DFS pat...
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
  
  	/* [MS-SMB2] 2.2.13 NameOffset:
  	 * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
  	 * the SMB2 header, the file name includes a prefix that will
  	 * be processed during DFS name normalization as specified in
  	 * section 3.3.5.9. Otherwise, the file name is relative to
  	 * the share that is identified by the TreeId in the SMB2
  	 * header.
  	 */
  	if (tcon->share_flags & SHI1005_FLAGS_DFS) {
  		int name_len;
4f33bc358   Ronnie Sahlberg   cifs: remove rfc1...
2158
  		req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
f0712928b   Aurelien Aptel   CIFS: use DFS pat...
2159
2160
2161
  		rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
  						 &name_len,
  						 tcon->treeName, path);
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2162
  		if (rc)
f0712928b   Aurelien Aptel   CIFS: use DFS pat...
2163
2164
  			return rc;
  		req->NameLength = cpu_to_le16(name_len * 2);
59aa37184   Pavel Shilovsky   CIFS: Simplify SM...
2165
2166
  		uni_path_len = copy_size;
  		path = copy_path;
f0712928b   Aurelien Aptel   CIFS: use DFS pat...
2167
2168
2169
2170
  	} else {
  		uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
  		/* MUST set path len (NameLength) to 0 opening root of share */
  		req->NameLength = cpu_to_le16(uni_path_len - 2);
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
  		copy_size = uni_path_len;
  		if (copy_size % 8 != 0)
  			copy_size = roundup(copy_size, 8);
  		copy_path = kzalloc(copy_size, GFP_KERNEL);
  		if (!copy_path)
  			return -ENOMEM;
  		memcpy((char *)copy_path, (const char *)path,
  		       uni_path_len);
  		uni_path_len = copy_size;
  		path = copy_path;
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2181
  	}
59aa37184   Pavel Shilovsky   CIFS: Simplify SM...
2182
2183
  	iov[1].iov_len = uni_path_len;
  	iov[1].iov_base = path;
59aa37184   Pavel Shilovsky   CIFS: Simplify SM...
2184

b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
2185
2186
  	if (!server->oplocks)
  		*oplock = SMB2_OPLOCK_LEVEL_NONE;
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
2187
  	if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) ||
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
2188
2189
  	    *oplock == SMB2_OPLOCK_LEVEL_NONE)
  		req->RequestedOplockLevel = *oplock;
f80156833   Steve French   smb3: check for a...
2190
2191
2192
  	else if (!(server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) &&
  		  (oparms->create_options & CREATE_NOT_FILE))
  		req->RequestedOplockLevel = *oplock; /* no srv lease support */
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
2193
  	else {
729c0c9dd   Stefano Brivio   cifs: Fix stack o...
2194
2195
  		rc = add_lease_context(server, iov, &n_iov,
  				       oparms->fid->lease_key, oplock);
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2196
  		if (rc)
d22cbfecb   Pavel Shilovsky   CIFS: Simplify SM...
2197
  			return rc;
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
2198
  	}
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
2199
2200
  	if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) {
  		/* need to set Next field of lease context if we request it */
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
2201
  		if (server->capabilities & SMB2_GLOBAL_CAP_LEASING) {
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
2202
  			struct create_context *ccontext =
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2203
  			    (struct create_context *)iov[n_iov-1].iov_base;
1c46943f8   Steve French   [CIFS] Fix minor ...
2204
  			ccontext->Next =
a41a28bda   Pavel Shilovsky   CIFS: Move creati...
2205
  				cpu_to_le32(server->vals->create_lease_size);
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
2206
  		}
b56eae4df   Steve French   [SMB3] Send durab...
2207

da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2208
  		rc = add_durable_context(iov, &n_iov, oparms,
b56eae4df   Steve French   [SMB3] Send durab...
2209
  					tcon->use_persistent);
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2210
  		if (rc)
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
2211
  			return rc;
63eb3def3   Pavel Shilovsky   CIFS: Request dur...
2212
  	}
ce558b0e1   Steve French   smb3: Add posix c...
2213
2214
2215
2216
2217
2218
2219
2220
2221
  	if (tcon->posix_extensions) {
  		if (n_iov > 2) {
  			struct create_context *ccontext =
  			    (struct create_context *)iov[n_iov-1].iov_base;
  			ccontext->Next =
  				cpu_to_le32(iov[n_iov-1].iov_len);
  		}
  
  		rc = add_posix_context(iov, &n_iov, oparms->mode);
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2222
  		if (rc)
ce558b0e1   Steve French   smb3: Add posix c...
2223
  			return rc;
ce558b0e1   Steve French   smb3: Add posix c...
2224
  	}
ce558b0e1   Steve French   smb3: Add posix c...
2225

cdeaf9d04   Steve French   smb3: allow previ...
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
  	if (tcon->snapshot_time) {
  		cifs_dbg(FYI, "adding snapshot context
  ");
  		if (n_iov > 2) {
  			struct create_context *ccontext =
  			    (struct create_context *)iov[n_iov-1].iov_base;
  			ccontext->Next =
  				cpu_to_le32(iov[n_iov-1].iov_len);
  		}
  
  		rc = add_twarp_context(iov, &n_iov, tcon->snapshot_time);
  		if (rc)
  			return rc;
  	}
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
  	rqst->rq_nvec = n_iov;
  	return 0;
  }
  
  /* rq_iov[0] is the request and is released by cifs_small_buf_release().
   * All other vectors are freed by kfree().
   */
  void
  SMB2_open_free(struct smb_rqst *rqst)
  {
  	int i;
b4d965a37   Ronnie Sahlberg   cifs: allow calli...
2251
2252
2253
2254
2255
2256
  	if (rqst && rqst->rq_iov) {
  		cifs_small_buf_release(rqst->rq_iov[0].iov_base);
  		for (i = 1; i < rqst->rq_nvec; i++)
  			if (rqst->rq_iov[i].iov_base != smb2_padding)
  				kfree(rqst->rq_iov[i].iov_base);
  	}
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
  }
  
  int
  SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
  	  __u8 *oplock, struct smb2_file_all_info *buf,
  	  struct kvec *err_iov, int *buftype)
  {
  	struct smb_rqst rqst;
  	struct smb2_create_rsp *rsp = NULL;
  	struct TCP_Server_Info *server;
  	struct cifs_tcon *tcon = oparms->tcon;
  	struct cifs_ses *ses = tcon->ses;
4d8dfafc5   Ronnie Sahlberg   cifs: create a de...
2269
  	struct kvec iov[SMB2_CREATE_IOV_SIZE];
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
  	struct kvec rsp_iov = {NULL, 0};
  	int resp_buftype;
  	int rc = 0;
  	int flags = 0;
  
  	cifs_dbg(FYI, "create/open
  ");
  	if (ses && (ses->server))
  		server = ses->server;
  	else
  		return -EIO;
  
  	if (smb3_encryption_required(tcon))
  		flags |= CIFS_TRANSFORM_REQ;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2284
  	memset(&rqst, 0, sizeof(struct smb_rqst));
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2285
  	memset(&iov, 0, sizeof(iov));
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2286
  	rqst.rq_iov = iov;
4d8dfafc5   Ronnie Sahlberg   cifs: create a de...
2287
  	rqst.rq_nvec = SMB2_CREATE_IOV_SIZE;
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2288
2289
2290
2291
  
  	rc = SMB2_open_init(tcon, &rqst, oplock, oparms, path);
  	if (rc)
  		goto creat_exit;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2292
2293
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
4f33bc358   Ronnie Sahlberg   cifs: remove rfc1...
2294
  			    &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2295
  	rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2296
2297
2298
  
  	if (rc != 0) {
  		cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
91cb74f51   Ronnie Sahlberg   cifs: Change SMB2...
2299
2300
  		if (err_iov && rsp) {
  			*err_iov = rsp_iov;
9d874c365   Ronnie Sahlberg   cifs: fix a buffe...
2301
  			*buftype = resp_buftype;
91cb74f51   Ronnie Sahlberg   cifs: Change SMB2...
2302
2303
2304
  			resp_buftype = CIFS_NO_BUFFER;
  			rsp = NULL;
  		}
28d59363a   Steve French   smb3: add tracepo...
2305
2306
  		trace_smb3_open_err(xid, tcon->tid, ses->Suid,
  				    oparms->create_options, oparms->desired_access, rc);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2307
  		goto creat_exit;
28d59363a   Steve French   smb3: add tracepo...
2308
2309
2310
2311
  	} else
  		trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid,
  				     ses->Suid, oparms->create_options,
  				     oparms->desired_access);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2312

064f6047a   Pavel Shilovsky   CIFS: Make SMB2_o...
2313
2314
  	oparms->fid->persistent_fid = rsp->PersistentFileId;
  	oparms->fid->volatile_fid = rsp->VolatileFileId;
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
2315
2316
2317
2318
2319
2320
2321
2322
2323
  
  	if (buf) {
  		memcpy(buf, &rsp->CreationTime, 32);
  		buf->AllocationSize = rsp->AllocationSize;
  		buf->EndOfFile = rsp->EndofFile;
  		buf->Attributes = rsp->FileAttributes;
  		buf->NumberOfLinks = cpu_to_le32(1);
  		buf->DeletePending = 0;
  	}
2e44b2887   Pavel Shilovsky   CIFS: Process opl...
2324

b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
2325
  	if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE)
96164ab2d   Ronnie Sahlberg   cifs: store the l...
2326
2327
  		*oplock = parse_lease_state(server, rsp, &oparms->fid->epoch,
  					    oparms->fid->lease_key);
b8c32dbb0   Pavel Shilovsky   CIFS: Request SMB...
2328
2329
  	else
  		*oplock = rsp->OplockLevel;
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2330
  creat_exit:
1eb9fb520   Ronnie Sahlberg   cifs: create SMB2...
2331
  	SMB2_open_free(&rqst);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2332
2333
2334
  	free_rsp_buf(resp_buftype, rsp);
  	return rc;
  }
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2335
2336
2337
2338
2339
  /*
   *	SMB2 IOCTL is used for both IOCTLs and FSCTLs
   */
  int
  SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
63a83b861   Aurelien Aptel   CIFS: use tcon_ip...
2340
  	   u64 volatile_fid, u32 opcode, bool is_fsctl,
51146625f   Aurelien Aptel   CIFS: add use_ipc...
2341
2342
  	   char *in_data, u32 indatalen,
  	   char **out_data, u32 *plen /* returned data len */)
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2343
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2344
  	struct smb_rqst rqst;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2345
2346
  	struct smb2_ioctl_req *req;
  	struct smb2_ioctl_rsp *rsp;
8e3531060   Steve French   Fix dereference b...
2347
  	struct cifs_ses *ses;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2348
  	struct kvec iov[2];
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2349
  	struct kvec rsp_iov;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2350
  	int resp_buftype;
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2351
  	int n_iov;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2352
  	int rc = 0;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
2353
  	int flags = 0;
977546802   Ronnie Sahlberg   cifs: remove rfc1...
2354
  	unsigned int total_len;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2355
2356
2357
  
  	cifs_dbg(FYI, "SMB2 IOCTL
  ");
3d1a3745d   Steve French   Add sparse file s...
2358
2359
  	if (out_data != NULL)
  		*out_data = NULL;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2360
2361
2362
  	/* zero out returned data len, in case of error */
  	if (plen)
  		*plen = 0;
8e3531060   Steve French   Fix dereference b...
2363
2364
2365
2366
  	if (tcon)
  		ses = tcon->ses;
  	else
  		return -EIO;
68a6afa7f   Christos Gkekas   cifs: Clean up un...
2367
  	if (!ses || !(ses->server))
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2368
  		return -EIO;
977546802   Ronnie Sahlberg   cifs: remove rfc1...
2369
  	rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len);
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2370
2371
  	if (rc)
  		return rc;
5a77e75fe   Steve French   smb3: rename encr...
2372
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
2373
  		flags |= CIFS_TRANSFORM_REQ;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2374
2375
2376
2377
2378
2379
2380
2381
  	req->CtlCode = cpu_to_le32(opcode);
  	req->PersistentFileId = persistent_fid;
  	req->VolatileFileId = volatile_fid;
  
  	if (indatalen) {
  		req->InputCount = cpu_to_le32(indatalen);
  		/* do not set InputOffset if no input data */
  		req->InputOffset =
977546802   Ronnie Sahlberg   cifs: remove rfc1...
2382
  		       cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer));
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2383
2384
  		iov[1].iov_base = in_data;
  		iov[1].iov_len = indatalen;
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2385
  		n_iov = 2;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2386
  	} else
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2387
  		n_iov = 1;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2388
2389
2390
2391
2392
2393
2394
2395
2396
  
  	req->OutputOffset = 0;
  	req->OutputCount = 0; /* MBZ */
  
  	/*
  	 * Could increase MaxOutputResponse, but that would require more
  	 * than one credit. Windows typically sets this smaller, but for some
  	 * ioctls it may be useful to allow server to send more. No point
  	 * limiting what the server can send as long as fits in one credit
7db0a6efd   Steve French   SMB3: Work around...
2397
2398
2399
2400
  	 * Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE
  	 * (by default, note that it can be overridden to make max larger)
  	 * in responses (except for read responses which can be bigger.
  	 * We may want to bump this limit up
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2401
  	 */
7db0a6efd   Steve French   SMB3: Work around...
2402
  	req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize);
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2403
2404
2405
2406
2407
2408
2409
  
  	if (is_fsctl)
  		req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);
  	else
  		req->Flags = 0;
  
  	iov[0].iov_base = (char *)req;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2410

7ff8d45c9   Steve French   Fix corrupt SMB2 ...
2411
2412
2413
2414
2415
2416
  	/*
  	 * If no input data, the size of ioctl struct in
  	 * protocol spec still includes a 1 byte data buffer,
  	 * but if input data passed to ioctl, we do not
  	 * want to double count this, so we do not send
  	 * the dummy one byte of data in iovec[0] if sending
977546802   Ronnie Sahlberg   cifs: remove rfc1...
2417
  	 * input data (in iovec[1]).
7ff8d45c9   Steve French   Fix corrupt SMB2 ...
2418
2419
2420
  	 */
  
  	if (indatalen) {
977546802   Ronnie Sahlberg   cifs: remove rfc1...
2421
  		iov[0].iov_len = total_len - 1;
7ff8d45c9   Steve French   Fix corrupt SMB2 ...
2422
  	} else
977546802   Ronnie Sahlberg   cifs: remove rfc1...
2423
  		iov[0].iov_len = total_len;
7ff8d45c9   Steve French   Fix corrupt SMB2 ...
2424

4587eee04   Steve French   SMB3: Validate ne...
2425
2426
  	/* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
  	if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
977546802   Ronnie Sahlberg   cifs: remove rfc1...
2427
  		req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2428

40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2429
2430
2431
2432
2433
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = n_iov;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
977546802   Ronnie Sahlberg   cifs: remove rfc1...
2434
  			    &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2435
2436
  	cifs_small_buf_release(req);
  	rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base;
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2437

eccb4422c   Steve French   smb3: Add ftrace ...
2438
2439
2440
  	if (rc != 0)
  		trace_smb3_fsctl_err(xid, persistent_fid, tcon->tid,
  				ses->Suid, 0, opcode, rc);
9bf0c9cd4   Steve French   CIFS: Fix SMB2/SM...
2441
  	if ((rc != 0) && (rc != -EINVAL)) {
8e3531060   Steve French   Fix dereference b...
2442
  		cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2443
  		goto ioctl_exit;
9bf0c9cd4   Steve French   CIFS: Fix SMB2/SM...
2444
2445
2446
  	} else if (rc == -EINVAL) {
  		if ((opcode != FSCTL_SRV_COPYCHUNK_WRITE) &&
  		    (opcode != FSCTL_SRV_COPYCHUNK)) {
8e3531060   Steve French   Fix dereference b...
2447
  			cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
9bf0c9cd4   Steve French   CIFS: Fix SMB2/SM...
2448
2449
  			goto ioctl_exit;
  		}
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
  	}
  
  	/* check if caller wants to look at return data or just return rc */
  	if ((plen == NULL) || (out_data == NULL))
  		goto ioctl_exit;
  
  	*plen = le32_to_cpu(rsp->OutputCount);
  
  	/* We check for obvious errors in the output buffer length and offset */
  	if (*plen == 0)
  		goto ioctl_exit; /* server returned no data */
2d204ee9d   Dan Carpenter   cifs: integer ove...
2461
  	else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) {
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2462
2463
2464
2465
2466
2467
  		cifs_dbg(VFS, "srv returned invalid ioctl length: %d
  ", *plen);
  		*plen = 0;
  		rc = -EIO;
  		goto ioctl_exit;
  	}
2d204ee9d   Dan Carpenter   cifs: integer ove...
2468
  	if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) {
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
  		cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d
  ", *plen,
  			le32_to_cpu(rsp->OutputOffset));
  		*plen = 0;
  		rc = -EIO;
  		goto ioctl_exit;
  	}
  
  	*out_data = kmalloc(*plen, GFP_KERNEL);
  	if (*out_data == NULL) {
  		rc = -ENOMEM;
  		goto ioctl_exit;
  	}
977b61704   Ronnie Sahlberg   cifs: remove rfc1...
2482
  	memcpy(*out_data, (char *)rsp + le32_to_cpu(rsp->OutputOffset), *plen);
4a72dafa1   Steve French   SMB2 FSCTL and IO...
2483
2484
2485
2486
  ioctl_exit:
  	free_rsp_buf(resp_buftype, rsp);
  	return rc;
  }
64a5cfa6d   Steve French   Allow setting per...
2487
2488
2489
2490
2491
2492
2493
2494
2495
  /*
   *   Individual callers to ioctl worker function follow
   */
  
  int
  SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
  		     u64 persistent_fid, u64 volatile_fid)
  {
  	int rc;
64a5cfa6d   Steve French   Allow setting per...
2496
2497
2498
2499
  	struct  compress_ioctl fsctl_input;
  	char *ret_data = NULL;
  
  	fsctl_input.CompressionState =
bc09d141e   Fabian Frederick   fs/cifs: remove o...
2500
  			cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
64a5cfa6d   Steve French   Allow setting per...
2501
2502
2503
2504
2505
2506
2507
2508
  
  	rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
  			FSCTL_SET_COMPRESSION, true /* is_fsctl */,
  			(char *)&fsctl_input /* data input */,
  			2 /* in data len */, &ret_data /* out data */, NULL);
  
  	cifs_dbg(FYI, "set compression rc %d
  ", rc);
64a5cfa6d   Steve French   Allow setting per...
2509
2510
2511
  
  	return rc;
  }
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2512
  int
8eb4ecfab   Ronnie Sahlberg   cifs: add SMB2_cl...
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
  SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
  		u64 persistent_fid, u64 volatile_fid)
  {
  	struct smb2_close_req *req;
  	struct kvec *iov = rqst->rq_iov;
  	unsigned int total_len;
  	int rc;
  
  	rc = smb2_plain_req_init(SMB2_CLOSE, tcon, (void **) &req, &total_len);
  	if (rc)
  		return rc;
  
  	req->PersistentFileId = persistent_fid;
  	req->VolatileFileId = volatile_fid;
  	iov[0].iov_base = (char *)req;
  	iov[0].iov_len = total_len;
  
  	return 0;
  }
  
  void
  SMB2_close_free(struct smb_rqst *rqst)
  {
b4d965a37   Ronnie Sahlberg   cifs: allow calli...
2536
2537
  	if (rqst && rqst->rq_iov)
  		cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
8eb4ecfab   Ronnie Sahlberg   cifs: add SMB2_cl...
2538
2539
2540
  }
  
  int
97ca17622   Ronnie Sahlberg   cifs: add a new S...
2541
2542
  SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon,
  		 u64 persistent_fid, u64 volatile_fid, int flags)
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2543
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2544
  	struct smb_rqst rqst;
8eb4ecfab   Ronnie Sahlberg   cifs: add SMB2_cl...
2545
  	struct smb2_close_rsp *rsp = NULL;
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2546
2547
  	struct cifs_ses *ses = tcon->ses;
  	struct kvec iov[1];
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2548
  	struct kvec rsp_iov;
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2549
2550
  	int resp_buftype;
  	int rc = 0;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2551
2552
  	cifs_dbg(FYI, "Close
  ");
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2553

68a6afa7f   Christos Gkekas   cifs: Clean up un...
2554
  	if (!ses || !(ses->server))
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2555
  		return -EIO;
5a77e75fe   Steve French   smb3: rename encr...
2556
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
2557
  		flags |= CIFS_TRANSFORM_REQ;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2558
  	memset(&rqst, 0, sizeof(struct smb_rqst));
8eb4ecfab   Ronnie Sahlberg   cifs: add SMB2_cl...
2559
  	memset(&iov, 0, sizeof(iov));
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2560
2561
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 1;
8eb4ecfab   Ronnie Sahlberg   cifs: add SMB2_cl...
2562
2563
2564
  	rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid);
  	if (rc)
  		goto close_exit;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2565
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2566
  	rsp = (struct smb2_close_rsp *)rsp_iov.iov_base;
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2567
2568
  
  	if (rc != 0) {
d4a029d21   Namjae Jeon   cifs: remove unne...
2569
  		cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
eccb4422c   Steve French   smb3: Add ftrace ...
2570
2571
  		trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid,
  				     rc);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2572
2573
  		goto close_exit;
  	}
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2574
2575
2576
  	/* BB FIXME - decode close response, update inode for caching */
  
  close_exit:
8eb4ecfab   Ronnie Sahlberg   cifs: add SMB2_cl...
2577
  	SMB2_close_free(&rqst);
2503a0dba   Pavel Shilovsky   CIFS: Add SMB2 su...
2578
2579
2580
  	free_rsp_buf(resp_buftype, rsp);
  	return rc;
  }
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2581

97ca17622   Ronnie Sahlberg   cifs: add a new S...
2582
2583
2584
2585
2586
2587
  int
  SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
  	   u64 persistent_fid, u64 volatile_fid)
  {
  	return SMB2_close_flags(xid, tcon, persistent_fid, volatile_fid, 0);
  }
730928c8f   Ronnie Sahlberg   cifs: update smb2...
2588
2589
2590
  int
  smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
  		  struct kvec *iov, unsigned int min_buf_size)
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2591
  {
c1596ff52   Ronnie Sahlberg   cifs: change vali...
2592
  	unsigned int smb_len = iov->iov_len;
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
2593
2594
  	char *end_of_smb = smb_len + (char *)iov->iov_base;
  	char *begin_of_buf = offset + (char *)iov->iov_base;
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2595
2596
2597
2598
  	char *end_of_buf = begin_of_buf + buffer_length;
  
  
  	if (buffer_length < min_buf_size) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2599
2600
2601
  		cifs_dbg(VFS, "buffer length %d smaller than minimum size %d
  ",
  			 buffer_length, min_buf_size);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2602
2603
2604
2605
2606
  		return -EINVAL;
  	}
  
  	/* check if beyond RFC1001 maximum length */
  	if ((smb_len > 0x7FFFFF) || (buffer_length > 0x7FFFFF)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2607
2608
2609
  		cifs_dbg(VFS, "buffer length %d or smb length %d too large
  ",
  			 buffer_length, smb_len);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2610
2611
2612
2613
  		return -EINVAL;
  	}
  
  	if ((begin_of_buf > end_of_smb) || (end_of_buf > end_of_smb)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2614
2615
  		cifs_dbg(VFS, "illegal server response, bad offset to data
  ");
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
  		return -EINVAL;
  	}
  
  	return 0;
  }
  
  /*
   * If SMB buffer fields are valid, copy into temporary buffer to hold result.
   * Caller must free buffer.
   */
  static int
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
2627
  validate_and_copy_iov(unsigned int offset, unsigned int buffer_length,
c1596ff52   Ronnie Sahlberg   cifs: change vali...
2628
  		      struct kvec *iov, unsigned int minbufsize,
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2629
  		      char *data)
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2630
  {
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
2631
  	char *begin_of_buf = offset + (char *)iov->iov_base;
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2632
2633
2634
2635
  	int rc;
  
  	if (!data)
  		return -EINVAL;
730928c8f   Ronnie Sahlberg   cifs: update smb2...
2636
  	rc = smb2_validate_iov(offset, buffer_length, iov, minbufsize);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2637
2638
2639
2640
2641
2642
2643
  	if (rc)
  		return rc;
  
  	memcpy(data, begin_of_buf, buffer_length);
  
  	return 0;
  }
296ecbae7   Ronnie Sahlberg   cifs: add SMB2_qu...
2644
2645
2646
2647
2648
  int
  SMB2_query_info_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
  		     u64 persistent_fid, u64 volatile_fid,
  		     u8 info_class, u8 info_type, u32 additional_info,
  		     size_t output_len)
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2649
2650
  {
  	struct smb2_query_info_req *req;
296ecbae7   Ronnie Sahlberg   cifs: add SMB2_qu...
2651
  	struct kvec *iov = rqst->rq_iov;
b2fb7fecc   Ronnie Sahlberg   cifs: remove rfc1...
2652
  	unsigned int total_len;
296ecbae7   Ronnie Sahlberg   cifs: add SMB2_qu...
2653
  	int rc;
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2654

b2fb7fecc   Ronnie Sahlberg   cifs: remove rfc1...
2655
2656
  	rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, (void **) &req,
  			     &total_len);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2657
2658
  	if (rc)
  		return rc;
42c493c16   Shirish Pargaonkar   cifs: prototype d...
2659
  	req->InfoType = info_type;
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
2660
  	req->FileInfoClass = info_class;
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2661
2662
  	req->PersistentFileId = persistent_fid;
  	req->VolatileFileId = volatile_fid;
42c493c16   Shirish Pargaonkar   cifs: prototype d...
2663
  	req->AdditionalInformation = cpu_to_le32(additional_info);
48923d2a9   Aurelien Aptel   CIFS: do not send...
2664
2665
2666
2667
2668
  
  	/*
  	 * We do not use the input buffer (do not send extra byte)
  	 */
  	req->InputBufferOffset = 0;
48923d2a9   Aurelien Aptel   CIFS: do not send...
2669

f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
2670
  	req->OutputBufferLength = cpu_to_le32(output_len);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2671
2672
  
  	iov[0].iov_base = (char *)req;
b2fb7fecc   Ronnie Sahlberg   cifs: remove rfc1...
2673
2674
  	/* 1 for Buffer */
  	iov[0].iov_len = total_len - 1;
296ecbae7   Ronnie Sahlberg   cifs: add SMB2_qu...
2675
2676
2677
2678
2679
2680
  	return 0;
  }
  
  void
  SMB2_query_info_free(struct smb_rqst *rqst)
  {
b4d965a37   Ronnie Sahlberg   cifs: allow calli...
2681
2682
  	if (rqst && rqst->rq_iov)
  		cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
296ecbae7   Ronnie Sahlberg   cifs: add SMB2_qu...
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
  }
  
  static int
  query_info(const unsigned int xid, struct cifs_tcon *tcon,
  	   u64 persistent_fid, u64 volatile_fid, u8 info_class, u8 info_type,
  	   u32 additional_info, size_t output_len, size_t min_len, void **data,
  		u32 *dlen)
  {
  	struct smb_rqst rqst;
  	struct smb2_query_info_rsp *rsp = NULL;
  	struct kvec iov[1];
  	struct kvec rsp_iov;
  	int rc = 0;
  	int resp_buftype;
  	struct cifs_ses *ses = tcon->ses;
  	int flags = 0;
  
  	cifs_dbg(FYI, "Query Info
  ");
  
  	if (!ses || !(ses->server))
  		return -EIO;
  
  	if (smb3_encryption_required(tcon))
  		flags |= CIFS_TRANSFORM_REQ;
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2708

40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2709
  	memset(&rqst, 0, sizeof(struct smb_rqst));
296ecbae7   Ronnie Sahlberg   cifs: add SMB2_qu...
2710
  	memset(&iov, 0, sizeof(iov));
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2711
2712
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 1;
296ecbae7   Ronnie Sahlberg   cifs: add SMB2_qu...
2713
2714
2715
2716
2717
  	rc = SMB2_query_info_init(tcon, &rqst, persistent_fid, volatile_fid,
  				  info_class, info_type, additional_info,
  				  output_len);
  	if (rc)
  		goto qinf_exit;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2718
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2719
  	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
e5d048871   Pavel Shilovsky   CIFS: Fix possibl...
2720

be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2721
2722
  	if (rc) {
  		cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
eccb4422c   Steve French   smb3: Add ftrace ...
2723
2724
  		trace_smb3_query_info_err(xid, persistent_fid, tcon->tid,
  				ses->Suid, info_class, (__u32)info_type, rc);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2725
2726
  		goto qinf_exit;
  	}
42c493c16   Shirish Pargaonkar   cifs: prototype d...
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
  	if (dlen) {
  		*dlen = le32_to_cpu(rsp->OutputBufferLength);
  		if (!*data) {
  			*data = kmalloc(*dlen, GFP_KERNEL);
  			if (!*data) {
  				cifs_dbg(VFS,
  					"Error %d allocating memory for acl
  ",
  					rc);
  				*dlen = 0;
  				goto qinf_exit;
  			}
  		}
  	}
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
2741
  	rc = validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2742
  				   le32_to_cpu(rsp->OutputBufferLength),
c1596ff52   Ronnie Sahlberg   cifs: change vali...
2743
  				   &rsp_iov, min_len, *data);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2744
2745
  
  qinf_exit:
296ecbae7   Ronnie Sahlberg   cifs: add SMB2_qu...
2746
  	SMB2_query_info_free(&rqst);
be4cb9e3d   Pavel Shilovsky   CIFS: Query SMB2 ...
2747
2748
2749
  	free_rsp_buf(resp_buftype, rsp);
  	return rc;
  }
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2750

95907fea4   Ronnie Sahlberg   cifs: Add support...
2751
  int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
7cb3def44   Ronnie Sahlberg   cifs: handle larg...
2752
2753
  		   u64 persistent_fid, u64 volatile_fid,
  		   int ea_buf_size, struct smb2_file_full_ea_info *data)
95907fea4   Ronnie Sahlberg   cifs: Add support...
2754
2755
2756
  {
  	return query_info(xid, tcon, persistent_fid, volatile_fid,
  			  FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0,
7cb3def44   Ronnie Sahlberg   cifs: handle larg...
2757
  			  ea_buf_size,
95907fea4   Ronnie Sahlberg   cifs: Add support...
2758
2759
2760
2761
  			  sizeof(struct smb2_file_full_ea_info),
  			  (void **)&data,
  			  NULL);
  }
42c493c16   Shirish Pargaonkar   cifs: prototype d...
2762
2763
2764
2765
2766
2767
2768
2769
2770
  int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
  	u64 persistent_fid, u64 volatile_fid, struct smb2_file_all_info *data)
  {
  	return query_info(xid, tcon, persistent_fid, volatile_fid,
  			  FILE_ALL_INFORMATION, SMB2_O_INFO_FILE, 0,
  			  sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
  			  sizeof(struct smb2_file_all_info), (void **)&data,
  			  NULL);
  }
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
2771
  int
42c493c16   Shirish Pargaonkar   cifs: prototype d...
2772
  SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
2773
  		u64 persistent_fid, u64 volatile_fid,
42c493c16   Shirish Pargaonkar   cifs: prototype d...
2774
  		void **data, u32 *plen)
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
2775
  {
42c493c16   Shirish Pargaonkar   cifs: prototype d...
2776
2777
  	__u32 additional_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO;
  	*plen = 0;
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
2778
  	return query_info(xid, tcon, persistent_fid, volatile_fid,
42c493c16   Shirish Pargaonkar   cifs: prototype d...
2779
  			  0, SMB2_O_INFO_SECURITY, additional_info,
ee25c6dd7   Shirish Pargaonkar   cifs: For SMB2 se...
2780
  			  SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen);
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
2781
2782
2783
2784
2785
2786
2787
  }
  
  int
  SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
  		 u64 persistent_fid, u64 volatile_fid, __le64 *uniqueid)
  {
  	return query_info(xid, tcon, persistent_fid, volatile_fid,
42c493c16   Shirish Pargaonkar   cifs: prototype d...
2788
2789
  			  FILE_INTERNAL_INFORMATION, SMB2_O_INFO_FILE, 0,
  			  sizeof(struct smb2_file_internal_info),
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
2790
  			  sizeof(struct smb2_file_internal_info),
42c493c16   Shirish Pargaonkar   cifs: prototype d...
2791
  			  (void **)&uniqueid, NULL);
f0df737ee   Pavel Shilovsky   CIFS: Add open/cl...
2792
  }
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
  /*
   * This is a no-op for now. We're not really interested in the reply, but
   * rather in the fact that the server sent one and that server->lstrp
   * gets updated.
   *
   * FIXME: maybe we should consider checking that the reply matches request?
   */
  static void
  smb2_echo_callback(struct mid_q_entry *mid)
  {
  	struct TCP_Server_Info *server = mid->callback_data;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
2804
  	struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf;
b1765ebd9   Pavel Shilovsky   CIFS: Do not assu...
2805
  	unsigned int credits_received = 0;
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2806

b1765ebd9   Pavel Shilovsky   CIFS: Do not assu...
2807
2808
  	if (mid->mid_state == MID_RESPONSE_RECEIVED
  	    || mid->mid_state == MID_RESPONSE_MALFORMED)
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
2809
  		credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2810
2811
2812
2813
  
  	DeleteMidQEntry(mid);
  	add_credits(server, credits_received, CIFS_ECHO_OP);
  }
53e0e11ef   Pavel Shilovsky   CIFS: Fix a possi...
2814
2815
2816
2817
2818
2819
2820
2821
  void smb2_reconnect_server(struct work_struct *work)
  {
  	struct TCP_Server_Info *server = container_of(work,
  					struct TCP_Server_Info, reconnect.work);
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon, *tcon2;
  	struct list_head tmp_list;
  	int tcon_exist = false;
18ea43113   Germano Percossi   CIFS: reconnect t...
2822
2823
  	int rc;
  	int resched = false;
53e0e11ef   Pavel Shilovsky   CIFS: Fix a possi...
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
  
  	/* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
  	mutex_lock(&server->reconnect_mutex);
  
  	INIT_LIST_HEAD(&tmp_list);
  	cifs_dbg(FYI, "Need negotiate, reconnecting tcons
  ");
  
  	spin_lock(&cifs_tcp_ses_lock);
  	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
  		list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
96a988ffe   Pavel Shilovsky   CIFS: Fix a possi...
2835
  			if (tcon->need_reconnect || tcon->need_reopen_files) {
53e0e11ef   Pavel Shilovsky   CIFS: Fix a possi...
2836
2837
2838
2839
2840
  				tcon->tc_count++;
  				list_add_tail(&tcon->rlist, &tmp_list);
  				tcon_exist = true;
  			}
  		}
b327a717e   Aurelien Aptel   CIFS: make IPC a ...
2841
2842
2843
2844
  		if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) {
  			list_add_tail(&ses->tcon_ipc->rlist, &tmp_list);
  			tcon_exist = true;
  		}
53e0e11ef   Pavel Shilovsky   CIFS: Fix a possi...
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
  	}
  	/*
  	 * Get the reference to server struct to be sure that the last call of
  	 * cifs_put_tcon() in the loop below won't release the server pointer.
  	 */
  	if (tcon_exist)
  		server->srv_count++;
  
  	spin_unlock(&cifs_tcp_ses_lock);
  
  	list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
18ea43113   Germano Percossi   CIFS: reconnect t...
2856
2857
  		rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon);
  		if (!rc)
96a988ffe   Pavel Shilovsky   CIFS: Fix a possi...
2858
  			cifs_reopen_persistent_handles(tcon);
18ea43113   Germano Percossi   CIFS: reconnect t...
2859
2860
  		else
  			resched = true;
53e0e11ef   Pavel Shilovsky   CIFS: Fix a possi...
2861
2862
2863
2864
2865
2866
  		list_del_init(&tcon->rlist);
  		cifs_put_tcon(tcon);
  	}
  
  	cifs_dbg(FYI, "Reconnecting tcons finished
  ");
18ea43113   Germano Percossi   CIFS: reconnect t...
2867
2868
  	if (resched)
  		queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);
53e0e11ef   Pavel Shilovsky   CIFS: Fix a possi...
2869
2870
2871
2872
2873
2874
  	mutex_unlock(&server->reconnect_mutex);
  
  	/* now we can safely release srv struct */
  	if (tcon_exist)
  		cifs_put_tcp_session(server, 1);
  }
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2875
2876
2877
2878
2879
  int
  SMB2_echo(struct TCP_Server_Info *server)
  {
  	struct smb2_echo_req *req;
  	int rc = 0;
c713c8770   Ronnie Sahlberg   cifs: push rfc100...
2880
  	struct kvec iov[1];
738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
2881
  	struct smb_rqst rqst = { .rq_iov = iov,
c713c8770   Ronnie Sahlberg   cifs: push rfc100...
2882
  				 .rq_nvec = 1 };
7f7ae759f   Ronnie Sahlberg   cifs: remove rfc1...
2883
  	unsigned int total_len;
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2884

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2885
2886
  	cifs_dbg(FYI, "In echo request
  ");
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2887

4fcd1813e   Steve French   Fix reconnect to ...
2888
  	if (server->tcpStatus == CifsNeedNegotiate) {
53e0e11ef   Pavel Shilovsky   CIFS: Fix a possi...
2889
2890
2891
  		/* No need to send echo on newly established connections */
  		queue_delayed_work(cifsiod_wq, &server->reconnect, 0);
  		return rc;
4fcd1813e   Steve French   Fix reconnect to ...
2892
  	}
7f7ae759f   Ronnie Sahlberg   cifs: remove rfc1...
2893
  	rc = smb2_plain_req_init(SMB2_ECHO, NULL, (void **)&req, &total_len);
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2894
2895
  	if (rc)
  		return rc;
7f7ae759f   Ronnie Sahlberg   cifs: remove rfc1...
2896
  	req->sync_hdr.CreditRequest = cpu_to_le16(1);
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2897

c713c8770   Ronnie Sahlberg   cifs: push rfc100...
2898
2899
  	iov[0].iov_len = total_len;
  	iov[0].iov_base = (char *)req;
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2900

9b7c18a2d   Pavel Shilovsky   CIFS: Add mid han...
2901
2902
  	rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL,
  			     server, CIFS_ECHO_OP);
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2903
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2904
2905
  		cifs_dbg(FYI, "Echo request failed: %d
  ", rc);
9094fad1e   Pavel Shilovsky   CIFS: Add echo re...
2906
2907
2908
2909
  
  	cifs_small_buf_release(req);
  	return rc;
  }
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2910
2911
2912
2913
2914
  
  int
  SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
  	   u64 volatile_fid)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2915
  	struct smb_rqst rqst;
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2916
  	struct smb2_flush_req *req;
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2917
2918
  	struct cifs_ses *ses = tcon->ses;
  	struct kvec iov[1];
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2919
  	struct kvec rsp_iov;
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2920
2921
  	int resp_buftype;
  	int rc = 0;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
2922
  	int flags = 0;
1f444e4c0   Ronnie Sahlberg   cifs: remove rfc1...
2923
  	unsigned int total_len;
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2924

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2925
2926
  	cifs_dbg(FYI, "Flush
  ");
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2927

68a6afa7f   Christos Gkekas   cifs: Clean up un...
2928
  	if (!ses || !(ses->server))
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2929
  		return -EIO;
1f444e4c0   Ronnie Sahlberg   cifs: remove rfc1...
2930
  	rc = smb2_plain_req_init(SMB2_FLUSH, tcon, (void **) &req, &total_len);
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2931
2932
  	if (rc)
  		return rc;
5a77e75fe   Steve French   smb3: rename encr...
2933
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
2934
  		flags |= CIFS_TRANSFORM_REQ;
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2935
2936
2937
2938
  	req->PersistentFileId = persistent_fid;
  	req->VolatileFileId = volatile_fid;
  
  	iov[0].iov_base = (char *)req;
1f444e4c0   Ronnie Sahlberg   cifs: remove rfc1...
2939
  	iov[0].iov_len = total_len;
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2940

40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
2941
2942
2943
2944
2945
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 1;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2946
  	cifs_small_buf_release(req);
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2947

eccb4422c   Steve French   smb3: Add ftrace ...
2948
  	if (rc != 0) {
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2949
  		cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE);
eccb4422c   Steve French   smb3: Add ftrace ...
2950
2951
2952
  		trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid,
  				     rc);
  	}
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2953

da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
2954
  	free_rsp_buf(resp_buftype, rsp_iov.iov_base);
7a5cfb196   Pavel Shilovsky   CIFS: Add SMB2 su...
2955
2956
  	return rc;
  }
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
2957
2958
2959
2960
2961
2962
  
  /*
   * To form a chain of read requests, any read requests after the first should
   * have the end_of_chain boolean set to true.
   */
  static int
738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
2963
  smb2_new_read_req(void **buf, unsigned int *total_len,
2dabfd5ba   Long Li   CIFS: SMBD: Add p...
2964
2965
  	struct cifs_io_parms *io_parms, struct cifs_readdata *rdata,
  	unsigned int remaining_bytes, int request_type)
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
2966
2967
  {
  	int rc = -EACCES;
b8f57ee8a   Pavel Shilovsky   CIFS: Separate RF...
2968
  	struct smb2_read_plain_req *req = NULL;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
2969
  	struct smb2_sync_hdr *shdr;
2dabfd5ba   Long Li   CIFS: SMBD: Add p...
2970
  	struct TCP_Server_Info *server;
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
2971

b8f57ee8a   Pavel Shilovsky   CIFS: Separate RF...
2972
2973
  	rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, (void **) &req,
  				 total_len);
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
2974
2975
  	if (rc)
  		return rc;
2dabfd5ba   Long Li   CIFS: SMBD: Add p...
2976
2977
2978
  
  	server = io_parms->tcon->ses->server;
  	if (server == NULL)
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
2979
  		return -ECONNABORTED;
b8f57ee8a   Pavel Shilovsky   CIFS: Separate RF...
2980
  	shdr = &req->sync_hdr;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
2981
  	shdr->ProcessId = cpu_to_le32(io_parms->pid);
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
2982
2983
2984
2985
2986
2987
2988
2989
2990
  
  	req->PersistentFileId = io_parms->persistent_fid;
  	req->VolatileFileId = io_parms->volatile_fid;
  	req->ReadChannelInfoOffset = 0; /* reserved */
  	req->ReadChannelInfoLength = 0; /* reserved */
  	req->Channel = 0; /* reserved */
  	req->MinimumCount = 0;
  	req->Length = cpu_to_le32(io_parms->length);
  	req->Offset = cpu_to_le64(io_parms->offset);
bd3dcc6a2   Long Li   CIFS: SMBD: Upper...
2991
2992
2993
2994
2995
  #ifdef CONFIG_CIFS_SMB_DIRECT
  	/*
  	 * If we want to do a RDMA write, fill in and append
  	 * smbd_buffer_descriptor_v1 to the end of read request
  	 */
bb4c04194   Long Li   cifs: smbd: Don't...
2996
  	if (server->rdma && rdata && !server->sign &&
bd3dcc6a2   Long Li   CIFS: SMBD: Upper...
2997
2998
2999
3000
3001
3002
3003
3004
  		rdata->bytes >= server->smbd_conn->rdma_readwrite_threshold) {
  
  		struct smbd_buffer_descriptor_v1 *v1;
  		bool need_invalidate =
  			io_parms->tcon->ses->server->dialect == SMB30_PROT_ID;
  
  		rdata->mr = smbd_register_mr(
  				server->smbd_conn, rdata->pages,
7cf20bce7   Long Li   CIFS: SMBD: Suppo...
3005
3006
  				rdata->nr_pages, rdata->page_offset,
  				rdata->tailsz, true, need_invalidate);
bd3dcc6a2   Long Li   CIFS: SMBD: Upper...
3007
3008
3009
3010
3011
3012
3013
  		if (!rdata->mr)
  			return -ENOBUFS;
  
  		req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
  		if (need_invalidate)
  			req->Channel = SMB2_CHANNEL_RDMA_V1;
  		req->ReadChannelInfoOffset =
2026b06e9   Steve French   Cleanup some mino...
3014
  			cpu_to_le16(offsetof(struct smb2_read_plain_req, Buffer));
bd3dcc6a2   Long Li   CIFS: SMBD: Upper...
3015
  		req->ReadChannelInfoLength =
2026b06e9   Steve French   Cleanup some mino...
3016
  			cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
bd3dcc6a2   Long Li   CIFS: SMBD: Upper...
3017
  		v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
2026b06e9   Steve French   Cleanup some mino...
3018
3019
3020
  		v1->offset = cpu_to_le64(rdata->mr->mr->iova);
  		v1->token = cpu_to_le32(rdata->mr->mr->rkey);
  		v1->length = cpu_to_le32(rdata->mr->mr->length);
bd3dcc6a2   Long Li   CIFS: SMBD: Upper...
3021
3022
3023
3024
  
  		*total_len += sizeof(*v1) - 1;
  	}
  #endif
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3025
3026
  	if (request_type & CHAINED_REQUEST) {
  		if (!(request_type & END_OF_CHAIN)) {
b8f57ee8a   Pavel Shilovsky   CIFS: Separate RF...
3027
3028
3029
  			/* next 8-byte aligned request */
  			*total_len = DIV_ROUND_UP(*total_len, 8) * 8;
  			shdr->NextCommand = cpu_to_le32(*total_len);
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3030
  		} else /* END_OF_CHAIN */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3031
  			shdr->NextCommand = 0;
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3032
  		if (request_type & RELATED_REQUEST) {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3033
  			shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3034
3035
3036
3037
  			/*
  			 * Related requests use info from previous read request
  			 * in chain.
  			 */
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3038
3039
  			shdr->SessionId = 0xFFFFFFFF;
  			shdr->TreeId = 0xFFFFFFFF;
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3040
3041
3042
3043
3044
3045
3046
3047
  			req->PersistentFileId = 0xFFFFFFFF;
  			req->VolatileFileId = 0xFFFFFFFF;
  		}
  	}
  	if (remaining_bytes > io_parms->length)
  		req->RemainingBytes = cpu_to_le32(remaining_bytes);
  	else
  		req->RemainingBytes = 0;
738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
3048
  	*buf = req;
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3049
3050
3051
3052
3053
3054
3055
3056
3057
  	return rc;
  }
  
  static void
  smb2_readv_callback(struct mid_q_entry *mid)
  {
  	struct cifs_readdata *rdata = mid->callback_data;
  	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
  	struct TCP_Server_Info *server = tcon->ses->server;
738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
3058
  	struct smb2_sync_hdr *shdr =
977b61704   Ronnie Sahlberg   cifs: remove rfc1...
3059
  				(struct smb2_sync_hdr *)rdata->iov[0].iov_base;
b1765ebd9   Pavel Shilovsky   CIFS: Do not assu...
3060
  	unsigned int credits_received = 0;
738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
3061
3062
  	struct smb_rqst rqst = { .rq_iov = rdata->iov,
  				 .rq_nvec = 2,
8321fec43   Jeff Layton   cifs: convert asy...
3063
  				 .rq_pages = rdata->pages,
1dbe3466b   Long Li   CIFS: Use offset ...
3064
  				 .rq_offset = rdata->page_offset,
8321fec43   Jeff Layton   cifs: convert asy...
3065
3066
3067
  				 .rq_npages = rdata->nr_pages,
  				 .rq_pagesz = rdata->pagesz,
  				 .rq_tailsz = rdata->tailsz };
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3068

f96637be0   Joe Perches   [CIFS] cifs: Rena...
3069
3070
3071
3072
  	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u
  ",
  		 __func__, mid->mid, mid->mid_state, rdata->result,
  		 rdata->bytes);
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3073
3074
3075
  
  	switch (mid->mid_state) {
  	case MID_RESPONSE_RECEIVED:
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3076
  		credits_received = le16_to_cpu(shdr->CreditRequest);
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3077
  		/* result already set, check signature */
4326ed2f6   Pavel Shilovsky   CIFS: Decrypt and...
3078
  		if (server->sign && !mid->decrypted) {
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
3079
  			int rc;
0b688cfc8   Jeff Layton   cifs: change smb2...
3080
  			rc = smb2_verify_signature(&rqst, server);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
3081
  			if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3082
3083
3084
  				cifs_dbg(VFS, "SMB signature verification returned error = %d
  ",
  					 rc);
3c1bf7e48   Pavel Shilovsky   CIFS: Enable sign...
3085
  		}
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3086
  		/* FIXME: should this be counted toward the initiating task? */
34a54d617   Pavel Shilovsky   CIFS: Use separat...
3087
3088
  		task_io_account_read(rdata->got_bytes);
  		cifs_stats_bytes_read(tcon, rdata->got_bytes);
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3089
3090
3091
3092
  		break;
  	case MID_REQUEST_SUBMITTED:
  	case MID_RETRY_NEEDED:
  		rdata->result = -EAGAIN;
d913ed17f   Pavel Shilovsky   CIFS: Optimize ci...
3093
3094
3095
3096
3097
3098
  		if (server->sign && rdata->got_bytes)
  			/* reset bytes number since we can not check a sign */
  			rdata->got_bytes = 0;
  		/* FIXME: should this be counted toward the initiating task? */
  		task_io_account_read(rdata->got_bytes);
  		cifs_stats_bytes_read(tcon, rdata->got_bytes);
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3099
  		break;
b1765ebd9   Pavel Shilovsky   CIFS: Do not assu...
3100
3101
3102
  	case MID_RESPONSE_MALFORMED:
  		credits_received = le16_to_cpu(shdr->CreditRequest);
  		/* fall through */
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3103
3104
3105
3106
  	default:
  		if (rdata->result != -ENODATA)
  			rdata->result = -EIO;
  	}
bd3dcc6a2   Long Li   CIFS: SMBD: Upper...
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
  #ifdef CONFIG_CIFS_SMB_DIRECT
  	/*
  	 * If this rdata has a memmory registered, the MR can be freed
  	 * MR needs to be freed as soon as I/O finishes to prevent deadlock
  	 * because they have limited number and are used for future I/Os
  	 */
  	if (rdata->mr) {
  		smbd_deregister_mr(rdata->mr);
  		rdata->mr = NULL;
  	}
  #endif
e9d56f920   Pavel Shilovsky   CIFS: Do not cons...
3118
  	if (rdata->result && rdata->result != -ENODATA) {
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3119
  		cifs_stats_fail_inc(tcon, SMB2_READ_HE);
6e7045ec3   Pavel Shilovsky   CIFS: Fix trace c...
3120
3121
3122
3123
3124
3125
3126
3127
3128
  		trace_smb3_read_err(0 /* xid */,
  				    rdata->cfile->fid.persistent_fid,
  				    tcon->tid, tcon->ses->Suid, rdata->offset,
  				    rdata->bytes, rdata->result);
  	} else
  		trace_smb3_read_done(0 /* xid */,
  				     rdata->cfile->fid.persistent_fid,
  				     tcon->tid, tcon->ses->Suid,
  				     rdata->offset, rdata->got_bytes);
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3129
3130
3131
3132
3133
  
  	queue_work(cifsiod_wq, &rdata->work);
  	DeleteMidQEntry(mid);
  	add_credits(server, credits_received, 0);
  }
738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
3134
  /* smb2_async_readv - send an async read, and set up mid to handle result */
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3135
3136
3137
  int
  smb2_async_readv(struct cifs_readdata *rdata)
  {
bed9da021   Pavel Shilovsky   CIFS: Use multicr...
3138
  	int rc, flags = 0;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3139
3140
  	char *buf;
  	struct smb2_sync_hdr *shdr;
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3141
  	struct cifs_io_parms io_parms;
738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
3142
  	struct smb_rqst rqst = { .rq_iov = rdata->iov,
c713c8770   Ronnie Sahlberg   cifs: push rfc100...
3143
  				 .rq_nvec = 1 };
bed9da021   Pavel Shilovsky   CIFS: Use multicr...
3144
  	struct TCP_Server_Info *server;
738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
3145
  	unsigned int total_len;
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3146

f96637be0   Joe Perches   [CIFS] cifs: Rena...
3147
3148
3149
  	cifs_dbg(FYI, "%s: offset=%llu bytes=%u
  ",
  		 __func__, rdata->offset, rdata->bytes);
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3150
3151
3152
3153
3154
3155
3156
  
  	io_parms.tcon = tlink_tcon(rdata->cfile->tlink);
  	io_parms.offset = rdata->offset;
  	io_parms.length = rdata->bytes;
  	io_parms.persistent_fid = rdata->cfile->fid.persistent_fid;
  	io_parms.volatile_fid = rdata->cfile->fid.volatile_fid;
  	io_parms.pid = rdata->pid;
bed9da021   Pavel Shilovsky   CIFS: Use multicr...
3157
3158
  
  	server = io_parms.tcon->ses->server;
2dabfd5ba   Long Li   CIFS: SMBD: Add p...
3159
3160
  	rc = smb2_new_read_req(
  		(void **) &buf, &total_len, &io_parms, rdata, 0, 0);
bed9da021   Pavel Shilovsky   CIFS: Use multicr...
3161
3162
3163
3164
3165
3166
3167
3168
3169
  	if (rc) {
  		if (rc == -EAGAIN && rdata->credits) {
  			/* credits was reset by reconnect */
  			rdata->credits = 0;
  			/* reduce in_flight value since we won't send the req */
  			spin_lock(&server->req_lock);
  			server->in_flight--;
  			spin_unlock(&server->req_lock);
  		}
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3170
  		return rc;
bed9da021   Pavel Shilovsky   CIFS: Use multicr...
3171
  	}
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3172

5a77e75fe   Steve French   smb3: rename encr...
3173
  	if (smb3_encryption_required(io_parms.tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3174
  		flags |= CIFS_TRANSFORM_REQ;
c713c8770   Ronnie Sahlberg   cifs: push rfc100...
3175
3176
  	rdata->iov[0].iov_base = buf;
  	rdata->iov[0].iov_len = total_len;
b8f57ee8a   Pavel Shilovsky   CIFS: Separate RF...
3177
3178
  
  	shdr = (struct smb2_sync_hdr *)buf;
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3179

bed9da021   Pavel Shilovsky   CIFS: Use multicr...
3180
  	if (rdata->credits) {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3181
  		shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
bed9da021   Pavel Shilovsky   CIFS: Use multicr...
3182
  						SMB2_MAX_BUFFER_SIZE));
d1130682d   Pavel Shilovsky   CIFS: Fix adjustm...
3183
3184
  		shdr->CreditRequest =
  			cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1);
bed9da021   Pavel Shilovsky   CIFS: Use multicr...
3185
3186
  		spin_lock(&server->req_lock);
  		server->credits += rdata->credits -
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3187
  						le16_to_cpu(shdr->CreditCharge);
bed9da021   Pavel Shilovsky   CIFS: Use multicr...
3188
3189
  		spin_unlock(&server->req_lock);
  		wake_up(&server->request_q);
d1130682d   Pavel Shilovsky   CIFS: Fix adjustm...
3190
  		rdata->credits = le16_to_cpu(shdr->CreditCharge);
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3191
  		flags |= CIFS_HAS_CREDITS;
bed9da021   Pavel Shilovsky   CIFS: Use multicr...
3192
  	}
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3193
  	kref_get(&rdata->refcount);
fec344e3f   Jeff Layton   cifs: change cifs...
3194
  	rc = cifs_call_async(io_parms.tcon->ses->server, &rqst,
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3195
  			     cifs_readv_receive, smb2_readv_callback,
4326ed2f6   Pavel Shilovsky   CIFS: Decrypt and...
3196
  			     smb3_handle_read_data, rdata, flags);
e5d048871   Pavel Shilovsky   CIFS: Fix possibl...
3197
  	if (rc) {
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3198
  		kref_put(&rdata->refcount, cifs_readdata_release);
e5d048871   Pavel Shilovsky   CIFS: Fix possibl...
3199
  		cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
6e7045ec3   Pavel Shilovsky   CIFS: Fix trace c...
3200
3201
3202
3203
3204
  		trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
  				    io_parms.tcon->tid,
  				    io_parms.tcon->ses->Suid,
  				    io_parms.offset, io_parms.length, rc);
  	}
09a4707e7   Pavel Shilovsky   CIFS: Add SMB2 su...
3205
3206
3207
3208
  
  	cifs_small_buf_release(buf);
  	return rc;
  }
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3209

d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3210
3211
3212
3213
  int
  SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
  	  unsigned int *nbytes, char **buf, int *buf_type)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
3214
  	struct smb_rqst rqst;
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3215
  	int resp_buftype, rc = -EACCES;
b8f57ee8a   Pavel Shilovsky   CIFS: Separate RF...
3216
  	struct smb2_read_plain_req *req = NULL;
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3217
  	struct smb2_read_rsp *rsp = NULL;
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3218
  	struct kvec iov[1];
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3219
  	struct kvec rsp_iov;
738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
3220
  	unsigned int total_len;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3221
3222
  	int flags = CIFS_LOG_ERROR;
  	struct cifs_ses *ses = io_parms->tcon->ses;
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3223
3224
  
  	*nbytes = 0;
2dabfd5ba   Long Li   CIFS: SMBD: Add p...
3225
  	rc = smb2_new_read_req((void **)&req, &total_len, io_parms, NULL, 0, 0);
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3226
3227
  	if (rc)
  		return rc;
5a77e75fe   Steve French   smb3: rename encr...
3228
  	if (smb3_encryption_required(io_parms->tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3229
  		flags |= CIFS_TRANSFORM_REQ;
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3230
3231
  	iov[0].iov_base = (char *)req;
  	iov[0].iov_len = total_len;
b8f57ee8a   Pavel Shilovsky   CIFS: Separate RF...
3232

40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
3233
3234
3235
3236
3237
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 1;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
b8f57ee8a   Pavel Shilovsky   CIFS: Separate RF...
3238
  	cifs_small_buf_release(req);
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3239

da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3240
  	rsp = (struct smb2_read_rsp *)rsp_iov.iov_base;
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3241

a821df3f1   Ronnie Sahlberg   cifs: fix NULL de...
3242
3243
3244
3245
3246
  	if (rc) {
  		if (rc != -ENODATA) {
  			cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
  			cifs_dbg(VFS, "Send error in read = %d
  ", rc);
6e7045ec3   Pavel Shilovsky   CIFS: Fix trace c...
3247
3248
3249
3250
  			trace_smb3_read_err(xid, req->PersistentFileId,
  					    io_parms->tcon->tid, ses->Suid,
  					    io_parms->offset, io_parms->length,
  					    rc);
a821df3f1   Ronnie Sahlberg   cifs: fix NULL de...
3251
  		}
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3252
  		free_rsp_buf(resp_buftype, rsp_iov.iov_base);
a821df3f1   Ronnie Sahlberg   cifs: fix NULL de...
3253
  		return rc == -ENODATA ? 0 : rc;
eccb4422c   Steve French   smb3: Add ftrace ...
3254
3255
3256
3257
  	} else
  		trace_smb3_read_done(xid, req->PersistentFileId,
  				    io_parms->tcon->tid, ses->Suid,
  				    io_parms->offset, io_parms->length);
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3258

a821df3f1   Ronnie Sahlberg   cifs: fix NULL de...
3259
3260
3261
3262
3263
3264
3265
3266
  	*nbytes = le32_to_cpu(rsp->DataLength);
  	if ((*nbytes > CIFS_MAX_MSGSIZE) ||
  	    (*nbytes > io_parms->length)) {
  		cifs_dbg(FYI, "bad length %d for count %d
  ",
  			 *nbytes, io_parms->length);
  		rc = -EIO;
  		*nbytes = 0;
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3267
3268
3269
  	}
  
  	if (*buf) {
977b61704   Ronnie Sahlberg   cifs: remove rfc1...
3270
  		memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3271
  		free_rsp_buf(resp_buftype, rsp_iov.iov_base);
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3272
  	} else if (resp_buftype != CIFS_NO_BUFFER) {
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3273
  		*buf = rsp_iov.iov_base;
d8e050398   Pavel Shilovsky   CIFS: Add readpag...
3274
3275
3276
3277
3278
3279
3280
  		if (resp_buftype == CIFS_SMALL_BUFFER)
  			*buf_type = CIFS_SMALL_BUFFER;
  		else if (resp_buftype == CIFS_LARGE_BUFFER)
  			*buf_type = CIFS_LARGE_BUFFER;
  	}
  	return rc;
  }
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
  /*
   * Check the mid_state and signature on received buffer (if any), and queue the
   * workqueue completion task.
   */
  static void
  smb2_writev_callback(struct mid_q_entry *mid)
  {
  	struct cifs_writedata *wdata = mid->callback_data;
  	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
  	unsigned int written;
  	struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
b1765ebd9   Pavel Shilovsky   CIFS: Do not assu...
3292
  	unsigned int credits_received = 0;
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3293
3294
3295
  
  	switch (mid->mid_state) {
  	case MID_RESPONSE_RECEIVED:
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
3296
  		credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
  		wdata->result = smb2_check_receive(mid, tcon->ses->server, 0);
  		if (wdata->result != 0)
  			break;
  
  		written = le32_to_cpu(rsp->DataLength);
  		/*
  		 * Mask off high 16 bits when bytes written as returned
  		 * by the server is greater than bytes requested by the
  		 * client. OS/2 servers are known to set incorrect
  		 * CountHigh values.
  		 */
  		if (written > wdata->bytes)
  			written &= 0xFFFF;
  
  		if (written < wdata->bytes)
  			wdata->result = -ENOSPC;
  		else
  			wdata->bytes = written;
  		break;
  	case MID_REQUEST_SUBMITTED:
  	case MID_RETRY_NEEDED:
  		wdata->result = -EAGAIN;
  		break;
b1765ebd9   Pavel Shilovsky   CIFS: Do not assu...
3320
3321
3322
  	case MID_RESPONSE_MALFORMED:
  		credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
  		/* fall through */
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3323
3324
3325
3326
  	default:
  		wdata->result = -EIO;
  		break;
  	}
db223a590   Long Li   CIFS: SMBD: Upper...
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
  #ifdef CONFIG_CIFS_SMB_DIRECT
  	/*
  	 * If this wdata has a memory registered, the MR can be freed
  	 * The number of MRs available is limited, it's important to recover
  	 * used MR as soon as I/O is finished. Hold MR longer in the later
  	 * I/O process can possibly result in I/O deadlock due to lack of MR
  	 * to send request on I/O retry
  	 */
  	if (wdata->mr) {
  		smbd_deregister_mr(wdata->mr);
  		wdata->mr = NULL;
  	}
  #endif
6e7045ec3   Pavel Shilovsky   CIFS: Fix trace c...
3340
  	if (wdata->result) {
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3341
  		cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
6e7045ec3   Pavel Shilovsky   CIFS: Fix trace c...
3342
3343
3344
3345
3346
3347
3348
3349
3350
  		trace_smb3_write_err(0 /* no xid */,
  				     wdata->cfile->fid.persistent_fid,
  				     tcon->tid, tcon->ses->Suid, wdata->offset,
  				     wdata->bytes, wdata->result);
  	} else
  		trace_smb3_write_done(0 /* no xid */,
  				      wdata->cfile->fid.persistent_fid,
  				      tcon->tid, tcon->ses->Suid,
  				      wdata->offset, wdata->bytes);
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3351
3352
3353
3354
3355
3356
3357
3358
  
  	queue_work(cifsiod_wq, &wdata->work);
  	DeleteMidQEntry(mid);
  	add_credits(tcon->ses->server, credits_received, 0);
  }
  
  /* smb2_async_writev - send an async write, and set up mid to handle result */
  int
4a5c80d7b   Steve French   [CIFS] clean up p...
3359
3360
  smb2_async_writev(struct cifs_writedata *wdata,
  		  void (*release)(struct kref *kref))
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3361
  {
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
3362
  	int rc = -EACCES, flags = 0;
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3363
  	struct smb2_write_req *req = NULL;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3364
  	struct smb2_sync_hdr *shdr;
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3365
  	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
3366
  	struct TCP_Server_Info *server = tcon->ses->server;
c713c8770   Ronnie Sahlberg   cifs: push rfc100...
3367
  	struct kvec iov[1];
738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
3368
  	struct smb_rqst rqst = { };
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3369
  	unsigned int total_len;
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3370

f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3371
  	rc = smb2_plain_req_init(SMB2_WRITE, tcon, (void **) &req, &total_len);
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
3372
3373
3374
3375
3376
3377
3378
3379
3380
  	if (rc) {
  		if (rc == -EAGAIN && wdata->credits) {
  			/* credits was reset by reconnect */
  			wdata->credits = 0;
  			/* reduce in_flight value since we won't send the req */
  			spin_lock(&server->req_lock);
  			server->in_flight--;
  			spin_unlock(&server->req_lock);
  		}
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3381
  		goto async_writev_out;
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
3382
  	}
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3383

5a77e75fe   Steve French   smb3: rename encr...
3384
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3385
  		flags |= CIFS_TRANSFORM_REQ;
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3386
  	shdr = (struct smb2_sync_hdr *)req;
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3387
  	shdr->ProcessId = cpu_to_le32(wdata->cfile->pid);
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3388
3389
3390
3391
3392
3393
3394
  
  	req->PersistentFileId = wdata->cfile->fid.persistent_fid;
  	req->VolatileFileId = wdata->cfile->fid.volatile_fid;
  	req->WriteChannelInfoOffset = 0;
  	req->WriteChannelInfoLength = 0;
  	req->Channel = 0;
  	req->Offset = cpu_to_le64(wdata->offset);
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3395
  	req->DataOffset = cpu_to_le16(
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3396
  				offsetof(struct smb2_write_req, Buffer));
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3397
  	req->RemainingBytes = 0;
db223a590   Long Li   CIFS: SMBD: Upper...
3398
3399
3400
3401
3402
  #ifdef CONFIG_CIFS_SMB_DIRECT
  	/*
  	 * If we want to do a server RDMA read, fill in and append
  	 * smbd_buffer_descriptor_v1 to the end of write request
  	 */
bb4c04194   Long Li   cifs: smbd: Don't...
3403
  	if (server->rdma && !server->sign && wdata->bytes >=
db223a590   Long Li   CIFS: SMBD: Upper...
3404
3405
3406
3407
3408
3409
3410
  		server->smbd_conn->rdma_readwrite_threshold) {
  
  		struct smbd_buffer_descriptor_v1 *v1;
  		bool need_invalidate = server->dialect == SMB30_PROT_ID;
  
  		wdata->mr = smbd_register_mr(
  				server->smbd_conn, wdata->pages,
7cf20bce7   Long Li   CIFS: SMBD: Suppo...
3411
3412
  				wdata->nr_pages, wdata->page_offset,
  				wdata->tailsz, false, need_invalidate);
db223a590   Long Li   CIFS: SMBD: Upper...
3413
3414
3415
3416
3417
3418
  		if (!wdata->mr) {
  			rc = -ENOBUFS;
  			goto async_writev_out;
  		}
  		req->Length = 0;
  		req->DataOffset = 0;
7cf20bce7   Long Li   CIFS: SMBD: Suppo...
3419
3420
3421
3422
3423
3424
3425
3426
  		if (wdata->nr_pages > 1)
  			req->RemainingBytes =
  				cpu_to_le32(
  					(wdata->nr_pages - 1) * wdata->pagesz -
  					wdata->page_offset + wdata->tailsz
  				);
  		else
  			req->RemainingBytes = cpu_to_le32(wdata->tailsz);
db223a590   Long Li   CIFS: SMBD: Upper...
3427
3428
3429
3430
  		req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
  		if (need_invalidate)
  			req->Channel = SMB2_CHANNEL_RDMA_V1;
  		req->WriteChannelInfoOffset =
2026b06e9   Steve French   Cleanup some mino...
3431
  			cpu_to_le16(offsetof(struct smb2_write_req, Buffer));
db223a590   Long Li   CIFS: SMBD: Upper...
3432
  		req->WriteChannelInfoLength =
2026b06e9   Steve French   Cleanup some mino...
3433
  			cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
db223a590   Long Li   CIFS: SMBD: Upper...
3434
  		v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
2026b06e9   Steve French   Cleanup some mino...
3435
3436
3437
  		v1->offset = cpu_to_le64(wdata->mr->mr->iova);
  		v1->token = cpu_to_le32(wdata->mr->mr->rkey);
  		v1->length = cpu_to_le32(wdata->mr->mr->length);
db223a590   Long Li   CIFS: SMBD: Upper...
3438
3439
  	}
  #endif
c713c8770   Ronnie Sahlberg   cifs: push rfc100...
3440
3441
  	iov[0].iov_len = total_len - 1;
  	iov[0].iov_base = (char *)req;
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3442

738f9de5c   Pavel Shilovsky   CIFS: Send RFC100...
3443
  	rqst.rq_iov = iov;
c713c8770   Ronnie Sahlberg   cifs: push rfc100...
3444
  	rqst.rq_nvec = 1;
eddb079de   Jeff Layton   cifs: convert asy...
3445
  	rqst.rq_pages = wdata->pages;
57a929a66   Long Li   CIFS: Introduce o...
3446
  	rqst.rq_offset = wdata->page_offset;
eddb079de   Jeff Layton   cifs: convert asy...
3447
3448
3449
  	rqst.rq_npages = wdata->nr_pages;
  	rqst.rq_pagesz = wdata->pagesz;
  	rqst.rq_tailsz = wdata->tailsz;
db223a590   Long Li   CIFS: SMBD: Upper...
3450
3451
  #ifdef CONFIG_CIFS_SMB_DIRECT
  	if (wdata->mr) {
c713c8770   Ronnie Sahlberg   cifs: push rfc100...
3452
  		iov[0].iov_len += sizeof(struct smbd_buffer_descriptor_v1);
db223a590   Long Li   CIFS: SMBD: Upper...
3453
3454
3455
  		rqst.rq_npages = 0;
  	}
  #endif
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3456
3457
3458
  	cifs_dbg(FYI, "async write at %llu %u bytes
  ",
  		 wdata->offset, wdata->bytes);
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3459

db223a590   Long Li   CIFS: SMBD: Upper...
3460
3461
3462
3463
3464
  #ifdef CONFIG_CIFS_SMB_DIRECT
  	/* For RDMA read, I/O size is in RemainingBytes not in Length */
  	if (!wdata->mr)
  		req->Length = cpu_to_le32(wdata->bytes);
  #else
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3465
  	req->Length = cpu_to_le32(wdata->bytes);
db223a590   Long Li   CIFS: SMBD: Upper...
3466
  #endif
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3467

cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
3468
  	if (wdata->credits) {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3469
  		shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
3470
  						    SMB2_MAX_BUFFER_SIZE));
d1130682d   Pavel Shilovsky   CIFS: Fix adjustm...
3471
3472
  		shdr->CreditRequest =
  			cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1);
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
3473
3474
  		spin_lock(&server->req_lock);
  		server->credits += wdata->credits -
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3475
  						le16_to_cpu(shdr->CreditCharge);
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
3476
3477
  		spin_unlock(&server->req_lock);
  		wake_up(&server->request_q);
d1130682d   Pavel Shilovsky   CIFS: Fix adjustm...
3478
  		wdata->credits = le16_to_cpu(shdr->CreditCharge);
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3479
  		flags |= CIFS_HAS_CREDITS;
cb7e9eabb   Pavel Shilovsky   CIFS: Use multicr...
3480
  	}
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3481
  	kref_get(&wdata->refcount);
9b7c18a2d   Pavel Shilovsky   CIFS: Add mid han...
3482
3483
  	rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL,
  			     wdata, flags);
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3484

e5d048871   Pavel Shilovsky   CIFS: Fix possibl...
3485
  	if (rc) {
eccb4422c   Steve French   smb3: Add ftrace ...
3486
3487
3488
  		trace_smb3_write_err(0 /* no xid */, req->PersistentFileId,
  				     tcon->tid, tcon->ses->Suid, wdata->offset,
  				     wdata->bytes, rc);
4a5c80d7b   Steve French   [CIFS] clean up p...
3489
  		kref_put(&wdata->refcount, release);
e5d048871   Pavel Shilovsky   CIFS: Fix possibl...
3490
  		cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
6e7045ec3   Pavel Shilovsky   CIFS: Fix trace c...
3491
  	}
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3492

333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3493
3494
  async_writev_out:
  	cifs_small_buf_release(req);
333191412   Pavel Shilovsky   CIFS: Add SMB2 su...
3495
3496
  	return rc;
  }
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
  
  /*
   * SMB2_write function gets iov pointer to kvec array with n_vec as a length.
   * The length field from io_parms must be at least 1 and indicates a number of
   * elements with data to write that begins with position 1 in iov array. All
   * data length is specified by count.
   */
  int
  SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
  	   unsigned int *nbytes, struct kvec *iov, int n_vec)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
3508
  	struct smb_rqst rqst;
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3509
3510
3511
3512
  	int rc = 0;
  	struct smb2_write_req *req = NULL;
  	struct smb2_write_rsp *rsp = NULL;
  	int resp_buftype;
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3513
  	struct kvec rsp_iov;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3514
  	int flags = 0;
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3515
  	unsigned int total_len;
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3516

009d34439   Pavel Shilovsky   CIFS: Add writepa...
3517
3518
3519
3520
  	*nbytes = 0;
  
  	if (n_vec < 1)
  		return rc;
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3521
3522
  	rc = smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, (void **) &req,
  			     &total_len);
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3523
3524
3525
3526
3527
  	if (rc)
  		return rc;
  
  	if (io_parms->tcon->ses->server == NULL)
  		return -ECONNABORTED;
5a77e75fe   Steve French   smb3: rename encr...
3528
  	if (smb3_encryption_required(io_parms->tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3529
  		flags |= CIFS_TRANSFORM_REQ;
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3530
  	req->sync_hdr.ProcessId = cpu_to_le32(io_parms->pid);
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3531
3532
3533
3534
3535
3536
3537
3538
  
  	req->PersistentFileId = io_parms->persistent_fid;
  	req->VolatileFileId = io_parms->volatile_fid;
  	req->WriteChannelInfoOffset = 0;
  	req->WriteChannelInfoLength = 0;
  	req->Channel = 0;
  	req->Length = cpu_to_le32(io_parms->length);
  	req->Offset = cpu_to_le64(io_parms->offset);
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3539
  	req->DataOffset = cpu_to_le16(
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3540
  				offsetof(struct smb2_write_req, Buffer));
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3541
3542
3543
  	req->RemainingBytes = 0;
  
  	iov[0].iov_base = (char *)req;
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3544
3545
  	/* 1 for Buffer */
  	iov[0].iov_len = total_len - 1;
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3546

40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
3547
3548
3549
3550
3551
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = n_vec + 1;
  
  	rc = cifs_send_recv(xid, io_parms->tcon->ses, &rqst,
f5688a6d7   Ronnie Sahlberg   cifs: remove rfc1...
3552
  			    &resp_buftype, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3553
3554
  	cifs_small_buf_release(req);
  	rsp = (struct smb2_write_rsp *)rsp_iov.iov_base;
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3555
3556
  
  	if (rc) {
eccb4422c   Steve French   smb3: Add ftrace ...
3557
3558
3559
3560
  		trace_smb3_write_err(xid, req->PersistentFileId,
  				     io_parms->tcon->tid,
  				     io_parms->tcon->ses->Suid,
  				     io_parms->offset, io_parms->length, rc);
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3561
  		cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3562
3563
  		cifs_dbg(VFS, "Send error in write = %d
  ", rc);
eccb4422c   Steve French   smb3: Add ftrace ...
3564
  	} else {
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3565
  		*nbytes = le32_to_cpu(rsp->DataLength);
eccb4422c   Steve French   smb3: Add ftrace ...
3566
3567
3568
3569
3570
  		trace_smb3_write_done(xid, req->PersistentFileId,
  				     io_parms->tcon->tid,
  				     io_parms->tcon->ses->Suid,
  				     io_parms->offset, *nbytes);
  	}
e5d048871   Pavel Shilovsky   CIFS: Fix possibl...
3571
3572
  
  	free_rsp_buf(resp_buftype, rsp);
009d34439   Pavel Shilovsky   CIFS: Add writepa...
3573
3574
  	return rc;
  }
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3575

d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3576
3577
3578
3579
3580
3581
  static unsigned int
  num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size)
  {
  	int len;
  	unsigned int entrycount = 0;
  	unsigned int next_offset = 0;
56446f218   Dan Carpenter   CIFS: fix wrappin...
3582
3583
  	char *entryptr;
  	FILE_DIRECTORY_INFO *dir_info;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3584
3585
3586
  
  	if (bufstart == NULL)
  		return 0;
56446f218   Dan Carpenter   CIFS: fix wrappin...
3587
  	entryptr = bufstart;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3588
3589
  
  	while (1) {
56446f218   Dan Carpenter   CIFS: fix wrappin...
3590
3591
3592
  		if (entryptr + next_offset < entryptr ||
  		    entryptr + next_offset > end_of_buf ||
  		    entryptr + next_offset + size > end_of_buf) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3593
3594
  			cifs_dbg(VFS, "malformed search entry would overflow
  ");
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3595
3596
  			break;
  		}
56446f218   Dan Carpenter   CIFS: fix wrappin...
3597
3598
3599
3600
3601
3602
3603
  		entryptr = entryptr + next_offset;
  		dir_info = (FILE_DIRECTORY_INFO *)entryptr;
  
  		len = le32_to_cpu(dir_info->FileNameLength);
  		if (entryptr + len < entryptr ||
  		    entryptr + len > end_of_buf ||
  		    entryptr + len + size > end_of_buf) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3604
3605
3606
  			cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p
  ",
  				 end_of_buf);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3607
3608
  			break;
  		}
56446f218   Dan Carpenter   CIFS: fix wrappin...
3609
  		*lastentry = entryptr;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3610
  		entrycount++;
56446f218   Dan Carpenter   CIFS: fix wrappin...
3611
  		next_offset = le32_to_cpu(dir_info->NextEntryOffset);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
  		if (!next_offset)
  			break;
  	}
  
  	return entrycount;
  }
  
  /*
   * Readdir/FindFirst
   */
  int
  SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
  		     u64 persistent_fid, u64 volatile_fid, int index,
  		     struct cifs_search_info *srch_inf)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
3627
  	struct smb_rqst rqst;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3628
3629
3630
  	struct smb2_query_directory_req *req;
  	struct smb2_query_directory_rsp *rsp = NULL;
  	struct kvec iov[2];
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3631
  	struct kvec rsp_iov;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3632
3633
  	int rc = 0;
  	int len;
75fdfc849   Steve French   Fix warning on un...
3634
  	int resp_buftype = CIFS_NO_BUFFER;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3635
3636
3637
3638
3639
3640
3641
  	unsigned char *bufptr;
  	struct TCP_Server_Info *server;
  	struct cifs_ses *ses = tcon->ses;
  	__le16 asteriks = cpu_to_le16('*');
  	char *end_of_smb;
  	unsigned int output_size = CIFSMaxBufSize;
  	size_t info_buf_size;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3642
  	int flags = 0;
7c00c3a62   Ronnie Sahlberg   cifs: remove rfc1...
3643
  	unsigned int total_len;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3644
3645
3646
3647
3648
  
  	if (ses && (ses->server))
  		server = ses->server;
  	else
  		return -EIO;
7c00c3a62   Ronnie Sahlberg   cifs: remove rfc1...
3649
3650
  	rc = smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, (void **) &req,
  			     &total_len);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3651
3652
  	if (rc)
  		return rc;
5a77e75fe   Steve French   smb3: rename encr...
3653
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3654
  		flags |= CIFS_TRANSFORM_REQ;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
  	switch (srch_inf->info_level) {
  	case SMB_FIND_FILE_DIRECTORY_INFO:
  		req->FileInformationClass = FILE_DIRECTORY_INFORMATION;
  		info_buf_size = sizeof(FILE_DIRECTORY_INFO) - 1;
  		break;
  	case SMB_FIND_FILE_ID_FULL_DIR_INFO:
  		req->FileInformationClass = FILEID_FULL_DIRECTORY_INFORMATION;
  		info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1;
  		break;
  	default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3665
3666
3667
  		cifs_dbg(VFS, "info level %u isn't supported
  ",
  			 srch_inf->info_level);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
  		rc = -EINVAL;
  		goto qdir_exit;
  	}
  
  	req->FileIndex = cpu_to_le32(index);
  	req->PersistentFileId = persistent_fid;
  	req->VolatileFileId = volatile_fid;
  
  	len = 0x2;
  	bufptr = req->Buffer;
  	memcpy(bufptr, &asteriks, len);
  
  	req->FileNameOffset =
7c00c3a62   Ronnie Sahlberg   cifs: remove rfc1...
3681
  		cpu_to_le16(sizeof(struct smb2_query_directory_req) - 1);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
  	req->FileNameLength = cpu_to_le16(len);
  	/*
  	 * BB could be 30 bytes or so longer if we used SMB2 specific
  	 * buffer lengths, but this is safe and close enough.
  	 */
  	output_size = min_t(unsigned int, output_size, server->maxBuf);
  	output_size = min_t(unsigned int, output_size, 2 << 15);
  	req->OutputBufferLength = cpu_to_le32(output_size);
  
  	iov[0].iov_base = (char *)req;
7c00c3a62   Ronnie Sahlberg   cifs: remove rfc1...
3692
3693
  	/* 1 for Buffer */
  	iov[0].iov_len = total_len - 1;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3694
3695
3696
  
  	iov[1].iov_base = (char *)(req->Buffer);
  	iov[1].iov_len = len;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
3697
3698
3699
3700
3701
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 2;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3702
3703
  	cifs_small_buf_release(req);
  	rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base;
e5d048871   Pavel Shilovsky   CIFS: Fix possibl...
3704

d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3705
  	if (rc) {
31473fc4f   Pavel Shilovsky   CIFS: Separate SM...
3706
  		if (rc == -ENODATA &&
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
3707
  		    rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
52755808d   Pavel Shilovsky   CIFS: Fix SMB2 re...
3708
3709
  			srch_inf->endOfSearch = true;
  			rc = 0;
c6961288a   Pavel Shilovsky   CIFS: Do not coun...
3710
3711
  		} else
  			cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3712
3713
  		goto qdir_exit;
  	}
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3714

730928c8f   Ronnie Sahlberg   cifs: update smb2...
3715
3716
3717
  	rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
  			       le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
  			       info_buf_size);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
  	if (rc)
  		goto qdir_exit;
  
  	srch_inf->unicode = true;
  
  	if (srch_inf->ntwrk_buf_start) {
  		if (srch_inf->smallBuf)
  			cifs_small_buf_release(srch_inf->ntwrk_buf_start);
  		else
  			cifs_buf_release(srch_inf->ntwrk_buf_start);
  	}
  	srch_inf->ntwrk_buf_start = (char *)rsp;
977b61704   Ronnie Sahlberg   cifs: remove rfc1...
3730
3731
3732
  	srch_inf->srch_entries_start = srch_inf->last_entry =
  		(char *)rsp + le16_to_cpu(rsp->OutputBufferOffset);
  	end_of_smb = rsp_iov.iov_len + (char *)rsp;
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3733
3734
3735
3736
  	srch_inf->entries_in_buffer =
  			num_entries(srch_inf->srch_entries_start, end_of_smb,
  				    &srch_inf->last_entry, info_buf_size);
  	srch_inf->index_of_last_entry += srch_inf->entries_in_buffer;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3737
3738
3739
3740
  	cifs_dbg(FYI, "num entries %d last_index %lld srch start %p srch end %p
  ",
  		 srch_inf->entries_in_buffer, srch_inf->index_of_last_entry,
  		 srch_inf->srch_entries_start, srch_inf->last_entry);
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3741
3742
3743
3744
3745
  	if (resp_buftype == CIFS_LARGE_BUFFER)
  		srch_inf->smallBuf = false;
  	else if (resp_buftype == CIFS_SMALL_BUFFER)
  		srch_inf->smallBuf = true;
  	else
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3746
3747
  		cifs_dbg(VFS, "illegal search buffer type
  ");
d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3748

d324f08d6   Pavel Shilovsky   CIFS: Add readdir...
3749
3750
3751
3752
3753
3754
  	return rc;
  
  qdir_exit:
  	free_rsp_buf(resp_buftype, rsp);
  	return rc;
  }
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3755
3756
  static int
  send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
dac953401   Shirish Pargaonkar   cifs: prototype d...
3757
3758
3759
  	       u64 persistent_fid, u64 volatile_fid, u32 pid, u8 info_class,
  	       u8 info_type, u32 additional_info, unsigned int num,
  		void **data, unsigned int *size)
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3760
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
3761
  	struct smb_rqst rqst;
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3762
3763
3764
  	struct smb2_set_info_req *req;
  	struct smb2_set_info_rsp *rsp = NULL;
  	struct kvec *iov;
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3765
  	struct kvec rsp_iov;
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3766
3767
3768
  	int rc = 0;
  	int resp_buftype;
  	unsigned int i;
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3769
  	struct cifs_ses *ses = tcon->ses;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3770
  	int flags = 0;
2fc803efe   Ronnie Sahlberg   cifs: remove rfc1...
3771
  	unsigned int total_len;
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3772

68a6afa7f   Christos Gkekas   cifs: Clean up un...
3773
  	if (!ses || !(ses->server))
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3774
3775
3776
3777
  		return -EIO;
  
  	if (!num)
  		return -EINVAL;
6da2ec560   Kees Cook   treewide: kmalloc...
3778
  	iov = kmalloc_array(num, sizeof(struct kvec), GFP_KERNEL);
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3779
3780
  	if (!iov)
  		return -ENOMEM;
2fc803efe   Ronnie Sahlberg   cifs: remove rfc1...
3781
  	rc = smb2_plain_req_init(SMB2_SET_INFO, tcon, (void **) &req, &total_len);
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3782
3783
3784
3785
  	if (rc) {
  		kfree(iov);
  		return rc;
  	}
5a77e75fe   Steve French   smb3: rename encr...
3786
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3787
  		flags |= CIFS_TRANSFORM_REQ;
2fc803efe   Ronnie Sahlberg   cifs: remove rfc1...
3788
  	req->sync_hdr.ProcessId = cpu_to_le32(pid);
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
3789

dac953401   Shirish Pargaonkar   cifs: prototype d...
3790
  	req->InfoType = info_type;
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3791
3792
3793
  	req->FileInfoClass = info_class;
  	req->PersistentFileId = persistent_fid;
  	req->VolatileFileId = volatile_fid;
dac953401   Shirish Pargaonkar   cifs: prototype d...
3794
  	req->AdditionalInformation = cpu_to_le32(additional_info);
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3795

35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3796
  	req->BufferOffset =
2fc803efe   Ronnie Sahlberg   cifs: remove rfc1...
3797
  			cpu_to_le16(sizeof(struct smb2_set_info_req) - 1);
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3798
  	req->BufferLength = cpu_to_le32(*size);
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3799
  	memcpy(req->Buffer, *data, *size);
2fc803efe   Ronnie Sahlberg   cifs: remove rfc1...
3800
  	total_len += *size;
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3801
3802
  
  	iov[0].iov_base = (char *)req;
2fc803efe   Ronnie Sahlberg   cifs: remove rfc1...
3803
3804
  	/* 1 for Buffer */
  	iov[0].iov_len = total_len - 1;
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3805
3806
  
  	for (i = 1; i < num; i++) {
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3807
3808
3809
3810
  		le32_add_cpu(&req->BufferLength, size[i]);
  		iov[i].iov_base = (char *)data[i];
  		iov[i].iov_len = size[i];
  	}
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
3811
3812
3813
3814
3815
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = num;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
2fc803efe   Ronnie Sahlberg   cifs: remove rfc1...
3816
  			    &rsp_iov);
f46ecbd97   Stefano Brivio   cifs: Fix slab-ou...
3817
  	cifs_buf_release(req);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3818
  	rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base;
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3819

eccb4422c   Steve French   smb3: Add ftrace ...
3820
  	if (rc != 0) {
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3821
  		cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE);
eccb4422c   Steve French   smb3: Add ftrace ...
3822
3823
3824
  		trace_smb3_set_info_err(xid, persistent_fid, tcon->tid,
  				ses->Suid, info_class, (__u32)info_type, rc);
  	}
7d3fb24bc   Steve French   Removed duplicate...
3825

35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
  	free_rsp_buf(resp_buftype, rsp);
  	kfree(iov);
  	return rc;
  }
  
  int
  SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
  	    u64 persistent_fid, u64 volatile_fid, __le16 *target_file)
  {
  	struct smb2_file_rename_info info;
  	void **data;
  	unsigned int size[2];
  	int rc;
  	int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX));
6da2ec560   Kees Cook   treewide: kmalloc...
3840
  	data = kmalloc_array(2, sizeof(void *), GFP_KERNEL);
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
  	if (!data)
  		return -ENOMEM;
  
  	info.ReplaceIfExists = 1; /* 1 = replace existing target with new */
  			      /* 0 = fail if target already exists */
  	info.RootDirectory = 0;  /* MBZ for network ops (why does spec say?) */
  	info.FileNameLength = cpu_to_le32(len);
  
  	data[0] = &info;
  	size[0] = sizeof(struct smb2_file_rename_info);
  
  	data[1] = target_file;
  	size[1] = len + 2 /* null */;
  
  	rc = send_set_info(xid, tcon, persistent_fid, volatile_fid,
dac953401   Shirish Pargaonkar   cifs: prototype d...
3856
3857
  		current->tgid, FILE_RENAME_INFORMATION, SMB2_O_INFO_FILE,
  		0, 2, data, size);
35143eb5c   Pavel Shilovsky   CIFS: Add SMB2 su...
3858
3859
3860
  	kfree(data);
  	return rc;
  }
568798cc6   Pavel Shilovsky   CIFS: Add SMB2 su...
3861
3862
  
  int
897fba117   Steve French   remove directory ...
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
  SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
  		  u64 persistent_fid, u64 volatile_fid)
  {
  	__u8 delete_pending = 1;
  	void *data;
  	unsigned int size;
  
  	data = &delete_pending;
  	size = 1; /* sizeof __u8 */
  
  	return send_set_info(xid, tcon, persistent_fid, volatile_fid,
dac953401   Shirish Pargaonkar   cifs: prototype d...
3874
3875
  		current->tgid, FILE_DISPOSITION_INFORMATION, SMB2_O_INFO_FILE,
  		0, 1, &data, &size);
897fba117   Steve French   remove directory ...
3876
3877
3878
  }
  
  int
568798cc6   Pavel Shilovsky   CIFS: Add SMB2 su...
3879
3880
3881
3882
3883
3884
3885
3886
  SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
  		  u64 persistent_fid, u64 volatile_fid, __le16 *target_file)
  {
  	struct smb2_file_link_info info;
  	void **data;
  	unsigned int size[2];
  	int rc;
  	int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX));
6da2ec560   Kees Cook   treewide: kmalloc...
3887
  	data = kmalloc_array(2, sizeof(void *), GFP_KERNEL);
568798cc6   Pavel Shilovsky   CIFS: Add SMB2 su...
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
  	if (!data)
  		return -ENOMEM;
  
  	info.ReplaceIfExists = 0; /* 1 = replace existing link with new */
  			      /* 0 = fail if link already exists */
  	info.RootDirectory = 0;  /* MBZ for network ops (why does spec say?) */
  	info.FileNameLength = cpu_to_le32(len);
  
  	data[0] = &info;
  	size[0] = sizeof(struct smb2_file_link_info);
  
  	data[1] = target_file;
  	size[1] = len + 2 /* null */;
  
  	rc = send_set_info(xid, tcon, persistent_fid, volatile_fid,
dac953401   Shirish Pargaonkar   cifs: prototype d...
3903
3904
  			current->tgid, FILE_LINK_INFORMATION, SMB2_O_INFO_FILE,
  			0, 2, data, size);
568798cc6   Pavel Shilovsky   CIFS: Add SMB2 su...
3905
3906
3907
  	kfree(data);
  	return rc;
  }
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
3908
3909
3910
  
  int
  SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
f29ebb47d   Steve French   Add worker functi...
3911
  	     u64 volatile_fid, u32 pid, __le64 *eof, bool is_falloc)
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
3912
3913
3914
3915
3916
3917
3918
3919
3920
  {
  	struct smb2_file_eof_info info;
  	void *data;
  	unsigned int size;
  
  	info.EndOfFile = *eof;
  
  	data = &info;
  	size = sizeof(struct smb2_file_eof_info);
f29ebb47d   Steve French   Add worker functi...
3921
3922
  	if (is_falloc)
  		return send_set_info(xid, tcon, persistent_fid, volatile_fid,
dac953401   Shirish Pargaonkar   cifs: prototype d...
3923
3924
  			pid, FILE_ALLOCATION_INFORMATION, SMB2_O_INFO_FILE,
  			0, 1, &data, &size);
f29ebb47d   Steve French   Add worker functi...
3925
3926
  	else
  		return send_set_info(xid, tcon, persistent_fid, volatile_fid,
dac953401   Shirish Pargaonkar   cifs: prototype d...
3927
3928
  			pid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE,
  			0, 1, &data, &size);
c839ff244   Pavel Shilovsky   CIFS: Add SMB2 su...
3929
  }
1feeaac75   Pavel Shilovsky   CIFS: Add set_fil...
3930
3931
3932
3933
3934
3935
3936
3937
  
  int
  SMB2_set_info(const unsigned int xid, struct cifs_tcon *tcon,
  	      u64 persistent_fid, u64 volatile_fid, FILE_BASIC_INFO *buf)
  {
  	unsigned int size;
  	size = sizeof(FILE_BASIC_INFO);
  	return send_set_info(xid, tcon, persistent_fid, volatile_fid,
dac953401   Shirish Pargaonkar   cifs: prototype d...
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
  		current->tgid, FILE_BASIC_INFORMATION, SMB2_O_INFO_FILE,
  		0, 1, (void **)&buf, &size);
  }
  
  int
  SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
  		u64 persistent_fid, u64 volatile_fid,
  		struct cifs_ntsd *pnntsd, int pacllen, int aclflag)
  {
  	return send_set_info(xid, tcon, persistent_fid, volatile_fid,
  			current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag,
  			1, (void **)&pnntsd, &pacllen);
1feeaac75   Pavel Shilovsky   CIFS: Add set_fil...
3950
  }
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
3951
3952
  
  int
5517554e4   Ronnie Sahlberg   cifs: Add support...
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
  SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
  	    u64 persistent_fid, u64 volatile_fid,
  	    struct smb2_file_full_ea_info *buf, int len)
  {
  	return send_set_info(xid, tcon, persistent_fid, volatile_fid,
  		current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE,
  		0, 1, (void **)&buf, &len);
  }
  
  int
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
3963
3964
3965
3966
  SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
  		  const u64 persistent_fid, const u64 volatile_fid,
  		  __u8 oplock_level)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
3967
  	struct smb_rqst rqst;
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
3968
  	int rc;
0d5a288d2   Ronnie Sahlberg   cifs: remove stru...
3969
  	struct smb2_oplock_break *req = NULL;
21ad9487c   Ronnie Sahlberg   cifs: remove rfc1...
3970
  	struct cifs_ses *ses = tcon->ses;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3971
  	int flags = CIFS_OBREAK_OP;
21ad9487c   Ronnie Sahlberg   cifs: remove rfc1...
3972
3973
3974
3975
  	unsigned int total_len;
  	struct kvec iov[1];
  	struct kvec rsp_iov;
  	int resp_buf_type;
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
3976

f96637be0   Joe Perches   [CIFS] cifs: Rena...
3977
3978
  	cifs_dbg(FYI, "SMB2_oplock_break
  ");
21ad9487c   Ronnie Sahlberg   cifs: remove rfc1...
3979
3980
  	rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req,
  			     &total_len);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
3981
3982
  	if (rc)
  		return rc;
5a77e75fe   Steve French   smb3: rename encr...
3983
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
3984
  		flags |= CIFS_TRANSFORM_REQ;
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
3985
3986
3987
  	req->VolatileFid = volatile_fid;
  	req->PersistentFid = persistent_fid;
  	req->OplockLevel = oplock_level;
21ad9487c   Ronnie Sahlberg   cifs: remove rfc1...
3988
  	req->sync_hdr.CreditRequest = cpu_to_le16(1);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
3989

21ad9487c   Ronnie Sahlberg   cifs: remove rfc1...
3990
3991
3992
3993
  	flags |= CIFS_NO_RESP;
  
  	iov[0].iov_base = (char *)req;
  	iov[0].iov_len = total_len;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
3994
3995
3996
3997
3998
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 1;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
3999
  	cifs_small_buf_release(req);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
4000
4001
4002
  
  	if (rc) {
  		cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4003
4004
  		cifs_dbg(FYI, "Send error in Oplock Break = %d
  ", rc);
983c88a49   Pavel Shilovsky   CIFS: Add oplock ...
4005
4006
4007
4008
  	}
  
  	return rc;
  }
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4009

730928c8f   Ronnie Sahlberg   cifs: update smb2...
4010
4011
4012
  void
  smb2_copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf,
  			     struct kstatfs *kst)
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4013
4014
4015
4016
  {
  	kst->f_bsize = le32_to_cpu(pfs_inf->BytesPerSector) *
  			  le32_to_cpu(pfs_inf->SectorsPerAllocationUnit);
  	kst->f_blocks = le64_to_cpu(pfs_inf->TotalAllocationUnits);
42bec214d   Sachin Prabhu   cifs: Fix df outp...
4017
4018
  	kst->f_bfree  = kst->f_bavail =
  			le64_to_cpu(pfs_inf->CallerAvailableAllocationUnits);
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4019
4020
  	return;
  }
2d3042178   Steve French   smb3: add support...
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
  static void
  copy_posix_fs_info_to_kstatfs(FILE_SYSTEM_POSIX_INFO *response_data,
  			struct kstatfs *kst)
  {
  	kst->f_bsize = le32_to_cpu(response_data->BlockSize);
  	kst->f_blocks = le64_to_cpu(response_data->TotalBlocks);
  	kst->f_bfree =  le64_to_cpu(response_data->BlocksAvail);
  	if (response_data->UserBlocksAvail == cpu_to_le64(-1))
  		kst->f_bavail = kst->f_bfree;
  	else
  		kst->f_bavail = le64_to_cpu(response_data->UserBlocksAvail);
  	if (response_data->TotalFileNodes != cpu_to_le64(-1))
  		kst->f_files = le64_to_cpu(response_data->TotalFileNodes);
  	if (response_data->FreeFileNodes != cpu_to_le64(-1))
  		kst->f_ffree = le64_to_cpu(response_data->FreeFileNodes);
  
  	return;
  }
2d3042178   Steve French   smb3: add support...
4039

6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4040
4041
4042
4043
  static int
  build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
  		   int outbuf_len, u64 persistent_fid, u64 volatile_fid)
  {
c0953f2ed   Gustavo A. R. Silva   cifs: smb2pdu: Fi...
4044
  	struct TCP_Server_Info *server;
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4045
4046
  	int rc;
  	struct smb2_query_info_req *req;
b2fb7fecc   Ronnie Sahlberg   cifs: remove rfc1...
4047
  	unsigned int total_len;
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4048

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4049
4050
  	cifs_dbg(FYI, "Query FSInfo level %d
  ", level);
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4051
4052
4053
  
  	if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
  		return -EIO;
c0953f2ed   Gustavo A. R. Silva   cifs: smb2pdu: Fi...
4054
  	server = tcon->ses->server;
b2fb7fecc   Ronnie Sahlberg   cifs: remove rfc1...
4055
4056
  	rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, (void **) &req,
  			     &total_len);
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4057
4058
4059
4060
4061
4062
4063
  	if (rc)
  		return rc;
  
  	req->InfoType = SMB2_O_INFO_FILESYSTEM;
  	req->FileInfoClass = level;
  	req->PersistentFileId = persistent_fid;
  	req->VolatileFileId = volatile_fid;
b2fb7fecc   Ronnie Sahlberg   cifs: remove rfc1...
4064
  	/* 1 for pad */
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4065
  	req->InputBufferOffset =
b2fb7fecc   Ronnie Sahlberg   cifs: remove rfc1...
4066
  			cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4067
  	req->OutputBufferLength = cpu_to_le32(
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
4068
  		outbuf_len + sizeof(struct smb2_query_info_rsp) - 1);
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4069
4070
  
  	iov->iov_base = (char *)req;
b2fb7fecc   Ronnie Sahlberg   cifs: remove rfc1...
4071
  	iov->iov_len = total_len;
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4072
4073
  	return 0;
  }
2d3042178   Steve French   smb3: add support...
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
  int
  SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon,
  	      u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata)
  {
  	struct smb_rqst rqst;
  	struct smb2_query_info_rsp *rsp = NULL;
  	struct kvec iov;
  	struct kvec rsp_iov;
  	int rc = 0;
  	int resp_buftype;
  	struct cifs_ses *ses = tcon->ses;
  	FILE_SYSTEM_POSIX_INFO *info = NULL;
  	int flags = 0;
  
  	rc = build_qfs_info_req(&iov, tcon, FS_POSIX_INFORMATION,
  				sizeof(FILE_SYSTEM_POSIX_INFO),
  				persistent_fid, volatile_fid);
  	if (rc)
  		return rc;
  
  	if (smb3_encryption_required(tcon))
  		flags |= CIFS_TRANSFORM_REQ;
  
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = &iov;
  	rqst.rq_nvec = 1;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
  	cifs_small_buf_release(iov.iov_base);
  	if (rc) {
  		cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
  		goto posix_qfsinf_exit;
  	}
  	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
  
  	info = (FILE_SYSTEM_POSIX_INFO *)(
  		le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
730928c8f   Ronnie Sahlberg   cifs: update smb2...
4111
4112
4113
  	rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
  			       le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
  			       sizeof(FILE_SYSTEM_POSIX_INFO));
2d3042178   Steve French   smb3: add support...
4114
4115
4116
4117
4118
4119
4120
  	if (!rc)
  		copy_posix_fs_info_to_kstatfs(info, fsdata);
  
  posix_qfsinf_exit:
  	free_rsp_buf(resp_buftype, rsp_iov.iov_base);
  	return rc;
  }
2d3042178   Steve French   smb3: add support...
4121

6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4122
4123
4124
4125
  int
  SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
  	      u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
4126
  	struct smb_rqst rqst;
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4127
4128
  	struct smb2_query_info_rsp *rsp = NULL;
  	struct kvec iov;
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4129
  	struct kvec rsp_iov;
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4130
4131
4132
4133
  	int rc = 0;
  	int resp_buftype;
  	struct cifs_ses *ses = tcon->ses;
  	struct smb2_fs_full_size_info *info = NULL;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
4134
  	int flags = 0;
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4135
4136
4137
4138
4139
4140
  
  	rc = build_qfs_info_req(&iov, tcon, FS_FULL_SIZE_INFORMATION,
  				sizeof(struct smb2_fs_full_size_info),
  				persistent_fid, volatile_fid);
  	if (rc)
  		return rc;
5a77e75fe   Steve French   smb3: rename encr...
4141
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
4142
  		flags |= CIFS_TRANSFORM_REQ;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
4143
4144
4145
4146
4147
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = &iov;
  	rqst.rq_nvec = 1;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4148
  	cifs_small_buf_release(iov.iov_base);
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4149
4150
  	if (rc) {
  		cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
34f626406   Steve French   Query file system...
4151
  		goto qfsinf_exit;
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4152
  	}
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4153
  	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4154

1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
4155
  	info = (struct smb2_fs_full_size_info *)(
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
4156
  		le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
730928c8f   Ronnie Sahlberg   cifs: update smb2...
4157
4158
4159
  	rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
  			       le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
  			       sizeof(struct smb2_fs_full_size_info));
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4160
  	if (!rc)
730928c8f   Ronnie Sahlberg   cifs: update smb2...
4161
  		smb2_copy_fs_info_to_kstatfs(info, fsdata);
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4162

34f626406   Steve French   Query file system...
4163
  qfsinf_exit:
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4164
  	free_rsp_buf(resp_buftype, rsp_iov.iov_base);
34f626406   Steve French   Query file system...
4165
4166
4167
4168
4169
  	return rc;
  }
  
  int
  SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
2167114c6   Steven French   Query device char...
4170
  	      u64 persistent_fid, u64 volatile_fid, int level)
34f626406   Steve French   Query file system...
4171
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
4172
  	struct smb_rqst rqst;
34f626406   Steve French   Query file system...
4173
4174
  	struct smb2_query_info_rsp *rsp = NULL;
  	struct kvec iov;
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4175
  	struct kvec rsp_iov;
34f626406   Steve French   Query file system...
4176
  	int rc = 0;
2167114c6   Steven French   Query device char...
4177
  	int resp_buftype, max_len, min_len;
34f626406   Steve French   Query file system...
4178
4179
  	struct cifs_ses *ses = tcon->ses;
  	unsigned int rsp_len, offset;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
4180
  	int flags = 0;
34f626406   Steve French   Query file system...
4181

2167114c6   Steven French   Query device char...
4182
4183
4184
4185
4186
4187
  	if (level == FS_DEVICE_INFORMATION) {
  		max_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
  		min_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
  	} else if (level == FS_ATTRIBUTE_INFORMATION) {
  		max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO);
  		min_len = MIN_FS_ATTR_INFO_SIZE;
af6a12ea8   Steven French   Query File System...
4188
4189
4190
  	} else if (level == FS_SECTOR_SIZE_INFORMATION) {
  		max_len = sizeof(struct smb3_fs_ss_info);
  		min_len = sizeof(struct smb3_fs_ss_info);
21ba3845b   Steve French   smb3: fill in sta...
4191
4192
4193
  	} else if (level == FS_VOLUME_INFORMATION) {
  		max_len = sizeof(struct smb3_fs_vol_info) + MAX_VOL_LABEL_LEN;
  		min_len = sizeof(struct smb3_fs_vol_info);
2167114c6   Steven French   Query device char...
4194
  	} else {
af6a12ea8   Steven French   Query File System...
4195
4196
  		cifs_dbg(FYI, "Invalid qfsinfo level %d
  ", level);
2167114c6   Steven French   Query device char...
4197
4198
4199
4200
  		return -EINVAL;
  	}
  
  	rc = build_qfs_info_req(&iov, tcon, level, max_len,
34f626406   Steve French   Query file system...
4201
4202
4203
  				persistent_fid, volatile_fid);
  	if (rc)
  		return rc;
5a77e75fe   Steve French   smb3: rename encr...
4204
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
4205
  		flags |= CIFS_TRANSFORM_REQ;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
4206
4207
4208
4209
4210
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = &iov;
  	rqst.rq_nvec = 1;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4211
  	cifs_small_buf_release(iov.iov_base);
34f626406   Steve French   Query file system...
4212
4213
4214
4215
  	if (rc) {
  		cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
  		goto qfsattr_exit;
  	}
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4216
  	rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
34f626406   Steve French   Query file system...
4217
4218
4219
  
  	rsp_len = le32_to_cpu(rsp->OutputBufferLength);
  	offset = le16_to_cpu(rsp->OutputBufferOffset);
730928c8f   Ronnie Sahlberg   cifs: update smb2...
4220
  	rc = smb2_validate_iov(offset, rsp_len, &rsp_iov, min_len);
2167114c6   Steven French   Query device char...
4221
4222
4223
4224
  	if (rc)
  		goto qfsattr_exit;
  
  	if (level == FS_ATTRIBUTE_INFORMATION)
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
4225
  		memcpy(&tcon->fsAttrInfo, offset
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
4226
  			+ (char *)rsp, min_t(unsigned int,
2167114c6   Steven French   Query device char...
4227
4228
  			rsp_len, max_len));
  	else if (level == FS_DEVICE_INFORMATION)
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
4229
  		memcpy(&tcon->fsDevInfo, offset
49f466bdb   Ronnie Sahlberg   cifs: remove stru...
4230
  			+ (char *)rsp, sizeof(FILE_SYSTEM_DEVICE_INFO));
af6a12ea8   Steven French   Query File System...
4231
4232
  	else if (level == FS_SECTOR_SIZE_INFORMATION) {
  		struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
1fc6ad2f1   Ronnie Sahlberg   cifs: remove head...
4233
  			(offset + (char *)rsp);
af6a12ea8   Steven French   Query File System...
4234
4235
4236
  		tcon->ss_flags = le32_to_cpu(ss_info->Flags);
  		tcon->perf_sector_size =
  			le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
21ba3845b   Steve French   smb3: fill in sta...
4237
4238
4239
4240
4241
  	} else if (level == FS_VOLUME_INFORMATION) {
  		struct smb3_fs_vol_info *vol_info = (struct smb3_fs_vol_info *)
  			(offset + (char *)rsp);
  		tcon->vol_serial_number = vol_info->VolumeSerialNumber;
  		tcon->vol_create_time = vol_info->VolumeCreationTime;
af6a12ea8   Steven French   Query File System...
4242
  	}
34f626406   Steve French   Query file system...
4243
4244
  
  qfsattr_exit:
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4245
  	free_rsp_buf(resp_buftype, rsp_iov.iov_base);
6fc05c25c   Pavel Shilovsky   CIFS: Add statfs ...
4246
4247
  	return rc;
  }
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4248
4249
4250
4251
4252
4253
  
  int
  smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
  	   const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid,
  	   const __u32 num_lock, struct smb2_lock_element *buf)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
4254
  	struct smb_rqst rqst;
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4255
4256
4257
  	int rc = 0;
  	struct smb2_lock_req *req = NULL;
  	struct kvec iov[2];
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4258
  	struct kvec rsp_iov;
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4259
4260
  	int resp_buf_type;
  	unsigned int count;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
4261
  	int flags = CIFS_NO_RESP;
ced93679c   Ronnie Sahlberg   cifs: remove rfc1...
4262
  	unsigned int total_len;
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4263

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4264
4265
  	cifs_dbg(FYI, "smb2_lockv num lock %d
  ", num_lock);
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4266

ced93679c   Ronnie Sahlberg   cifs: remove rfc1...
4267
  	rc = smb2_plain_req_init(SMB2_LOCK, tcon, (void **) &req, &total_len);
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4268
4269
  	if (rc)
  		return rc;
5a77e75fe   Steve French   smb3: rename encr...
4270
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
4271
  		flags |= CIFS_TRANSFORM_REQ;
ced93679c   Ronnie Sahlberg   cifs: remove rfc1...
4272
  	req->sync_hdr.ProcessId = cpu_to_le32(pid);
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4273
4274
4275
4276
4277
4278
  	req->LockCount = cpu_to_le16(num_lock);
  
  	req->PersistentFileId = persist_fid;
  	req->VolatileFileId = volatile_fid;
  
  	count = num_lock * sizeof(struct smb2_lock_element);
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4279
4280
  
  	iov[0].iov_base = (char *)req;
ced93679c   Ronnie Sahlberg   cifs: remove rfc1...
4281
  	iov[0].iov_len = total_len - sizeof(struct smb2_lock_element);
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4282
4283
4284
4285
  	iov[1].iov_base = (char *)buf;
  	iov[1].iov_len = count;
  
  	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
4286
4287
4288
4289
4290
4291
  
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 2;
  
  	rc = cifs_send_recv(xid, tcon->ses, &rqst, &resp_buf_type, flags,
ced93679c   Ronnie Sahlberg   cifs: remove rfc1...
4292
  			    &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4293
  	cifs_small_buf_release(req);
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4294
  	if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4295
4296
  		cifs_dbg(FYI, "Send error in smb2_lockv = %d
  ", rc);
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4297
  		cifs_stats_fail_inc(tcon, SMB2_LOCK_HE);
eccb4422c   Steve French   smb3: Add ftrace ...
4298
4299
  		trace_smb3_lock_err(xid, persist_fid, tcon->tid,
  				    tcon->ses->Suid, rc);
f7ba7fe68   Pavel Shilovsky   CIFS: Add brlock ...
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
  	}
  
  	return rc;
  }
  
  int
  SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon,
  	  const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid,
  	  const __u64 length, const __u64 offset, const __u32 lock_flags,
  	  const bool wait)
  {
  	struct smb2_lock_element lock;
  
  	lock.Offset = cpu_to_le64(offset);
  	lock.Length = cpu_to_le64(length);
  	lock.Flags = cpu_to_le32(lock_flags);
  	if (!wait && lock_flags != SMB2_LOCKFLAG_UNLOCK)
  		lock.Flags |= cpu_to_le32(SMB2_LOCKFLAG_FAIL_IMMEDIATELY);
  
  	return smb2_lockv(xid, tcon, persist_fid, volatile_fid, pid, 1, &lock);
  }
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
4321
4322
4323
4324
4325
  
  int
  SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
  		 __u8 *lease_key, const __le32 lease_state)
  {
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
4326
  	struct smb_rqst rqst;
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
4327
4328
  	int rc;
  	struct smb2_lease_ack *req = NULL;
8eb7998e7   Ronnie Sahlberg   cifs: remove rfc1...
4329
  	struct cifs_ses *ses = tcon->ses;
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
4330
  	int flags = CIFS_OBREAK_OP;
8eb7998e7   Ronnie Sahlberg   cifs: remove rfc1...
4331
4332
4333
4334
  	unsigned int total_len;
  	struct kvec iov[1];
  	struct kvec rsp_iov;
  	int resp_buf_type;
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
4335

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4336
4337
  	cifs_dbg(FYI, "SMB2_lease_break
  ");
8eb7998e7   Ronnie Sahlberg   cifs: remove rfc1...
4338
4339
  	rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req,
  			     &total_len);
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
4340
4341
  	if (rc)
  		return rc;
5a77e75fe   Steve French   smb3: rename encr...
4342
  	if (smb3_encryption_required(tcon))
7fb8986e7   Pavel Shilovsky   CIFS: Add capabil...
4343
  		flags |= CIFS_TRANSFORM_REQ;
8eb7998e7   Ronnie Sahlberg   cifs: remove rfc1...
4344
  	req->sync_hdr.CreditRequest = cpu_to_le16(1);
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
4345
  	req->StructureSize = cpu_to_le16(36);
8eb7998e7   Ronnie Sahlberg   cifs: remove rfc1...
4346
  	total_len += 12;
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
4347
4348
4349
  
  	memcpy(req->LeaseKey, lease_key, 16);
  	req->LeaseState = lease_state;
8eb7998e7   Ronnie Sahlberg   cifs: remove rfc1...
4350
4351
4352
4353
  	flags |= CIFS_NO_RESP;
  
  	iov[0].iov_base = (char *)req;
  	iov[0].iov_len = total_len;
40eff45b5   Ronnie Sahlberg   cifs: remove smb2...
4354
4355
4356
4357
4358
  	memset(&rqst, 0, sizeof(struct smb_rqst));
  	rqst.rq_iov = iov;
  	rqst.rq_nvec = 1;
  
  	rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
da502f7df   Pavel Shilovsky   CIFS: Make SendRe...
4359
  	cifs_small_buf_release(req);
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
4360
4361
4362
  
  	if (rc) {
  		cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4363
4364
  		cifs_dbg(FYI, "Send error in Lease Break = %d
  ", rc);
0822f5142   Pavel Shilovsky   CIFS: Add SMB2.1 ...
4365
4366
4367
4368
  	}
  
  	return rc;
  }