xref: /linux/fs/smb/client/cifssmb.c (revision 89a312991dc6e638a36adc43ccb91dbc25504c04)
1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2010
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   Contains the routines for constructing the SMB PDUs themselves
8  *
9  */
10 
11  /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
12  /* These are mostly routines that operate on a pathname, or on a tree id     */
13  /* (mounted volume), but there are eight handle based routines which must be */
14  /* treated slightly differently for reconnection purposes since we never     */
15  /* want to reuse a stale file handle and only the caller knows the file info */
16 
17 #include <linux/fs.h>
18 #include <linux/filelock.h>
19 #include <linux/kernel.h>
20 #include <linux/vfs.h>
21 #include <linux/slab.h>
22 #include <linux/posix_acl_xattr.h>
23 #include <linux/pagemap.h>
24 #include <linux/swap.h>
25 #include <linux/task_io_accounting_ops.h>
26 #include <linux/uaccess.h>
27 #include <linux/netfs.h>
28 #include <trace/events/netfs.h>
29 #include "cifsglob.h"
30 #include "cifsproto.h"
31 #include "smb1proto.h"
32 #include "../common/smbfsctl.h"
33 #include "cifsfs.h"
34 #include "cifsacl.h"
35 #include "cifs_unicode.h"
36 #include "cifs_debug.h"
37 #include "fscache.h"
38 #include "smbdirect.h"
39 #ifdef CONFIG_CIFS_DFS_UPCALL
40 #include "dfs_cache.h"
41 #endif
42 
43 #ifdef CONFIG_CIFS_POSIX
44 static struct {
45 	int index;
46 	char *name;
47 } protocols[] = {
48 	{CIFS_PROT, "\2NT LM 0.12"},
49 	{POSIX_PROT, "\2POSIX 2"},
50 	{BAD_PROT, "\2"}
51 };
52 #else
53 static struct {
54 	int index;
55 	char *name;
56 } protocols[] = {
57 	{CIFS_PROT, "\2NT LM 0.12"},
58 	{BAD_PROT, "\2"}
59 };
60 #endif
61 
62 /* define the number of elements in the cifs dialect array */
63 #ifdef CONFIG_CIFS_POSIX
64 #define CIFS_NUM_PROT 2
65 #else /* not posix */
66 #define CIFS_NUM_PROT 1
67 #endif /* CIFS_POSIX */
68 
69 
70 /* reconnect the socket, tcon, and smb session if needed */
71 static int
cifs_reconnect_tcon(struct cifs_tcon * tcon,int smb_command)72 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
73 {
74 	struct TCP_Server_Info *server;
75 	struct cifs_ses *ses;
76 	int rc;
77 
78 	/*
79 	 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
80 	 * tcp and smb session status done differently for those three - in the
81 	 * calling routine
82 	 */
83 	if (!tcon)
84 		return 0;
85 
86 	ses = tcon->ses;
87 	server = ses->server;
88 
89 	/*
90 	 * only tree disconnect, open, and write, (and ulogoff which does not
91 	 * have tcon) are allowed as we start umount
92 	 */
93 	spin_lock(&tcon->tc_lock);
94 	if (tcon->status == TID_EXITING) {
95 		if (smb_command != SMB_COM_TREE_DISCONNECT) {
96 			spin_unlock(&tcon->tc_lock);
97 			cifs_dbg(FYI, "can not send cmd %d while umounting\n",
98 				 smb_command);
99 			return -ENODEV;
100 		}
101 	}
102 	spin_unlock(&tcon->tc_lock);
103 
104 again:
105 	rc = cifs_wait_for_server_reconnect(server, tcon->retry);
106 	if (rc)
107 		return rc;
108 
109 	spin_lock(&ses->chan_lock);
110 	if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
111 		spin_unlock(&ses->chan_lock);
112 		return 0;
113 	}
114 	spin_unlock(&ses->chan_lock);
115 
116 	mutex_lock(&ses->session_mutex);
117 	/*
118 	 * Handle the case where a concurrent thread failed to negotiate or
119 	 * killed a channel.
120 	 */
121 	spin_lock(&server->srv_lock);
122 	switch (server->tcpStatus) {
123 	case CifsExiting:
124 		spin_unlock(&server->srv_lock);
125 		mutex_unlock(&ses->session_mutex);
126 		return -EHOSTDOWN;
127 	case CifsNeedReconnect:
128 		spin_unlock(&server->srv_lock);
129 		mutex_unlock(&ses->session_mutex);
130 		if (!tcon->retry)
131 			return -EHOSTDOWN;
132 		goto again;
133 	default:
134 		break;
135 	}
136 	spin_unlock(&server->srv_lock);
137 
138 	/*
139 	 * need to prevent multiple threads trying to simultaneously
140 	 * reconnect the same SMB session
141 	 */
142 	spin_lock(&ses->ses_lock);
143 	spin_lock(&ses->chan_lock);
144 	if (!cifs_chan_needs_reconnect(ses, server) &&
145 	    ses->ses_status == SES_GOOD) {
146 		spin_unlock(&ses->chan_lock);
147 		spin_unlock(&ses->ses_lock);
148 
149 		/* this means that we only need to tree connect */
150 		if (tcon->need_reconnect)
151 			goto skip_sess_setup;
152 
153 		mutex_unlock(&ses->session_mutex);
154 		goto out;
155 	}
156 	spin_unlock(&ses->chan_lock);
157 	spin_unlock(&ses->ses_lock);
158 
159 	rc = cifs_negotiate_protocol(0, ses, server);
160 	if (rc) {
161 		mutex_unlock(&ses->session_mutex);
162 		if (!tcon->retry)
163 			return -EHOSTDOWN;
164 		goto again;
165 	}
166 	rc = cifs_setup_session(0, ses, server, ses->local_nls);
167 	if ((rc == -EACCES) || (rc == -EHOSTDOWN) || (rc == -EKEYREVOKED)) {
168 		/*
169 		 * Try alternate password for next reconnect if an alternate
170 		 * password is available.
171 		 */
172 		if (ses->password2)
173 			swap(ses->password2, ses->password);
174 	}
175 
176 	/* do we need to reconnect tcon? */
177 	if (rc || !tcon->need_reconnect) {
178 		mutex_unlock(&ses->session_mutex);
179 		goto out;
180 	}
181 
182 skip_sess_setup:
183 	cifs_mark_open_files_invalid(tcon);
184 	rc = cifs_tree_connect(0, tcon);
185 	mutex_unlock(&ses->session_mutex);
186 	cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
187 
188 	if (rc) {
189 		pr_warn_once("reconnect tcon failed rc = %d\n", rc);
190 		goto out;
191 	}
192 
193 	atomic_inc(&tconInfoReconnectCount);
194 
195 	/* tell server Unix caps we support */
196 	if (cap_unix(ses))
197 		reset_cifs_unix_caps(0, tcon, NULL, NULL);
198 
199 	/*
200 	 * Removed call to reopen open files here. It is safer (and faster) to
201 	 * reopen files one at a time as needed in read and write.
202 	 *
203 	 * FIXME: what about file locks? don't we need to reclaim them ASAP?
204 	 */
205 
206 out:
207 	/*
208 	 * Check if handle based operation so we know whether we can continue
209 	 * or not without returning to caller to reset file handle
210 	 */
211 	switch (smb_command) {
212 	case SMB_COM_READ_ANDX:
213 	case SMB_COM_WRITE_ANDX:
214 	case SMB_COM_CLOSE:
215 	case SMB_COM_FIND_CLOSE2:
216 	case SMB_COM_LOCKING_ANDX:
217 		rc = -EAGAIN;
218 	}
219 
220 	return rc;
221 }
222 
223 /* Allocate and return pointer to an SMB request buffer, and set basic
224    SMB information in the SMB header.  If the return code is zero, this
225    function must have filled in request_buf pointer */
226 static int
small_smb_init(int smb_command,int wct,struct cifs_tcon * tcon,void ** request_buf)227 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
228 		void **request_buf)
229 {
230 	unsigned int in_len;
231 	int rc;
232 
233 	rc = cifs_reconnect_tcon(tcon, smb_command);
234 	if (rc)
235 		return rc;
236 
237 	*request_buf = cifs_small_buf_get();
238 	if (*request_buf == NULL) {
239 		/* BB should we add a retry in here if not a writepage? */
240 		return -ENOMEM;
241 	}
242 
243 	in_len = header_assemble((struct smb_hdr *) *request_buf, smb_command,
244 				 tcon, wct);
245 
246 	if (tcon != NULL)
247 		cifs_stats_inc(&tcon->num_smbs_sent);
248 
249 	return in_len;
250 }
251 
252 int
small_smb_init_no_tc(const int smb_command,const int wct,struct cifs_ses * ses,void ** request_buf)253 small_smb_init_no_tc(const int smb_command, const int wct,
254 		     struct cifs_ses *ses, void **request_buf)
255 {
256 	int rc;
257 	struct smb_hdr *buffer;
258 
259 	rc = small_smb_init(smb_command, wct, NULL, request_buf);
260 	if (rc < 0)
261 		return rc;
262 
263 	buffer = (struct smb_hdr *)*request_buf;
264 	buffer->Mid = get_next_mid(ses->server);
265 	if (ses->capabilities & CAP_UNICODE)
266 		buffer->Flags2 |= SMBFLG2_UNICODE;
267 	if (ses->capabilities & CAP_STATUS32)
268 		buffer->Flags2 |= SMBFLG2_ERR_STATUS;
269 
270 	/* uid, tid can stay at zero as set in header assemble */
271 
272 	/* BB add support for turning on the signing when
273 	this function is used after 1st of session setup requests */
274 
275 	return rc;
276 }
277 
278 /* If the return code is zero, this function must fill in request_buf pointer */
279 static int
__smb_init(int smb_command,int wct,struct cifs_tcon * tcon,void ** request_buf,void ** response_buf)280 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
281 			void **request_buf, void **response_buf)
282 {
283 	unsigned int in_len;
284 
285 	*request_buf = cifs_buf_get();
286 	if (*request_buf == NULL) {
287 		/* BB should we add a retry in here if not a writepage? */
288 		return -ENOMEM;
289 	}
290     /* Although the original thought was we needed the response buf for  */
291     /* potential retries of smb operations it turns out we can determine */
292     /* from the mid flags when the request buffer can be resent without  */
293     /* having to use a second distinct buffer for the response */
294 	if (response_buf)
295 		*response_buf = *request_buf;
296 
297 	in_len = header_assemble((struct smb_hdr *)*request_buf, smb_command, tcon,
298 				 wct);
299 
300 	if (tcon != NULL)
301 		cifs_stats_inc(&tcon->num_smbs_sent);
302 
303 	return in_len;
304 }
305 
306 /* If the return code is zero, this function must fill in request_buf pointer */
307 static int
smb_init(int smb_command,int wct,struct cifs_tcon * tcon,void ** request_buf,void ** response_buf)308 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
309 	 void **request_buf, void **response_buf)
310 {
311 	int rc;
312 
313 	rc = cifs_reconnect_tcon(tcon, smb_command);
314 	if (rc)
315 		return rc;
316 
317 	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
318 }
319 
320 static int
smb_init_no_reconnect(int smb_command,int wct,struct cifs_tcon * tcon,void ** request_buf,void ** response_buf)321 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
322 			void **request_buf, void **response_buf)
323 {
324 	spin_lock(&tcon->ses->chan_lock);
325 	if (cifs_chan_needs_reconnect(tcon->ses, tcon->ses->server) ||
326 	    tcon->need_reconnect) {
327 		spin_unlock(&tcon->ses->chan_lock);
328 		return -EHOSTDOWN;
329 	}
330 	spin_unlock(&tcon->ses->chan_lock);
331 
332 	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
333 }
334 
validate_t2(struct smb_t2_rsp * pSMB)335 static int validate_t2(struct smb_t2_rsp *pSMB)
336 {
337 	unsigned int total_size;
338 
339 	/* check for plausible wct */
340 	if (pSMB->hdr.WordCount < 10)
341 		goto vt2_err;
342 
343 	/* check for parm and data offset going beyond end of smb */
344 	if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
345 	    get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
346 		goto vt2_err;
347 
348 	total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
349 	if (total_size >= 512)
350 		goto vt2_err;
351 
352 	/* check that bcc is at least as big as parms + data, and that it is
353 	 * less than negotiated smb buffer
354 	 */
355 	total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
356 	if (total_size > get_bcc(&pSMB->hdr) ||
357 	    total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
358 		goto vt2_err;
359 
360 	return 0;
361 vt2_err:
362 	cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
363 		sizeof(struct smb_t2_rsp) + 16);
364 	return -EINVAL;
365 }
366 
367 static int
decode_ext_sec_blob(struct cifs_ses * ses,SMB_NEGOTIATE_RSP * pSMBr)368 decode_ext_sec_blob(struct cifs_ses *ses, SMB_NEGOTIATE_RSP *pSMBr)
369 {
370 	int	rc = 0;
371 	u16	count;
372 	char	*guid = pSMBr->u.extended_response.GUID;
373 	struct TCP_Server_Info *server = ses->server;
374 
375 	count = get_bcc(&pSMBr->hdr);
376 	if (count < SMB1_CLIENT_GUID_SIZE)
377 		return smb_EIO2(smb_eio_trace_neg_sec_blob_too_small,
378 				count, SMB1_CLIENT_GUID_SIZE);
379 
380 	spin_lock(&cifs_tcp_ses_lock);
381 	if (server->srv_count > 1) {
382 		spin_unlock(&cifs_tcp_ses_lock);
383 		if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
384 			cifs_dbg(FYI, "server UID changed\n");
385 			memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
386 		}
387 	} else {
388 		spin_unlock(&cifs_tcp_ses_lock);
389 		memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
390 	}
391 
392 	if (count == SMB1_CLIENT_GUID_SIZE) {
393 		server->sec_ntlmssp = true;
394 	} else {
395 		count -= SMB1_CLIENT_GUID_SIZE;
396 		rc = decode_negTokenInit(
397 			pSMBr->u.extended_response.SecurityBlob, count, server);
398 		if (rc != 1)
399 			return -EINVAL;
400 	}
401 
402 	return 0;
403 }
404 
405 static bool
should_set_ext_sec_flag(enum securityEnum sectype)406 should_set_ext_sec_flag(enum securityEnum sectype)
407 {
408 	switch (sectype) {
409 	case RawNTLMSSP:
410 	case Kerberos:
411 		return true;
412 	case Unspecified:
413 		if (global_secflags &
414 		    (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
415 			return true;
416 		fallthrough;
417 	default:
418 		return false;
419 	}
420 }
421 
422 int
CIFSSMBNegotiate(const unsigned int xid,struct cifs_ses * ses,struct TCP_Server_Info * server)423 CIFSSMBNegotiate(const unsigned int xid,
424 		 struct cifs_ses *ses,
425 		 struct TCP_Server_Info *server)
426 {
427 	SMB_NEGOTIATE_REQ *pSMB;
428 	SMB_NEGOTIATE_RSP *pSMBr;
429 	unsigned int in_len;
430 	int rc = 0;
431 	int bytes_returned;
432 	int i;
433 	u16 count;
434 
435 	if (!server) {
436 		WARN(1, "%s: server is NULL!\n", __func__);
437 		return smb_EIO(smb_eio_trace_null_pointers);
438 	}
439 
440 	rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
441 		      (void **) &pSMB, (void **) &pSMBr);
442 	if (rc < 0)
443 		return rc;
444 	in_len = rc;
445 
446 	pSMB->hdr.Mid = get_next_mid(server);
447 	pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
448 
449 	if (ses->unicode != 0)
450 		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
451 
452 	if (should_set_ext_sec_flag(ses->sectype)) {
453 		cifs_dbg(FYI, "Requesting extended security\n");
454 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
455 	}
456 
457 	count = 0;
458 	/*
459 	 * We know that all the name entries in the protocols array
460 	 * are short (< 16 bytes anyway) and are NUL terminated.
461 	 */
462 	for (i = 0; i < CIFS_NUM_PROT; i++) {
463 		size_t len = strlen(protocols[i].name) + 1;
464 
465 		memcpy(&pSMB->DialectsArray[count], protocols[i].name, len);
466 		count += len;
467 	}
468 	in_len += count;
469 	pSMB->ByteCount = cpu_to_le16(count);
470 
471 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, in_len,
472 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
473 	if (rc != 0)
474 		goto neg_err_exit;
475 
476 	server->dialect = le16_to_cpu(pSMBr->DialectIndex);
477 	cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
478 	/* Check wct = 1 error case */
479 	if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
480 		/* core returns wct = 1, but we do not ask for core - otherwise
481 		small wct just comes when dialect index is -1 indicating we
482 		could not negotiate a common dialect */
483 		rc = -EOPNOTSUPP;
484 		goto neg_err_exit;
485 	} else if (pSMBr->hdr.WordCount != 17) {
486 		/* unknown wct */
487 		rc = -EOPNOTSUPP;
488 		goto neg_err_exit;
489 	}
490 	/* else wct == 17, NTLM or better */
491 
492 	server->sec_mode = pSMBr->SecurityMode;
493 	if ((server->sec_mode & SECMODE_USER) == 0)
494 		cifs_dbg(FYI, "share mode security\n");
495 
496 	/* one byte, so no need to convert this or EncryptionKeyLen from
497 	   little endian */
498 	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
499 			       cifs_max_pending);
500 	set_credits(server, server->maxReq);
501 	/* probably no need to store and check maxvcs */
502 	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
503 	/* set up max_read for readahead check */
504 	server->max_read = server->maxBuf;
505 	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
506 	cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
507 	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
508 	server->session_key_id = pSMBr->SessionKey;
509 	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
510 	server->timeAdj *= 60;
511 
512 	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
513 		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
514 		memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
515 		       CIFS_CRYPTO_KEY_SIZE);
516 	} else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
517 			server->capabilities & CAP_EXTENDED_SECURITY) {
518 		server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
519 		rc = decode_ext_sec_blob(ses, pSMBr);
520 	} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
521 		/* no crypt key only if plain text pwd */
522 		rc = smb_EIO(smb_eio_trace_neg_no_crypt_key);
523 	} else {
524 		server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
525 		server->capabilities &= ~CAP_EXTENDED_SECURITY;
526 	}
527 
528 	if (!rc)
529 		rc = cifs_enable_signing(server, ses->sign);
530 neg_err_exit:
531 	cifs_buf_release(pSMB);
532 
533 	cifs_dbg(FYI, "negprot rc %d\n", rc);
534 	return rc;
535 }
536 
537 /*
538  * Issue a TREE_CONNECT request.
539  */
540 int
CIFSTCon(const unsigned int xid,struct cifs_ses * ses,const char * tree,struct cifs_tcon * tcon,const struct nls_table * nls_codepage)541 CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
542 	 const char *tree, struct cifs_tcon *tcon,
543 	 const struct nls_table *nls_codepage)
544 {
545 	struct smb_hdr *smb_buffer;
546 	struct smb_hdr *smb_buffer_response;
547 	TCONX_REQ *pSMB;
548 	TCONX_RSP *pSMBr;
549 	unsigned char *bcc_ptr;
550 	int rc = 0;
551 	int length, in_len;
552 	__u16 bytes_left, count;
553 
554 	if (ses == NULL)
555 		return smb_EIO(smb_eio_trace_null_pointers);
556 
557 	smb_buffer = cifs_buf_get();
558 	if (smb_buffer == NULL)
559 		return -ENOMEM;
560 
561 	smb_buffer_response = smb_buffer;
562 
563 	in_len = header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
564 				 NULL /*no tid */, 4 /*wct */);
565 
566 	smb_buffer->Mid = get_next_mid(ses->server);
567 	smb_buffer->Uid = ses->Suid;
568 	pSMB = (TCONX_REQ *) smb_buffer;
569 	pSMBr = (TCONX_RSP *) smb_buffer_response;
570 
571 	pSMB->AndXCommand = 0xFF;
572 	pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
573 	bcc_ptr = &pSMB->Password[0];
574 
575 	pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
576 	*bcc_ptr = 0; /* password is null byte */
577 	bcc_ptr++;              /* skip password */
578 	/* already aligned so no need to do it below */
579 
580 	if (ses->server->sign)
581 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
582 
583 	if (ses->capabilities & CAP_STATUS32)
584 		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
585 
586 	if (ses->capabilities & CAP_DFS)
587 		smb_buffer->Flags2 |= SMBFLG2_DFS;
588 
589 	if (ses->capabilities & CAP_UNICODE) {
590 		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
591 		length =
592 		    cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
593 			6 /* max utf8 char length in bytes */ *
594 			(/* server len*/ + 256 /* share len */), nls_codepage);
595 		bcc_ptr += 2 * length;	/* convert num 16 bit words to bytes */
596 		bcc_ptr += 2;	/* skip trailing null */
597 	} else {		/* ASCII */
598 		strcpy(bcc_ptr, tree);
599 		bcc_ptr += strlen(tree) + 1;
600 	}
601 	strcpy(bcc_ptr, "?????");
602 	bcc_ptr += strlen("?????");
603 	bcc_ptr += 1;
604 	count = bcc_ptr - &pSMB->Password[0];
605 	in_len += count;
606 	pSMB->ByteCount = cpu_to_le16(count);
607 
608 	rc = SendReceive(xid, ses, smb_buffer, in_len, smb_buffer_response,
609 			 &length, 0);
610 
611 	/* above now done in SendReceive */
612 	if (rc == 0) {
613 		bool is_unicode;
614 
615 		tcon->tid = smb_buffer_response->Tid;
616 		bcc_ptr = pByteArea(smb_buffer_response);
617 		bytes_left = get_bcc(smb_buffer_response);
618 		if (bytes_left < 2) {
619 			rc = smb_EIO2(smb_eio_trace_tcon_bcc_too_small,
620 				      bytes_left, 2);
621 			goto out;
622 		}
623 		length = strnlen(bcc_ptr, bytes_left - 2);
624 		if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
625 			is_unicode = true;
626 		else
627 			is_unicode = false;
628 
629 
630 		/* skip service field (NB: this field is always ASCII) */
631 		if (length == 3) {
632 			if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
633 			    (bcc_ptr[2] == 'C')) {
634 				cifs_dbg(FYI, "IPC connection\n");
635 				tcon->ipc = true;
636 				tcon->pipe = true;
637 			}
638 		} else if (length == 2) {
639 			if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
640 				/* the most common case */
641 				cifs_dbg(FYI, "disk share connection\n");
642 			}
643 		}
644 		bcc_ptr += length + 1;
645 		bytes_left -= (length + 1);
646 		strscpy(tcon->tree_name, tree, sizeof(tcon->tree_name));
647 
648 		/* mostly informational -- no need to fail on error here */
649 		kfree(tcon->nativeFileSystem);
650 		tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
651 						      bytes_left, is_unicode,
652 						      nls_codepage);
653 
654 		cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
655 
656 		if ((smb_buffer_response->WordCount == 3) ||
657 			 (smb_buffer_response->WordCount == 7))
658 			/* field is in same location */
659 			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
660 		else
661 			tcon->Flags = 0;
662 		cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
663 
664 		/*
665 		 * reset_cifs_unix_caps calls QFSInfo which requires
666 		 * need_reconnect to be false, but we would not need to call
667 		 * reset_caps if this were not a reconnect case so must check
668 		 * need_reconnect flag here.  The caller will also clear
669 		 * need_reconnect when tcon was successful but needed to be
670 		 * cleared earlier in the case of unix extensions reconnect
671 		 */
672 		if (tcon->need_reconnect && tcon->unix_ext) {
673 			cifs_dbg(FYI, "resetting caps for %s\n", tcon->tree_name);
674 			tcon->need_reconnect = false;
675 			reset_cifs_unix_caps(xid, tcon, NULL, NULL);
676 		}
677 	}
678 out:
679 	cifs_buf_release(smb_buffer);
680 	return rc;
681 }
682 
683 int
CIFSSMBTDis(const unsigned int xid,struct cifs_tcon * tcon)684 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
685 {
686 	struct smb_hdr *smb_buffer;
687 	unsigned int in_len;
688 	int rc = 0;
689 
690 	cifs_dbg(FYI, "In tree disconnect\n");
691 
692 	/* BB: do we need to check this? These should never be NULL. */
693 	if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
694 		return smb_EIO(smb_eio_trace_null_pointers);
695 
696 	/*
697 	 * No need to return error on this operation if tid invalidated and
698 	 * closed on server already e.g. due to tcp session crashing. Also,
699 	 * the tcon is no longer on the list, so no need to take lock before
700 	 * checking this.
701 	 */
702 	spin_lock(&tcon->ses->chan_lock);
703 	if ((tcon->need_reconnect) || CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses)) {
704 		spin_unlock(&tcon->ses->chan_lock);
705 		return smb_EIO(smb_eio_trace_tdis_in_reconnect);
706 	}
707 	spin_unlock(&tcon->ses->chan_lock);
708 
709 	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
710 			    (void **)&smb_buffer);
711 	if (rc < 0)
712 		return rc;
713 	in_len = rc;
714 
715 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, in_len, 0);
716 	cifs_small_buf_release(smb_buffer);
717 	if (rc)
718 		cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
719 
720 	/* No need to return error on this operation if tid invalidated and
721 	   closed on server already e.g. due to tcp session crashing */
722 	if (rc == -EAGAIN)
723 		rc = 0;
724 
725 	return rc;
726 }
727 
728 /*
729  * This is a no-op for now. We're not really interested in the reply, but
730  * rather in the fact that the server sent one and that server->lstrp
731  * gets updated.
732  *
733  * FIXME: maybe we should consider checking that the reply matches request?
734  */
735 static void
cifs_echo_callback(struct TCP_Server_Info * server,struct mid_q_entry * mid)736 cifs_echo_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
737 {
738 	struct cifs_credits credits = { .value = 1, .instance = 0 };
739 
740 	release_mid(server, mid);
741 	add_credits(server, &credits, CIFS_ECHO_OP);
742 }
743 
744 int
CIFSSMBEcho(struct TCP_Server_Info * server)745 CIFSSMBEcho(struct TCP_Server_Info *server)
746 {
747 	ECHO_REQ *smb;
748 	int rc = 0;
749 	struct kvec iov[1];
750 	struct smb_rqst rqst = {
751 		.rq_iov = iov,
752 		.rq_nvec = ARRAY_SIZE(iov),
753 	};
754 	unsigned int in_len;
755 
756 	cifs_dbg(FYI, "In echo request\n");
757 
758 	rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
759 	if (rc < 0)
760 		return rc;
761 	in_len = rc;
762 
763 	if (server->capabilities & CAP_UNICODE)
764 		smb->hdr.Flags2 |= SMBFLG2_UNICODE;
765 
766 	/* set up echo request */
767 	smb->hdr.Tid = 0xffff;
768 	smb->hdr.WordCount = 1;
769 	put_unaligned_le16(1, &smb->EchoCount);
770 	put_bcc(1, &smb->hdr);
771 	smb->Data[0] = 'a';
772 	in_len += 3;
773 
774 	iov[0].iov_len = in_len;
775 	iov[0].iov_base = smb;
776 
777 	rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
778 			     server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
779 	if (rc)
780 		cifs_dbg(FYI, "Echo request failed: %d\n", rc);
781 
782 	cifs_small_buf_release(smb);
783 
784 	return rc;
785 }
786 
787 int
CIFSSMBLogoff(const unsigned int xid,struct cifs_ses * ses)788 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
789 {
790 	LOGOFF_ANDX_REQ *pSMB;
791 	unsigned int in_len;
792 	int rc = 0;
793 
794 	cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
795 
796 	/*
797 	 * BB: do we need to check validity of ses and server? They should
798 	 * always be valid since we have an active reference. If not, that
799 	 * should probably be a BUG()
800 	 */
801 	if (!ses || !ses->server)
802 		return smb_EIO(smb_eio_trace_null_pointers);
803 
804 	mutex_lock(&ses->session_mutex);
805 	spin_lock(&ses->chan_lock);
806 	if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
807 		spin_unlock(&ses->chan_lock);
808 		goto session_already_dead; /* no need to send SMBlogoff if uid
809 					      already closed due to reconnect */
810 	}
811 	spin_unlock(&ses->chan_lock);
812 
813 	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
814 	if (rc < 0) {
815 		mutex_unlock(&ses->session_mutex);
816 		return rc;
817 	}
818 	in_len = rc;
819 
820 	pSMB->hdr.Mid = get_next_mid(ses->server);
821 
822 	if (ses->server->sign)
823 		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
824 
825 	pSMB->hdr.Uid = ses->Suid;
826 
827 	pSMB->AndXCommand = 0xFF;
828 	rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, in_len, 0);
829 	cifs_small_buf_release(pSMB);
830 session_already_dead:
831 	mutex_unlock(&ses->session_mutex);
832 
833 	/* if session dead then we do not need to do ulogoff,
834 		since server closed smb session, no sense reporting
835 		error */
836 	if (rc == -EAGAIN)
837 		rc = 0;
838 	return rc;
839 }
840 
841 int
CIFSPOSIXDelFile(const unsigned int xid,struct cifs_tcon * tcon,const char * fileName,__u16 type,const struct nls_table * nls_codepage,int remap)842 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
843 		 const char *fileName, __u16 type,
844 		 const struct nls_table *nls_codepage, int remap)
845 {
846 	TRANSACTION2_SPI_REQ *pSMB = NULL;
847 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
848 	struct unlink_psx_rq *pRqD;
849 	unsigned int in_len;
850 	int name_len;
851 	int rc = 0;
852 	int bytes_returned = 0;
853 	__u16 params, param_offset, offset, byte_count;
854 
855 	cifs_dbg(FYI, "In POSIX delete\n");
856 PsxDelete:
857 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
858 		      (void **) &pSMBr);
859 	if (rc < 0)
860 		return rc;
861 	in_len = rc;
862 
863 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
864 		name_len =
865 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
866 				       PATH_MAX, nls_codepage, remap);
867 		name_len++;	/* trailing null */
868 		name_len *= 2;
869 	} else {
870 		name_len = copy_path_name(pSMB->FileName, fileName);
871 	}
872 
873 	params = 6 + name_len;
874 	pSMB->MaxParameterCount = cpu_to_le16(2);
875 	pSMB->MaxDataCount = 0; /* BB double check this with jra */
876 	pSMB->MaxSetupCount = 0;
877 	pSMB->Reserved = 0;
878 	pSMB->Flags = 0;
879 	pSMB->Timeout = 0;
880 	pSMB->Reserved2 = 0;
881 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
882 				InformationLevel);
883 	offset = param_offset + params;
884 
885 	/* Setup pointer to Request Data (inode type). */
886 	pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset);
887 	pRqD->type = cpu_to_le16(type);
888 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
889 	pSMB->DataOffset = cpu_to_le16(offset);
890 	pSMB->SetupCount = 1;
891 	pSMB->Reserved3 = 0;
892 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
893 	byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
894 
895 	pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
896 	pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
897 	pSMB->ParameterCount = cpu_to_le16(params);
898 	pSMB->TotalParameterCount = pSMB->ParameterCount;
899 	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
900 	pSMB->Reserved4 = 0;
901 	in_len += byte_count;
902 	pSMB->ByteCount = cpu_to_le16(byte_count);
903 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
904 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
905 	if (rc)
906 		cifs_dbg(FYI, "Posix delete returned %d\n", rc);
907 	cifs_buf_release(pSMB);
908 
909 	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
910 
911 	if (rc == -EAGAIN)
912 		goto PsxDelete;
913 
914 	return rc;
915 }
916 
917 int
CIFSSMBDelFile(const unsigned int xid,struct cifs_tcon * tcon,const char * name,struct cifs_sb_info * cifs_sb,struct dentry * dentry)918 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
919 	       struct cifs_sb_info *cifs_sb, struct dentry *dentry)
920 {
921 	DELETE_FILE_REQ *pSMB = NULL;
922 	DELETE_FILE_RSP *pSMBr = NULL;
923 	unsigned int in_len;
924 	int rc = 0;
925 	int bytes_returned;
926 	int name_len;
927 	int remap = cifs_remap(cifs_sb);
928 
929 DelFileRetry:
930 	rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
931 		      (void **) &pSMBr);
932 	if (rc < 0)
933 		return rc;
934 	in_len = rc;
935 
936 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
937 		name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
938 					      PATH_MAX, cifs_sb->local_nls,
939 					      remap);
940 		name_len++;	/* trailing null */
941 		name_len *= 2;
942 	} else {
943 		name_len = copy_path_name(pSMB->fileName, name);
944 	}
945 	pSMB->SearchAttributes =
946 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
947 	pSMB->BufferFormat = 0x04;
948 	in_len += name_len + 1;
949 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
950 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
951 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
952 	cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
953 	if (rc)
954 		cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
955 
956 	cifs_buf_release(pSMB);
957 	if (rc == -EAGAIN)
958 		goto DelFileRetry;
959 
960 	return rc;
961 }
962 
963 int
CIFSSMBRmDir(const unsigned int xid,struct cifs_tcon * tcon,const char * name,struct cifs_sb_info * cifs_sb)964 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
965 	     struct cifs_sb_info *cifs_sb)
966 {
967 	DELETE_DIRECTORY_REQ *pSMB = NULL;
968 	DELETE_DIRECTORY_RSP *pSMBr = NULL;
969 	unsigned int in_len;
970 	int rc = 0;
971 	int bytes_returned;
972 	int name_len;
973 	int remap = cifs_remap(cifs_sb);
974 
975 	cifs_dbg(FYI, "In CIFSSMBRmDir\n");
976 RmDirRetry:
977 	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
978 		      (void **) &pSMBr);
979 	if (rc < 0)
980 		return rc;
981 	in_len = rc;
982 
983 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
984 		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
985 					      PATH_MAX, cifs_sb->local_nls,
986 					      remap);
987 		name_len++;	/* trailing null */
988 		name_len *= 2;
989 	} else {
990 		name_len = copy_path_name(pSMB->DirName, name);
991 	}
992 
993 	pSMB->BufferFormat = 0x04;
994 	in_len += name_len + 1;
995 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
996 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
997 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
998 	cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
999 	if (rc)
1000 		cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
1001 
1002 	cifs_buf_release(pSMB);
1003 	if (rc == -EAGAIN)
1004 		goto RmDirRetry;
1005 	return rc;
1006 }
1007 
1008 int
CIFSSMBMkDir(const unsigned int xid,struct inode * inode,umode_t mode,struct cifs_tcon * tcon,const char * name,struct cifs_sb_info * cifs_sb)1009 CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
1010 	     struct cifs_tcon *tcon, const char *name,
1011 	     struct cifs_sb_info *cifs_sb)
1012 {
1013 	int rc = 0;
1014 	CREATE_DIRECTORY_REQ *pSMB = NULL;
1015 	CREATE_DIRECTORY_RSP *pSMBr = NULL;
1016 	unsigned int in_len;
1017 	int bytes_returned;
1018 	int name_len;
1019 	int remap = cifs_remap(cifs_sb);
1020 
1021 	cifs_dbg(FYI, "In CIFSSMBMkDir\n");
1022 MkDirRetry:
1023 	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1024 		      (void **) &pSMBr);
1025 	if (rc < 0)
1026 		return rc;
1027 	in_len = rc;
1028 
1029 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1030 		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1031 					      PATH_MAX, cifs_sb->local_nls,
1032 					      remap);
1033 		name_len++;	/* trailing null */
1034 		name_len *= 2;
1035 	} else {
1036 		name_len = copy_path_name(pSMB->DirName, name);
1037 	}
1038 
1039 	pSMB->BufferFormat = 0x04;
1040 	in_len += name_len + 1;
1041 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
1042 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
1043 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1044 	cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1045 	if (rc)
1046 		cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
1047 
1048 	cifs_buf_release(pSMB);
1049 	if (rc == -EAGAIN)
1050 		goto MkDirRetry;
1051 	return rc;
1052 }
1053 
1054 int
CIFSPOSIXCreate(const unsigned int xid,struct cifs_tcon * tcon,__u32 posix_flags,__u64 mode,__u16 * netfid,FILE_UNIX_BASIC_INFO * pRetData,__u32 * pOplock,const char * name,const struct nls_table * nls_codepage,int remap)1055 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1056 		__u32 posix_flags, __u64 mode, __u16 *netfid,
1057 		FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1058 		const char *name, const struct nls_table *nls_codepage,
1059 		int remap)
1060 {
1061 	TRANSACTION2_SPI_REQ *pSMB = NULL;
1062 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
1063 	unsigned int in_len;
1064 	int name_len;
1065 	int rc = 0;
1066 	int bytes_returned = 0;
1067 	__u16 params, param_offset, offset, byte_count, count;
1068 	OPEN_PSX_REQ *pdata;
1069 	OPEN_PSX_RSP *psx_rsp;
1070 
1071 	cifs_dbg(FYI, "In POSIX Create\n");
1072 PsxCreat:
1073 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1074 		      (void **) &pSMBr);
1075 	if (rc < 0)
1076 		return rc;
1077 	in_len = rc;
1078 
1079 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1080 		name_len =
1081 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1082 				       PATH_MAX, nls_codepage, remap);
1083 		name_len++;	/* trailing null */
1084 		name_len *= 2;
1085 	} else {
1086 		name_len = copy_path_name(pSMB->FileName, name);
1087 	}
1088 
1089 	params = 6 + name_len;
1090 	count = sizeof(OPEN_PSX_REQ);
1091 	pSMB->MaxParameterCount = cpu_to_le16(2);
1092 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* large enough */
1093 	pSMB->MaxSetupCount = 0;
1094 	pSMB->Reserved = 0;
1095 	pSMB->Flags = 0;
1096 	pSMB->Timeout = 0;
1097 	pSMB->Reserved2 = 0;
1098 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
1099 				InformationLevel);
1100 	offset = param_offset + params;
1101 	pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset);
1102 	pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1103 	pdata->Permissions = cpu_to_le64(mode);
1104 	pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1105 	pdata->OpenFlags =  cpu_to_le32(*pOplock);
1106 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
1107 	pSMB->DataOffset = cpu_to_le16(offset);
1108 	pSMB->SetupCount = 1;
1109 	pSMB->Reserved3 = 0;
1110 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1111 	byte_count = 3 /* pad */  + params + count;
1112 
1113 	pSMB->DataCount = cpu_to_le16(count);
1114 	pSMB->ParameterCount = cpu_to_le16(params);
1115 	pSMB->TotalDataCount = pSMB->DataCount;
1116 	pSMB->TotalParameterCount = pSMB->ParameterCount;
1117 	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1118 	pSMB->Reserved4 = 0;
1119 	in_len += byte_count;
1120 	pSMB->ByteCount = cpu_to_le16(byte_count);
1121 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
1122 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1123 	if (rc) {
1124 		cifs_dbg(FYI, "Posix create returned %d\n", rc);
1125 		goto psx_create_err;
1126 	}
1127 
1128 	cifs_dbg(FYI, "copying inode info\n");
1129 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1130 
1131 	if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1132 		rc = smb_EIO2(smb_eio_trace_create_rsp_too_small,
1133 			      get_bcc(&pSMBr->hdr), sizeof(OPEN_PSX_RSP));
1134 		goto psx_create_err;
1135 	}
1136 
1137 	/* copy return information to pRetData */
1138 	psx_rsp = (OPEN_PSX_RSP *)
1139 		((char *)pSMBr + le16_to_cpu(pSMBr->t2.DataOffset));
1140 
1141 	*pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1142 	if (netfid)
1143 		*netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1144 	/* Let caller know file was created so we can set the mode. */
1145 	/* Do we care about the CreateAction in any other cases? */
1146 	if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1147 		*pOplock |= CIFS_CREATE_ACTION;
1148 	/* check to make sure response data is there */
1149 	if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1150 		pRetData->Type = cpu_to_le32(-1); /* unknown */
1151 		cifs_dbg(NOISY, "unknown type\n");
1152 	} else {
1153 		if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1154 					+ sizeof(FILE_UNIX_BASIC_INFO)) {
1155 			cifs_dbg(VFS, "Open response data too small\n");
1156 			pRetData->Type = cpu_to_le32(-1);
1157 			goto psx_create_err;
1158 		}
1159 		memcpy(pRetData,
1160 		       (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1161 		       sizeof(*pRetData));
1162 	}
1163 
1164 psx_create_err:
1165 	cifs_buf_release(pSMB);
1166 
1167 	if (posix_flags & SMB_O_DIRECTORY)
1168 		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1169 	else
1170 		cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1171 
1172 	if (rc == -EAGAIN)
1173 		goto PsxCreat;
1174 
1175 	return rc;
1176 }
1177 
convert_disposition(int disposition)1178 static __u16 convert_disposition(int disposition)
1179 {
1180 	__u16 ofun = 0;
1181 
1182 	switch (disposition) {
1183 		case FILE_SUPERSEDE:
1184 			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1185 			break;
1186 		case FILE_OPEN:
1187 			ofun = SMBOPEN_OAPPEND;
1188 			break;
1189 		case FILE_CREATE:
1190 			ofun = SMBOPEN_OCREATE;
1191 			break;
1192 		case FILE_OPEN_IF:
1193 			ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1194 			break;
1195 		case FILE_OVERWRITE:
1196 			ofun = SMBOPEN_OTRUNC;
1197 			break;
1198 		case FILE_OVERWRITE_IF:
1199 			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1200 			break;
1201 		default:
1202 			cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1203 			ofun =  SMBOPEN_OAPPEND; /* regular open */
1204 	}
1205 	return ofun;
1206 }
1207 
1208 static int
access_flags_to_smbopen_mode(const int access_flags)1209 access_flags_to_smbopen_mode(const int access_flags)
1210 {
1211 	/*
1212 	 * SYSTEM_SECURITY grants both read and write access to SACL, treat is as read/write.
1213 	 * MAXIMUM_ALLOWED grants as many access as possible, so treat it as read/write too.
1214 	 * SYNCHRONIZE as is does not grant any specific access, so do not check its mask.
1215 	 * If only SYNCHRONIZE bit is specified then fallback to read access.
1216 	 */
1217 	bool with_write_flags = access_flags & (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA |
1218 						FILE_DELETE_CHILD | FILE_WRITE_ATTRIBUTES | DELETE |
1219 						WRITE_DAC | WRITE_OWNER | SYSTEM_SECURITY |
1220 						MAXIMUM_ALLOWED | GENERIC_WRITE | GENERIC_ALL);
1221 	bool with_read_flags = access_flags & (FILE_READ_DATA | FILE_READ_EA | FILE_EXECUTE |
1222 						FILE_READ_ATTRIBUTES | READ_CONTROL |
1223 						SYSTEM_SECURITY | MAXIMUM_ALLOWED | GENERIC_ALL |
1224 						GENERIC_EXECUTE | GENERIC_READ);
1225 	bool with_execute_flags = access_flags & (FILE_EXECUTE | MAXIMUM_ALLOWED | GENERIC_ALL |
1226 						GENERIC_EXECUTE);
1227 
1228 	if (with_write_flags && with_read_flags)
1229 		return SMBOPEN_READWRITE;
1230 	else if (with_write_flags)
1231 		return SMBOPEN_WRITE;
1232 	else if (with_execute_flags)
1233 		return SMBOPEN_EXECUTE;
1234 	else
1235 		return SMBOPEN_READ;
1236 }
1237 
1238 int
SMBLegacyOpen(const unsigned int xid,struct cifs_tcon * tcon,const char * fileName,const int openDisposition,const int access_flags,const int create_options,__u16 * netfid,int * pOplock,FILE_ALL_INFO * pfile_info,const struct nls_table * nls_codepage,int remap)1239 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1240 	    const char *fileName, const int openDisposition,
1241 	    const int access_flags, const int create_options, __u16 *netfid,
1242 	    int *pOplock, FILE_ALL_INFO *pfile_info,
1243 	    const struct nls_table *nls_codepage, int remap)
1244 {
1245 	int rc;
1246 	OPENX_REQ *pSMB = NULL;
1247 	OPENX_RSP *pSMBr = NULL;
1248 	unsigned int in_len;
1249 	int bytes_returned;
1250 	int name_len;
1251 	__u16 count;
1252 
1253 OldOpenRetry:
1254 	rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1255 		      (void **) &pSMBr);
1256 	if (rc < 0)
1257 		return rc;
1258 	in_len = rc;
1259 
1260 	pSMB->AndXCommand = 0xFF;       /* none */
1261 
1262 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1263 		count = 1;      /* account for one byte pad to word boundary */
1264 		name_len =
1265 		   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1266 				      fileName, PATH_MAX, nls_codepage, remap);
1267 		name_len++;     /* trailing null */
1268 		name_len *= 2;
1269 	} else {
1270 		count = 0;      /* no pad */
1271 		name_len = copy_path_name(pSMB->fileName, fileName);
1272 	}
1273 	if (*pOplock & REQ_OPLOCK)
1274 		pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1275 	else if (*pOplock & REQ_BATCHOPLOCK)
1276 		pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1277 
1278 	pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1279 	pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1280 	pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1281 	/* set file as system file if special file such as fifo,
1282 	 * socket, char or block and server expecting SFU style and
1283 	   no Unix extensions */
1284 
1285 	if (create_options & CREATE_OPTION_SPECIAL)
1286 		pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1287 	else /* BB FIXME BB */
1288 		pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1289 
1290 	if (create_options & CREATE_OPTION_READONLY)
1291 		pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1292 
1293 	/* BB FIXME BB */
1294 /*	pSMB->CreateOptions = cpu_to_le32(create_options &
1295 						 CREATE_OPTIONS_MASK); */
1296 	/* BB FIXME END BB */
1297 
1298 	pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1299 	pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1300 	count += name_len;
1301 	in_len += count;
1302 
1303 	pSMB->ByteCount = cpu_to_le16(count);
1304 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
1305 			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
1306 	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1307 	if (rc) {
1308 		cifs_dbg(FYI, "Error in Open = %d\n", rc);
1309 	} else {
1310 	/* BB verify if wct == 15 */
1311 
1312 /*		*pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1313 
1314 		*netfid = pSMBr->Fid;   /* cifs fid stays in le */
1315 		/* Let caller know file was created so we can set the mode. */
1316 		/* Do we care about the CreateAction in any other cases? */
1317 	/* BB FIXME BB */
1318 /*		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1319 			*pOplock |= CIFS_CREATE_ACTION; */
1320 	/* BB FIXME END */
1321 
1322 		if (pfile_info) {
1323 			pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1324 			pfile_info->LastAccessTime = 0; /* BB fixme */
1325 			pfile_info->LastWriteTime = 0; /* BB fixme */
1326 			pfile_info->ChangeTime = 0;  /* BB fixme */
1327 			pfile_info->Attributes =
1328 				cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1329 			/* the file_info buf is endian converted by caller */
1330 			pfile_info->AllocationSize =
1331 				cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1332 			pfile_info->EndOfFile = pfile_info->AllocationSize;
1333 			pfile_info->NumberOfLinks = cpu_to_le32(1);
1334 			pfile_info->DeletePending = 0; /* successful open = not delete pending */
1335 		}
1336 	}
1337 
1338 	cifs_buf_release(pSMB);
1339 	if (rc == -EAGAIN)
1340 		goto OldOpenRetry;
1341 	return rc;
1342 }
1343 
1344 int
CIFS_open(const unsigned int xid,struct cifs_open_parms * oparms,int * oplock,FILE_ALL_INFO * buf)1345 CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1346 	  FILE_ALL_INFO *buf)
1347 {
1348 	int rc;
1349 	OPEN_REQ *req = NULL;
1350 	OPEN_RSP *rsp = NULL;
1351 	int bytes_returned;
1352 	int name_len;
1353 	__u16 count;
1354 	struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1355 	struct cifs_tcon *tcon = oparms->tcon;
1356 	int remap = cifs_remap(cifs_sb);
1357 	const struct nls_table *nls = cifs_sb->local_nls;
1358 	int create_options = oparms->create_options;
1359 	int desired_access = oparms->desired_access;
1360 	int disposition = oparms->disposition;
1361 	const char *path = oparms->path;
1362 	unsigned int in_len;
1363 
1364 openRetry:
1365 	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1366 		      (void **)&rsp);
1367 	if (rc < 0)
1368 		return rc;
1369 	in_len = rc;
1370 
1371 	/* no commands go after this */
1372 	req->AndXCommand = 0xFF;
1373 
1374 	if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1375 		/* account for one byte pad to word boundary */
1376 		count = 1;
1377 		name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1378 					      path, PATH_MAX, nls, remap);
1379 		/* trailing null */
1380 		name_len++;
1381 		name_len *= 2;
1382 		req->NameLength = cpu_to_le16(name_len);
1383 	} else {
1384 		/* BB improve check for buffer overruns BB */
1385 		/* no pad */
1386 		count = 0;
1387 		name_len = copy_path_name(req->fileName, path);
1388 		req->NameLength = cpu_to_le16(name_len);
1389 	}
1390 
1391 	if (*oplock & REQ_OPLOCK)
1392 		req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1393 	else if (*oplock & REQ_BATCHOPLOCK)
1394 		req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1395 
1396 	req->DesiredAccess = cpu_to_le32(desired_access);
1397 	req->AllocationSize = 0;
1398 
1399 	/*
1400 	 * Set file as system file if special file such as fifo, socket, char
1401 	 * or block and server expecting SFU style and no Unix extensions.
1402 	 */
1403 	if (create_options & CREATE_OPTION_SPECIAL)
1404 		req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1405 	else
1406 		req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1407 
1408 	/*
1409 	 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1410 	 * sensitive checks for other servers such as Samba.
1411 	 */
1412 	if (tcon->ses->capabilities & CAP_UNIX)
1413 		req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1414 
1415 	if (create_options & CREATE_OPTION_READONLY)
1416 		req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1417 
1418 	req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1419 	req->CreateDisposition = cpu_to_le32(disposition);
1420 	req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1421 
1422 	/* BB Experiment with various impersonation levels and verify */
1423 	req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1424 	req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1425 
1426 	count += name_len;
1427 	in_len += count;
1428 
1429 	req->ByteCount = cpu_to_le16(count);
1430 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req, in_len,
1431 			 (struct smb_hdr *)rsp, &bytes_returned, 0);
1432 	cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1433 	if (rc) {
1434 		cifs_dbg(FYI, "Error in Open = %d\n", rc);
1435 		cifs_buf_release(req);
1436 		if (rc == -EAGAIN)
1437 			goto openRetry;
1438 		return rc;
1439 	}
1440 
1441 	/* 1 byte no need to le_to_cpu */
1442 	*oplock = rsp->OplockLevel;
1443 	/* cifs fid stays in le */
1444 	oparms->fid->netfid = rsp->Fid;
1445 	oparms->fid->access = desired_access;
1446 
1447 	/* Let caller know file was created so we can set the mode. */
1448 	/* Do we care about the CreateAction in any other cases? */
1449 	if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1450 		*oplock |= CIFS_CREATE_ACTION;
1451 
1452 	if (buf) {
1453 		/* copy commonly used attributes */
1454 		memcpy(&buf->common_attributes,
1455 		       &rsp->common_attributes,
1456 		       sizeof(buf->common_attributes));
1457 		/* the file_info buf is endian converted by caller */
1458 		buf->AllocationSize = rsp->AllocationSize;
1459 		buf->EndOfFile = rsp->EndOfFile;
1460 		buf->NumberOfLinks = cpu_to_le32(1);
1461 		buf->DeletePending = 0; /* successful open = not delete pending */
1462 	}
1463 
1464 	cifs_buf_release(req);
1465 	return rc;
1466 }
1467 
1468 static void
cifs_readv_callback(struct TCP_Server_Info * server,struct mid_q_entry * mid)1469 cifs_readv_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1470 {
1471 	struct cifs_io_subrequest *rdata = mid->callback_data;
1472 	struct netfs_inode *ictx = netfs_inode(rdata->rreq->inode);
1473 	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
1474 	struct inode *inode = &ictx->inode;
1475 	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1476 				 .rq_nvec = 1,
1477 				 .rq_iter = rdata->subreq.io_iter };
1478 	struct cifs_credits credits = {
1479 		.value = 1,
1480 		.instance = 0,
1481 		.rreq_debug_id = rdata->rreq->debug_id,
1482 		.rreq_debug_index = rdata->subreq.debug_index,
1483 	};
1484 	unsigned int rreq_debug_id = rdata->rreq->debug_id;
1485 	unsigned int subreq_debug_index = rdata->subreq.debug_index;
1486 
1487 	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n",
1488 		 __func__, mid->mid, mid->mid_state, rdata->result,
1489 		 rdata->subreq.len);
1490 
1491 	switch (mid->mid_state) {
1492 	case MID_RESPONSE_RECEIVED:
1493 		/* result already set, check signature */
1494 		if (server->sign) {
1495 			int rc = 0;
1496 
1497 			iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);
1498 			rc = cifs_verify_signature(&rqst, server,
1499 						  mid->sequence_number);
1500 			if (rc)
1501 				cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1502 					 rc);
1503 		}
1504 		/* FIXME: should this be counted toward the initiating task? */
1505 		task_io_account_read(rdata->got_bytes);
1506 		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1507 		break;
1508 	case MID_REQUEST_SUBMITTED:
1509 		trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_req_submitted);
1510 		goto do_retry;
1511 	case MID_RETRY_NEEDED:
1512 		trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_retry_needed);
1513 do_retry:
1514 		__set_bit(NETFS_SREQ_NEED_RETRY, &rdata->subreq.flags);
1515 		rdata->result = -EAGAIN;
1516 		if (server->sign && rdata->got_bytes)
1517 			/* reset bytes number since we can not check a sign */
1518 			rdata->got_bytes = 0;
1519 		/* FIXME: should this be counted toward the initiating task? */
1520 		task_io_account_read(rdata->got_bytes);
1521 		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1522 		break;
1523 	case MID_RESPONSE_MALFORMED:
1524 		trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_malformed);
1525 		rdata->result = smb_EIO(smb_eio_trace_read_rsp_malformed);
1526 		break;
1527 	default:
1528 		trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_unknown);
1529 		rdata->result = smb_EIO1(smb_eio_trace_read_mid_state_unknown,
1530 					 mid->mid_state);
1531 		break;
1532 	}
1533 
1534 	if (rdata->result == -ENODATA) {
1535 		rdata->result = 0;
1536 		__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
1537 		trace_smb3_read_err(rdata->rreq->debug_id,
1538 				    rdata->subreq.debug_index,
1539 				    rdata->xid,
1540 				    rdata->req->cfile->fid.persistent_fid,
1541 				    tcon->tid, tcon->ses->Suid,
1542 				    rdata->subreq.start + rdata->subreq.transferred,
1543 				    rdata->subreq.len   - rdata->subreq.transferred,
1544 				    rdata->result);
1545 	} else {
1546 		size_t trans = rdata->subreq.transferred + rdata->got_bytes;
1547 		if (trans < rdata->subreq.len &&
1548 		    rdata->subreq.start + trans >= netfs_read_remote_i_size(inode)) {
1549 			rdata->result = 0;
1550 			__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
1551 		} else if (rdata->got_bytes > 0) {
1552 			__set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags);
1553 		}
1554 		if (rdata->got_bytes)
1555 			__set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags);
1556 		trace_smb3_read_done(rdata->rreq->debug_id,
1557 				     rdata->subreq.debug_index,
1558 				     rdata->xid,
1559 				     rdata->req->cfile->fid.persistent_fid,
1560 				     tcon->tid, tcon->ses->Suid,
1561 				     rdata->subreq.start + rdata->subreq.transferred,
1562 				     rdata->got_bytes);
1563 	}
1564 
1565 	trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, rdata->credits.value,
1566 			      server->credits, server->in_flight,
1567 			      0, cifs_trace_rw_credits_read_response_clear);
1568 	rdata->credits.value = 0;
1569 	rdata->subreq.error = rdata->result;
1570 	rdata->subreq.transferred += rdata->got_bytes;
1571 	trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_progress);
1572 	netfs_read_subreq_terminated(&rdata->subreq);
1573 	release_mid(server, mid);
1574 	add_credits(server, &credits, 0);
1575 	trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0,
1576 			      server->credits, server->in_flight,
1577 			      credits.value, cifs_trace_rw_credits_read_response_add);
1578 }
1579 
1580 /* cifs_async_readv - send an async write, and set up mid to handle result */
1581 int
cifs_async_readv(struct cifs_io_subrequest * rdata)1582 cifs_async_readv(struct cifs_io_subrequest *rdata)
1583 {
1584 	int rc;
1585 	READ_REQ *smb = NULL;
1586 	int wct;
1587 	struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
1588 	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1589 				 .rq_nvec = 1 };
1590 	unsigned int in_len;
1591 
1592 	cifs_dbg(FYI, "%s: offset=%llu bytes=%zu\n",
1593 		 __func__, rdata->subreq.start, rdata->subreq.len);
1594 
1595 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1596 		wct = 12;
1597 	else {
1598 		wct = 10; /* old style read */
1599 		if ((rdata->subreq.start >> 32) > 0)  {
1600 			/* can not handle this big offset for old */
1601 			return smb_EIO(smb_eio_trace_read_too_far);
1602 		}
1603 	}
1604 
1605 	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1606 	if (rc < 0)
1607 		return rc;
1608 	in_len = rc;
1609 
1610 	smb->hdr.Pid = cpu_to_le16((__u16)rdata->req->pid);
1611 	smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->req->pid >> 16));
1612 
1613 	smb->AndXCommand = 0xFF;	/* none */
1614 	smb->Fid = rdata->req->cfile->fid.netfid;
1615 	smb->OffsetLow = cpu_to_le32(rdata->subreq.start & 0xFFFFFFFF);
1616 	if (wct == 12)
1617 		smb->OffsetHigh = cpu_to_le32(rdata->subreq.start >> 32);
1618 	smb->Remaining = 0;
1619 	smb->MaxCount = cpu_to_le16(rdata->subreq.len & 0xFFFF);
1620 	smb->MaxCountHigh = cpu_to_le32(rdata->subreq.len >> 16);
1621 	if (wct == 12)
1622 		smb->ByteCount = 0;
1623 	else {
1624 		/* old style read */
1625 		struct smb_com_readx_req *smbr =
1626 			(struct smb_com_readx_req *)smb;
1627 		smbr->ByteCount = 0;
1628 	}
1629 
1630 	/* 4 for RFC1001 length + 1 for BCC */
1631 	rdata->iov[0].iov_base = smb;
1632 	rdata->iov[0].iov_len = in_len;
1633 
1634 	trace_smb3_read_enter(rdata->rreq->debug_id,
1635 			      rdata->subreq.debug_index,
1636 			      rdata->xid,
1637 			      rdata->req->cfile->fid.netfid,
1638 			      tcon->tid, tcon->ses->Suid,
1639 			      rdata->subreq.start, rdata->subreq.len);
1640 
1641 	rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1642 			     cifs_readv_callback, NULL, rdata, 0, NULL);
1643 
1644 	if (rc == 0)
1645 		cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1646 	cifs_small_buf_release(smb);
1647 	return rc;
1648 }
1649 
1650 int
CIFSSMBRead(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,char ** buf,int * pbuf_type)1651 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1652 	    unsigned int *nbytes, char **buf, int *pbuf_type)
1653 {
1654 	int rc = -EACCES;
1655 	READ_REQ *pSMB = NULL;
1656 	READ_RSP *pSMBr = NULL;
1657 	char *pReadData = NULL;
1658 	int wct;
1659 	int resp_buf_type = 0;
1660 	struct kvec iov[1];
1661 	struct kvec rsp_iov;
1662 	__u32 pid = io_parms->pid;
1663 	__u16 netfid = io_parms->netfid;
1664 	__u64 offset = io_parms->offset;
1665 	struct cifs_tcon *tcon = io_parms->tcon;
1666 	unsigned int in_len;
1667 	unsigned int count = io_parms->length;
1668 
1669 	cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1670 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1671 		wct = 12;
1672 	else {
1673 		wct = 10; /* old style read */
1674 		if ((offset >> 32) > 0)  {
1675 			/* can not handle this big offset for old */
1676 			return smb_EIO(smb_eio_trace_read_too_far);
1677 		}
1678 	}
1679 
1680 	*nbytes = 0;
1681 	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1682 	if (rc < 0)
1683 		return rc;
1684 	in_len = rc;
1685 
1686 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1687 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1688 
1689 	/* tcon and ses pointer are checked in smb_init */
1690 	if (!tcon->ses->server) {
1691 		cifs_small_buf_release(pSMB);
1692 		return -ECONNABORTED;
1693 	}
1694 
1695 	pSMB->AndXCommand = 0xFF;       /* none */
1696 	pSMB->Fid = netfid;
1697 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1698 	if (wct == 12)
1699 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1700 
1701 	pSMB->Remaining = 0;
1702 	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1703 	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1704 	if (wct == 12)
1705 		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1706 	else {
1707 		/* old style read */
1708 		struct smb_com_readx_req *pSMBW =
1709 			(struct smb_com_readx_req *)pSMB;
1710 		pSMBW->ByteCount = 0;
1711 	}
1712 
1713 	iov[0].iov_base = (char *)pSMB;
1714 	iov[0].iov_len = in_len;
1715 	rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1716 			  CIFS_LOG_ERROR, &rsp_iov);
1717 	cifs_small_buf_release(pSMB);
1718 	cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1719 	pSMBr = (READ_RSP *)rsp_iov.iov_base;
1720 	if (rc) {
1721 		cifs_dbg(VFS, "Send error in read = %d\n", rc);
1722 	} else {
1723 		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1724 		data_length = data_length << 16;
1725 		data_length += le16_to_cpu(pSMBr->DataLength);
1726 		*nbytes = data_length;
1727 
1728 		/*check that DataLength would not go beyond end of SMB */
1729 		if ((data_length > CIFSMaxBufSize)
1730 				|| (data_length > count)) {
1731 			cifs_dbg(FYI, "bad length %d for count %d\n",
1732 				 data_length, count);
1733 			rc = smb_EIO2(smb_eio_trace_read_overlarge,
1734 				      data_length, count);
1735 			*nbytes = 0;
1736 		} else {
1737 			pReadData = (char *) (&pSMBr->hdr.Protocol) +
1738 					le16_to_cpu(pSMBr->DataOffset);
1739 /*			if (rc = copy_to_user(buf, pReadData, data_length)) {
1740 				cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1741 				rc = -EFAULT;
1742 			}*/ /* can not use copy_to_user when using page cache*/
1743 			if (*buf)
1744 				memcpy(*buf, pReadData, data_length);
1745 		}
1746 	}
1747 
1748 	if (*buf) {
1749 		free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1750 	} else if (resp_buf_type != CIFS_NO_BUFFER) {
1751 		/* return buffer to caller to free */
1752 		*buf = rsp_iov.iov_base;
1753 		if (resp_buf_type == CIFS_SMALL_BUFFER)
1754 			*pbuf_type = CIFS_SMALL_BUFFER;
1755 		else if (resp_buf_type == CIFS_LARGE_BUFFER)
1756 			*pbuf_type = CIFS_LARGE_BUFFER;
1757 	} /* else no valid buffer on return - leave as null */
1758 
1759 	/* Note: On -EAGAIN error only caller can retry on handle based calls
1760 		since file handle passed in no longer valid */
1761 	return rc;
1762 }
1763 
1764 
1765 int
CIFSSMBWrite(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,const char * buf)1766 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1767 	     unsigned int *nbytes, const char *buf)
1768 {
1769 	int rc = -EACCES;
1770 	WRITE_REQ *pSMB = NULL;
1771 	WRITE_RSP *pSMBr = NULL;
1772 	int bytes_returned, wct;
1773 	__u32 bytes_sent;
1774 	__u16 byte_count;
1775 	__u32 pid = io_parms->pid;
1776 	__u16 netfid = io_parms->netfid;
1777 	__u64 offset = io_parms->offset;
1778 	struct cifs_tcon *tcon = io_parms->tcon;
1779 	unsigned int count = io_parms->length, in_len;
1780 
1781 	*nbytes = 0;
1782 
1783 	/* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1784 	if (tcon->ses == NULL)
1785 		return -ECONNABORTED;
1786 
1787 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1788 		wct = 14;
1789 	else {
1790 		wct = 12;
1791 		if ((offset >> 32) > 0) {
1792 			/* can not handle big offset for old srv */
1793 			return smb_EIO(smb_eio_trace_write_too_far);
1794 		}
1795 	}
1796 
1797 	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1798 		      (void **) &pSMBr);
1799 	if (rc < 0)
1800 		return rc;
1801 	in_len = rc;
1802 
1803 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1804 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1805 
1806 	/* tcon and ses pointer are checked in smb_init */
1807 	if (!tcon->ses->server) {
1808 		cifs_buf_release(pSMB);
1809 		return -ECONNABORTED;
1810 	}
1811 
1812 	pSMB->AndXCommand = 0xFF;	/* none */
1813 	pSMB->Fid = netfid;
1814 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1815 	if (wct == 14)
1816 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1817 
1818 	pSMB->Reserved = 0xFFFFFFFF;
1819 	pSMB->WriteMode = 0;
1820 	pSMB->Remaining = 0;
1821 
1822 	/* Can increase buffer size if buffer is big enough in some cases ie we
1823 	can send more if LARGE_WRITE_X capability returned by the server and if
1824 	our buffer is big enough or if we convert to iovecs on socket writes
1825 	and eliminate the copy to the CIFS buffer */
1826 	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1827 		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1828 	} else {
1829 		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1830 			 & ~0xFF;
1831 	}
1832 
1833 	if (bytes_sent > count)
1834 		bytes_sent = count;
1835 	pSMB->DataOffset =
1836 		cpu_to_le16(offsetof(struct smb_com_write_req, Data));
1837 	if (buf)
1838 		memcpy(pSMB->Data, buf, bytes_sent);
1839 	else if (count != 0) {
1840 		/* No buffer */
1841 		cifs_buf_release(pSMB);
1842 		return -EINVAL;
1843 	} /* else setting file size with write of zero bytes */
1844 	if (wct == 14)
1845 		byte_count = bytes_sent + 1; /* pad */
1846 	else /* wct == 12 */
1847 		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1848 
1849 	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1850 	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1851 	in_len += byte_count;
1852 
1853 	if (wct == 14)
1854 		pSMB->ByteCount = cpu_to_le16(byte_count);
1855 	else { /* old style write has byte count 4 bytes earlier
1856 		  so 4 bytes pad  */
1857 		struct smb_com_writex_req *pSMBW =
1858 			(struct smb_com_writex_req *)pSMB;
1859 		pSMBW->ByteCount = cpu_to_le16(byte_count);
1860 	}
1861 
1862 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
1863 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1864 	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1865 	if (rc) {
1866 		cifs_dbg(FYI, "Send error in write = %d\n", rc);
1867 	} else {
1868 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
1869 		*nbytes = (*nbytes) << 16;
1870 		*nbytes += le16_to_cpu(pSMBr->Count);
1871 
1872 		/*
1873 		 * Mask off high 16 bits when bytes written as returned by the
1874 		 * server is greater than bytes requested by the client. Some
1875 		 * OS/2 servers are known to set incorrect CountHigh values.
1876 		 */
1877 		if (*nbytes > count)
1878 			*nbytes &= 0xFFFF;
1879 	}
1880 
1881 	cifs_buf_release(pSMB);
1882 
1883 	/* Note: On -EAGAIN error only caller can retry on handle based calls
1884 		since file handle passed in no longer valid */
1885 
1886 	return rc;
1887 }
1888 
1889 /*
1890  * Check the mid_state and signature on received buffer (if any), and queue the
1891  * workqueue completion task.
1892  */
1893 static void
cifs_writev_callback(struct TCP_Server_Info * server,struct mid_q_entry * mid)1894 cifs_writev_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1895 {
1896 	struct cifs_io_subrequest *wdata = mid->callback_data;
1897 	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
1898 	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1899 	struct cifs_credits credits = {
1900 		.value = 1,
1901 		.instance = 0,
1902 		.rreq_debug_id = wdata->rreq->debug_id,
1903 		.rreq_debug_index = wdata->subreq.debug_index,
1904 	};
1905 	ssize_t result;
1906 	size_t written;
1907 
1908 	switch (mid->mid_state) {
1909 	case MID_RESPONSE_RECEIVED:
1910 		result = cifs_check_receive(mid, tcon->ses->server, 0);
1911 		if (result != 0)
1912 			break;
1913 
1914 		written = le16_to_cpu(smb->CountHigh);
1915 		written <<= 16;
1916 		written += le16_to_cpu(smb->Count);
1917 		/*
1918 		 * Mask off high 16 bits when bytes written as returned
1919 		 * by the server is greater than bytes requested by the
1920 		 * client. OS/2 servers are known to set incorrect
1921 		 * CountHigh values.
1922 		 */
1923 		if (written > wdata->subreq.len)
1924 			written &= 0xFFFF;
1925 
1926 		if (written < wdata->subreq.len) {
1927 			result = -ENOSPC;
1928 		} else {
1929 			result = written;
1930 			if (written > 0)
1931 				__set_bit(NETFS_SREQ_MADE_PROGRESS, &wdata->subreq.flags);
1932 		}
1933 		break;
1934 	case MID_REQUEST_SUBMITTED:
1935 		trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_req_submitted);
1936 		__set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags);
1937 		result = -EAGAIN;
1938 		break;
1939 	case MID_RETRY_NEEDED:
1940 		trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_retry_needed);
1941 		__set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags);
1942 		result = -EAGAIN;
1943 		break;
1944 	case MID_RESPONSE_MALFORMED:
1945 		trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_malformed);
1946 		result = smb_EIO(smb_eio_trace_write_rsp_malformed);
1947 		break;
1948 	default:
1949 		trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_unknown);
1950 		result = smb_EIO1(smb_eio_trace_write_mid_state_unknown,
1951 				  mid->mid_state);
1952 		break;
1953 	}
1954 
1955 	trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index,
1956 			      wdata->credits.value,
1957 			      server->credits, server->in_flight,
1958 			      0, cifs_trace_rw_credits_write_response_clear);
1959 	wdata->credits.value = 0;
1960 	cifs_write_subrequest_terminated(wdata, result);
1961 	release_mid(server, mid);
1962 	trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index, 0,
1963 			      server->credits, server->in_flight,
1964 			      credits.value, cifs_trace_rw_credits_write_response_add);
1965 	add_credits(tcon->ses->server, &credits, 0);
1966 }
1967 
1968 /* cifs_async_writev - send an async write, and set up mid to handle result */
1969 void
cifs_async_writev(struct cifs_io_subrequest * wdata)1970 cifs_async_writev(struct cifs_io_subrequest *wdata)
1971 {
1972 	int rc = -EACCES;
1973 	WRITE_REQ *req = NULL;
1974 	int wct;
1975 	struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
1976 	struct kvec iov[1];
1977 	struct smb_rqst rqst = { };
1978 	unsigned int in_len;
1979 
1980 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1981 		wct = 14;
1982 	} else {
1983 		wct = 12;
1984 		if (wdata->subreq.start >> 32 > 0) {
1985 			/* can not handle big offset for old srv */
1986 			rc = smb_EIO(smb_eio_trace_write_too_far);
1987 			goto out;
1988 		}
1989 	}
1990 
1991 	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&req);
1992 	if (rc < 0)
1993 		goto async_writev_out;
1994 	in_len = rc;
1995 
1996 	req->hdr.Pid = cpu_to_le16((__u16)wdata->req->pid);
1997 	req->hdr.PidHigh = cpu_to_le16((__u16)(wdata->req->pid >> 16));
1998 
1999 	req->AndXCommand = 0xFF;	/* none */
2000 	req->Fid = wdata->req->cfile->fid.netfid;
2001 	req->OffsetLow = cpu_to_le32(wdata->subreq.start & 0xFFFFFFFF);
2002 	if (wct == 14)
2003 		req->OffsetHigh = cpu_to_le32(wdata->subreq.start >> 32);
2004 	req->Reserved = 0xFFFFFFFF;
2005 	req->WriteMode = 0;
2006 	req->Remaining = 0;
2007 
2008 	req->DataOffset =
2009 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data));
2010 
2011 	iov[0].iov_base = req;
2012 	iov[0].iov_len = in_len + 1; /* +1 for BCC */
2013 
2014 	rqst.rq_iov = iov;
2015 	rqst.rq_nvec = 1;
2016 	rqst.rq_iter = wdata->subreq.io_iter;
2017 
2018 	cifs_dbg(FYI, "async write at %llu %zu bytes\n",
2019 		 wdata->subreq.start, wdata->subreq.len);
2020 
2021 	req->DataLengthLow = cpu_to_le16(wdata->subreq.len & 0xFFFF);
2022 	req->DataLengthHigh = cpu_to_le16(wdata->subreq.len >> 16);
2023 
2024 	if (wct == 14) {
2025 		in_len += wdata->subreq.len + 1;
2026 		put_bcc(wdata->subreq.len + 1, &req->hdr);
2027 	} else {
2028 		/* wct == 12 */
2029 		struct smb_com_writex_req *reqw =
2030 				(struct smb_com_writex_req *)req;
2031 		in_len += wdata->subreq.len + 5;
2032 		put_bcc(wdata->subreq.len + 5, &reqw->hdr);
2033 		iov[0].iov_len += 4; /* pad bigger by four bytes */
2034 	}
2035 
2036 	rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2037 			     cifs_writev_callback, NULL, wdata, 0, NULL);
2038 	/* Can't touch wdata if rc == 0 */
2039 	if (rc == 0)
2040 		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2041 
2042 async_writev_out:
2043 	cifs_small_buf_release(req);
2044 out:
2045 	if (rc) {
2046 		add_credits_and_wake_if(wdata->server, &wdata->credits, 0);
2047 		cifs_write_subrequest_terminated(wdata, rc);
2048 	}
2049 }
2050 
2051 int
CIFSSMBWrite2(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,struct kvec * iov,int n_vec)2052 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2053 	      unsigned int *nbytes, struct kvec *iov, int n_vec)
2054 {
2055 	int rc;
2056 	WRITE_REQ *pSMB = NULL;
2057 	int wct;
2058 	int smb_hdr_len;
2059 	int resp_buf_type = 0;
2060 	__u32 pid = io_parms->pid;
2061 	__u16 netfid = io_parms->netfid;
2062 	__u64 offset = io_parms->offset;
2063 	struct cifs_tcon *tcon = io_parms->tcon;
2064 	unsigned int count = io_parms->length;
2065 	struct kvec rsp_iov;
2066 	unsigned int in_len;
2067 
2068 	*nbytes = 0;
2069 
2070 	cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2071 
2072 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2073 		wct = 14;
2074 	} else {
2075 		wct = 12;
2076 		if ((offset >> 32) > 0) {
2077 			/* can not handle big offset for old srv */
2078 			return smb_EIO(smb_eio_trace_write_too_far);
2079 		}
2080 	}
2081 	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2082 	if (rc < 0)
2083 		return rc;
2084 	in_len = rc;
2085 
2086 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2087 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2088 
2089 	/* tcon and ses pointer are checked in smb_init */
2090 	if (!tcon->ses->server) {
2091 		cifs_small_buf_release(pSMB);
2092 		return -ECONNABORTED;
2093 	}
2094 
2095 	pSMB->AndXCommand = 0xFF;	/* none */
2096 	pSMB->Fid = netfid;
2097 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2098 	if (wct == 14)
2099 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2100 	pSMB->Reserved = 0xFFFFFFFF;
2101 	pSMB->WriteMode = 0;
2102 	pSMB->Remaining = 0;
2103 
2104 	pSMB->DataOffset =
2105 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data));
2106 
2107 	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2108 	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2109 	/* header + 1 byte pad */
2110 	smb_hdr_len = in_len + 1;
2111 	if (wct == 14)
2112 		in_len += count + 1;
2113 	else /* wct == 12 */
2114 		in_len += count + 5; /* smb data starts later */
2115 	if (wct == 14)
2116 		pSMB->ByteCount = cpu_to_le16(count + 1);
2117 	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2118 		struct smb_com_writex_req *pSMBW =
2119 				(struct smb_com_writex_req *)pSMB;
2120 		pSMBW->ByteCount = cpu_to_le16(count + 5);
2121 	}
2122 	iov[0].iov_base = pSMB;
2123 	if (wct == 14)
2124 		iov[0].iov_len = smb_hdr_len + 4;
2125 	else /* wct == 12 pad bigger by four bytes */
2126 		iov[0].iov_len = smb_hdr_len + 8;
2127 
2128 	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
2129 			  &rsp_iov);
2130 	cifs_small_buf_release(pSMB);
2131 	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2132 	if (rc) {
2133 		cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2134 	} else if (resp_buf_type == 0) {
2135 		/* presumably this can not happen, but best to be safe */
2136 		rc = smb_EIO1(smb_eio_trace_write_bad_buf_type, resp_buf_type);
2137 	} else {
2138 		WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
2139 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
2140 		*nbytes = (*nbytes) << 16;
2141 		*nbytes += le16_to_cpu(pSMBr->Count);
2142 
2143 		/*
2144 		 * Mask off high 16 bits when bytes written as returned by the
2145 		 * server is greater than bytes requested by the client. OS/2
2146 		 * servers are known to set incorrect CountHigh values.
2147 		 */
2148 		if (*nbytes > count)
2149 			*nbytes &= 0xFFFF;
2150 	}
2151 
2152 	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2153 
2154 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2155 		since file handle passed in no longer valid */
2156 
2157 	return rc;
2158 }
2159 
cifs_lockv(const unsigned int xid,struct cifs_tcon * tcon,const __u16 netfid,const __u8 lock_type,const __u32 num_unlock,const __u32 num_lock,LOCKING_ANDX_RANGE * buf)2160 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2161 	       const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2162 	       const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2163 {
2164 	int rc = 0;
2165 	LOCK_REQ *pSMB = NULL;
2166 	struct kvec iov[2];
2167 	struct kvec rsp_iov;
2168 	unsigned int in_len;
2169 	int resp_buf_type;
2170 	__u16 count;
2171 
2172 	cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2173 		 num_lock, num_unlock);
2174 
2175 	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2176 	if (rc < 0)
2177 		return rc;
2178 	in_len = rc;
2179 
2180 	pSMB->Timeout = 0;
2181 	pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2182 	pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2183 	pSMB->LockType = lock_type;
2184 	pSMB->AndXCommand = 0xFF; /* none */
2185 	pSMB->Fid = netfid; /* netfid stays le */
2186 
2187 	count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2188 	in_len += count;
2189 	pSMB->ByteCount = cpu_to_le16(count);
2190 
2191 	iov[0].iov_base = (char *)pSMB;
2192 	iov[0].iov_len = in_len -
2193 			 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2194 	iov[1].iov_base = (char *)buf;
2195 	iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2196 
2197 	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2198 	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
2199 			  CIFS_NO_RSP_BUF, &rsp_iov);
2200 	cifs_small_buf_release(pSMB);
2201 	if (rc)
2202 		cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2203 
2204 	return rc;
2205 }
2206 
2207 int
CIFSSMBLock(const unsigned int xid,struct cifs_tcon * tcon,const __u16 smb_file_id,const __u32 netpid,const __u64 len,const __u64 offset,const __u32 numUnlock,const __u32 numLock,const __u8 lockType,const bool waitFlag,const __u8 oplock_level)2208 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2209 	    const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2210 	    const __u64 offset, const __u32 numUnlock,
2211 	    const __u32 numLock, const __u8 lockType,
2212 	    const bool waitFlag, const __u8 oplock_level)
2213 {
2214 	int rc = 0;
2215 	LOCK_REQ *pSMB = NULL;
2216 /*	LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2217 	unsigned int in_len;
2218 	int bytes_returned;
2219 	int flags = CIFS_WINDOWS_LOCK | CIFS_INTERRUPTIBLE_WAIT;
2220 	__u16 count;
2221 
2222 	cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2223 		 (int)waitFlag, numLock);
2224 	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2225 
2226 	if (rc < 0)
2227 		return rc;
2228 	in_len = rc;
2229 
2230 	if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2231 		/* no response expected */
2232 		flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
2233 		pSMB->Timeout = 0;
2234 	} else if (waitFlag) {
2235 		flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2236 		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2237 	} else {
2238 		pSMB->Timeout = 0;
2239 	}
2240 
2241 	pSMB->NumberOfLocks = cpu_to_le16(numLock);
2242 	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2243 	pSMB->LockType = lockType;
2244 	pSMB->OplockLevel = oplock_level;
2245 	pSMB->AndXCommand = 0xFF;	/* none */
2246 	pSMB->Fid = smb_file_id; /* netfid stays le */
2247 
2248 	if ((numLock != 0) || (numUnlock != 0)) {
2249 		pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2250 		/* BB where to store pid high? */
2251 		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2252 		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2253 		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2254 		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2255 		count = sizeof(LOCKING_ANDX_RANGE);
2256 	} else {
2257 		/* oplock break */
2258 		count = 0;
2259 	}
2260 	in_len += count;
2261 	pSMB->ByteCount = cpu_to_le16(count);
2262 
2263 	if (waitFlag)
2264 		rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2265 				 (struct smb_hdr *) pSMB, &bytes_returned,
2266 				 flags);
2267 	else
2268 		rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, in_len, flags);
2269 	cifs_small_buf_release(pSMB);
2270 	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2271 	if (rc)
2272 		cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2273 
2274 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2275 	since file handle passed in no longer valid */
2276 	return rc;
2277 }
2278 
2279 int
CIFSSMBPosixLock(const unsigned int xid,struct cifs_tcon * tcon,const __u16 smb_file_id,const __u32 netpid,const loff_t start_offset,const __u64 len,struct file_lock * pLockData,const __u16 lock_type,const bool waitFlag)2280 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2281 		const __u16 smb_file_id, const __u32 netpid,
2282 		const loff_t start_offset, const __u64 len,
2283 		struct file_lock *pLockData, const __u16 lock_type,
2284 		const bool waitFlag)
2285 {
2286 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2287 	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2288 	struct cifs_posix_lock *parm_data;
2289 	unsigned int in_len;
2290 	int rc = 0;
2291 	int sr_flags = CIFS_INTERRUPTIBLE_WAIT;
2292 	int bytes_returned = 0;
2293 	int resp_buf_type = 0;
2294 	__u16 params, param_offset, offset, byte_count, count;
2295 	struct kvec iov[1];
2296 	struct kvec rsp_iov;
2297 
2298 	cifs_dbg(FYI, "Posix Lock\n");
2299 
2300 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2301 	if (rc < 0)
2302 		return rc;
2303 	in_len = rc;
2304 
2305 	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2306 
2307 	params = 6;
2308 	pSMB->MaxSetupCount = 0;
2309 	pSMB->Reserved = 0;
2310 	pSMB->Flags = 0;
2311 	pSMB->Reserved2 = 0;
2312 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
2313 	offset = param_offset + params;
2314 
2315 	count = sizeof(struct cifs_posix_lock);
2316 	pSMB->MaxParameterCount = cpu_to_le16(2);
2317 	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2318 	pSMB->SetupCount = 1;
2319 	pSMB->Reserved3 = 0;
2320 	if (pLockData)
2321 		pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2322 	else
2323 		pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2324 	byte_count = 3 /* pad */  + params + count;
2325 	pSMB->DataCount = cpu_to_le16(count);
2326 	pSMB->ParameterCount = cpu_to_le16(params);
2327 	pSMB->TotalDataCount = pSMB->DataCount;
2328 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2329 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2330 	parm_data = (struct cifs_posix_lock *)(((char *)pSMB) + offset);
2331 
2332 	parm_data->lock_type = cpu_to_le16(lock_type);
2333 	if (waitFlag) {
2334 		sr_flags |= CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2335 		parm_data->lock_flags = cpu_to_le16(1);
2336 		pSMB->Timeout = cpu_to_le32(-1);
2337 	} else
2338 		pSMB->Timeout = 0;
2339 
2340 	parm_data->pid = cpu_to_le32(netpid);
2341 	parm_data->start = cpu_to_le64(start_offset);
2342 	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2343 
2344 	pSMB->DataOffset = cpu_to_le16(offset);
2345 	pSMB->Fid = smb_file_id;
2346 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2347 	pSMB->Reserved4 = 0;
2348 	in_len += byte_count;
2349 	pSMB->ByteCount = cpu_to_le16(byte_count);
2350 	if (waitFlag) {
2351 		rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2352 				 (struct smb_hdr *) pSMBr, &bytes_returned,
2353 				 sr_flags);
2354 	} else {
2355 		iov[0].iov_base = (char *)pSMB;
2356 		iov[0].iov_len = in_len;
2357 		rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2358 				&resp_buf_type, sr_flags, &rsp_iov);
2359 		pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2360 	}
2361 	cifs_small_buf_release(pSMB);
2362 
2363 	if (rc) {
2364 		cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2365 	} else if (pLockData) {
2366 		/* lock structure can be returned on get */
2367 		__u16 data_offset;
2368 		__u16 data_count;
2369 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2370 
2371 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2372 			rc = smb_EIO2(smb_eio_trace_lock_bcc_too_small,
2373 				      get_bcc(&pSMBr->hdr), sizeof(*parm_data));
2374 			goto plk_err_exit;
2375 		}
2376 		data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2377 		data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2378 		if (data_count < sizeof(struct cifs_posix_lock)) {
2379 			rc = smb_EIO2(smb_eio_trace_lock_data_too_small,
2380 				      data_count, sizeof(struct cifs_posix_lock));
2381 			goto plk_err_exit;
2382 		}
2383 		parm_data = (struct cifs_posix_lock *)
2384 			((char *)&pSMBr->hdr.Protocol + data_offset);
2385 		if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2386 			pLockData->c.flc_type = F_UNLCK;
2387 		else {
2388 			if (parm_data->lock_type ==
2389 					cpu_to_le16(CIFS_RDLCK))
2390 				pLockData->c.flc_type = F_RDLCK;
2391 			else if (parm_data->lock_type ==
2392 					cpu_to_le16(CIFS_WRLCK))
2393 				pLockData->c.flc_type = F_WRLCK;
2394 
2395 			pLockData->fl_start = le64_to_cpu(parm_data->start);
2396 			pLockData->fl_end = pLockData->fl_start +
2397 				(le64_to_cpu(parm_data->length) ?
2398 				 le64_to_cpu(parm_data->length) - 1 : 0);
2399 			pLockData->c.flc_pid = -le32_to_cpu(parm_data->pid);
2400 		}
2401 	}
2402 
2403 plk_err_exit:
2404 	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2405 
2406 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2407 	   since file handle passed in no longer valid */
2408 
2409 	return rc;
2410 }
2411 
2412 
2413 int
CIFSSMBClose(const unsigned int xid,struct cifs_tcon * tcon,int smb_file_id)2414 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2415 {
2416 	int rc = 0;
2417 	CLOSE_REQ *pSMB = NULL;
2418 	unsigned int in_len;
2419 
2420 	cifs_dbg(FYI, "In CIFSSMBClose\n");
2421 
2422 /* do not retry on dead session on close */
2423 	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2424 	if (rc == -EAGAIN)
2425 		return 0;
2426 	if (rc < 0)
2427 		return rc;
2428 	in_len = rc;
2429 
2430 	pSMB->FileID = (__u16) smb_file_id;
2431 	pSMB->LastWriteTime = 0xFFFFFFFF;
2432 	pSMB->ByteCount = 0;
2433 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
2434 	cifs_small_buf_release(pSMB);
2435 	cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2436 	if (rc) {
2437 		if (rc != -EINTR) {
2438 			/* EINTR is expected when user ctl-c to kill app */
2439 			cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2440 		}
2441 	}
2442 
2443 	/* Since session is dead, file will be closed on server already */
2444 	if (rc == -EAGAIN)
2445 		rc = 0;
2446 
2447 	return rc;
2448 }
2449 
2450 int
CIFSSMBFlush(const unsigned int xid,struct cifs_tcon * tcon,int smb_file_id)2451 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2452 {
2453 	int rc = 0;
2454 	FLUSH_REQ *pSMB = NULL;
2455 	unsigned int in_len;
2456 
2457 	cifs_dbg(FYI, "In CIFSSMBFlush\n");
2458 
2459 	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2460 	if (rc < 0)
2461 		return rc;
2462 	in_len = rc;
2463 
2464 	pSMB->FileID = (__u16) smb_file_id;
2465 	pSMB->ByteCount = 0;
2466 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
2467 	cifs_small_buf_release(pSMB);
2468 	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2469 	if (rc)
2470 		cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2471 
2472 	return rc;
2473 }
2474 
CIFSSMBRename(const unsigned int xid,struct cifs_tcon * tcon,struct dentry * source_dentry,const char * from_name,const char * to_name,struct cifs_sb_info * cifs_sb)2475 int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2476 		  struct dentry *source_dentry,
2477 		  const char *from_name, const char *to_name,
2478 		  struct cifs_sb_info *cifs_sb)
2479 {
2480 	int rc = 0;
2481 	RENAME_REQ *pSMB = NULL;
2482 	RENAME_RSP *pSMBr = NULL;
2483 	unsigned int in_len;
2484 	int bytes_returned;
2485 	int name_len, name_len2;
2486 	__u16 count;
2487 	int remap = cifs_remap(cifs_sb);
2488 
2489 	cifs_dbg(FYI, "In CIFSSMBRename\n");
2490 renameRetry:
2491 	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2492 		      (void **) &pSMBr);
2493 	if (rc < 0)
2494 		return rc;
2495 	in_len = rc;
2496 
2497 	pSMB->BufferFormat = 0x04;
2498 	pSMB->SearchAttributes =
2499 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2500 			ATTR_DIRECTORY);
2501 
2502 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2503 		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2504 					      from_name, PATH_MAX,
2505 					      cifs_sb->local_nls, remap);
2506 		name_len++;	/* trailing null */
2507 		name_len *= 2;
2508 		pSMB->OldFileName[name_len] = 0x04;	/* pad */
2509 	/* protocol requires ASCII signature byte on Unicode string */
2510 		pSMB->OldFileName[name_len + 1] = 0x00;
2511 		name_len2 =
2512 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2513 				       to_name, PATH_MAX, cifs_sb->local_nls,
2514 				       remap);
2515 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2516 		name_len2 *= 2;	/* convert to bytes */
2517 	} else {
2518 		name_len = copy_path_name(pSMB->OldFileName, from_name);
2519 		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2520 		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2521 		name_len2++;	/* signature byte */
2522 	}
2523 
2524 	count = 1 /* 1st signature byte */  + name_len + name_len2;
2525 	in_len += count;
2526 	pSMB->ByteCount = cpu_to_le16(count);
2527 
2528 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2529 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2530 	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2531 	if (rc)
2532 		cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2533 
2534 	cifs_buf_release(pSMB);
2535 
2536 	if (rc == -EAGAIN)
2537 		goto renameRetry;
2538 
2539 	return rc;
2540 }
2541 
CIFSSMBRenameOpenFile(const unsigned int xid,struct cifs_tcon * pTcon,int netfid,const char * target_name,const struct nls_table * nls_codepage,int remap)2542 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2543 		int netfid, const char *target_name,
2544 		const struct nls_table *nls_codepage, int remap)
2545 {
2546 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2547 	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2548 	struct set_file_rename *rename_info;
2549 	unsigned int in_len;
2550 	char *data_offset;
2551 	char dummy_string[30];
2552 	int rc = 0;
2553 	int bytes_returned = 0;
2554 	int len_of_str;
2555 	__u16 params, param_offset, offset, count, byte_count;
2556 
2557 	cifs_dbg(FYI, "Rename to File by handle\n");
2558 	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2559 			(void **) &pSMBr);
2560 	if (rc < 0)
2561 		return rc;
2562 	in_len = rc;
2563 
2564 	params = 6;
2565 	pSMB->MaxSetupCount = 0;
2566 	pSMB->Reserved = 0;
2567 	pSMB->Flags = 0;
2568 	pSMB->Timeout = 0;
2569 	pSMB->Reserved2 = 0;
2570 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
2571 	offset = param_offset + params;
2572 
2573 	data_offset = (char *)(pSMB) + offset;
2574 	rename_info = (struct set_file_rename *) data_offset;
2575 	pSMB->MaxParameterCount = cpu_to_le16(2);
2576 	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2577 	pSMB->SetupCount = 1;
2578 	pSMB->Reserved3 = 0;
2579 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2580 	byte_count = 3 /* pad */  + params;
2581 	pSMB->ParameterCount = cpu_to_le16(params);
2582 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2583 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2584 	pSMB->DataOffset = cpu_to_le16(offset);
2585 	/* construct random name ".cifs_tmp<inodenum><mid>" */
2586 	rename_info->overwrite = cpu_to_le32(1);
2587 	rename_info->root_fid  = 0;
2588 	/* unicode only call */
2589 	if (target_name == NULL) {
2590 		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2591 		len_of_str =
2592 			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2593 					dummy_string, 24, nls_codepage, remap);
2594 	} else {
2595 		len_of_str =
2596 			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2597 					target_name, PATH_MAX, nls_codepage,
2598 					remap);
2599 	}
2600 	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2601 	count = sizeof(struct set_file_rename) + (2 * len_of_str);
2602 	byte_count += count;
2603 	pSMB->DataCount = cpu_to_le16(count);
2604 	pSMB->TotalDataCount = pSMB->DataCount;
2605 	pSMB->Fid = netfid;
2606 	pSMB->InformationLevel =
2607 		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2608 	pSMB->Reserved4 = 0;
2609 	in_len += byte_count;
2610 	pSMB->ByteCount = cpu_to_le16(byte_count);
2611 	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, in_len,
2612 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2613 	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2614 	if (rc)
2615 		cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2616 			 rc);
2617 
2618 	cifs_buf_release(pSMB);
2619 
2620 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2621 		since file handle passed in no longer valid */
2622 
2623 	return rc;
2624 }
2625 
2626 int
CIFSUnixCreateSymLink(const unsigned int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2627 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2628 		      const char *fromName, const char *toName,
2629 		      const struct nls_table *nls_codepage, int remap)
2630 {
2631 	TRANSACTION2_SPI_REQ *pSMB = NULL;
2632 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2633 	unsigned int in_len;
2634 	char *data_offset;
2635 	int name_len;
2636 	int name_len_target;
2637 	int rc = 0;
2638 	int bytes_returned = 0;
2639 	__u16 params, param_offset, offset, byte_count;
2640 
2641 	cifs_dbg(FYI, "In Symlink Unix style\n");
2642 createSymLinkRetry:
2643 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2644 		      (void **) &pSMBr);
2645 	if (rc < 0)
2646 		return rc;
2647 	in_len = rc;
2648 
2649 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2650 		name_len =
2651 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2652 				/* find define for this maxpathcomponent */
2653 					PATH_MAX, nls_codepage, remap);
2654 		name_len++;	/* trailing null */
2655 		name_len *= 2;
2656 
2657 	} else {
2658 		name_len = copy_path_name(pSMB->FileName, fromName);
2659 	}
2660 	params = 6 + name_len;
2661 	pSMB->MaxSetupCount = 0;
2662 	pSMB->Reserved = 0;
2663 	pSMB->Flags = 0;
2664 	pSMB->Timeout = 0;
2665 	pSMB->Reserved2 = 0;
2666 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
2667 				InformationLevel);
2668 	offset = param_offset + params;
2669 
2670 	data_offset = (char *)pSMB + offset;
2671 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2672 		name_len_target =
2673 		    cifsConvertToUTF16((__le16 *) data_offset, toName,
2674 				/* find define for this maxpathcomponent */
2675 					PATH_MAX, nls_codepage, remap);
2676 		name_len_target++;	/* trailing null */
2677 		name_len_target *= 2;
2678 	} else {
2679 		name_len_target = copy_path_name(data_offset, toName);
2680 	}
2681 
2682 	pSMB->MaxParameterCount = cpu_to_le16(2);
2683 	/* BB find exact max on data count below from sess */
2684 	pSMB->MaxDataCount = cpu_to_le16(1000);
2685 	pSMB->SetupCount = 1;
2686 	pSMB->Reserved3 = 0;
2687 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2688 	byte_count = 3 /* pad */  + params + name_len_target;
2689 	pSMB->DataCount = cpu_to_le16(name_len_target);
2690 	pSMB->ParameterCount = cpu_to_le16(params);
2691 	pSMB->TotalDataCount = pSMB->DataCount;
2692 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2693 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2694 	pSMB->DataOffset = cpu_to_le16(offset);
2695 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2696 	pSMB->Reserved4 = 0;
2697 	in_len += byte_count;
2698 	pSMB->ByteCount = cpu_to_le16(byte_count);
2699 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2700 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2701 	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2702 	if (rc)
2703 		cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2704 			 rc);
2705 
2706 	cifs_buf_release(pSMB);
2707 
2708 	if (rc == -EAGAIN)
2709 		goto createSymLinkRetry;
2710 
2711 	return rc;
2712 }
2713 
2714 int
CIFSUnixCreateHardLink(const unsigned int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2715 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2716 		       const char *fromName, const char *toName,
2717 		       const struct nls_table *nls_codepage, int remap)
2718 {
2719 	TRANSACTION2_SPI_REQ *pSMB = NULL;
2720 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2721 	unsigned int in_len;
2722 	char *data_offset;
2723 	int name_len;
2724 	int name_len_target;
2725 	int rc = 0;
2726 	int bytes_returned = 0;
2727 	__u16 params, param_offset, offset, byte_count;
2728 
2729 	cifs_dbg(FYI, "In Create Hard link Unix style\n");
2730 createHardLinkRetry:
2731 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2732 		      (void **) &pSMBr);
2733 	if (rc < 0)
2734 		return rc;
2735 	in_len = rc;
2736 
2737 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2738 		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2739 					      PATH_MAX, nls_codepage, remap);
2740 		name_len++;	/* trailing null */
2741 		name_len *= 2;
2742 
2743 	} else {
2744 		name_len = copy_path_name(pSMB->FileName, toName);
2745 	}
2746 	params = 6 + name_len;
2747 	pSMB->MaxSetupCount = 0;
2748 	pSMB->Reserved = 0;
2749 	pSMB->Flags = 0;
2750 	pSMB->Timeout = 0;
2751 	pSMB->Reserved2 = 0;
2752 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
2753 				InformationLevel);
2754 	offset = param_offset + params;
2755 
2756 	data_offset = (char *)pSMB + offset;
2757 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2758 		name_len_target =
2759 		    cifsConvertToUTF16((__le16 *) data_offset, fromName,
2760 				       PATH_MAX, nls_codepage, remap);
2761 		name_len_target++;	/* trailing null */
2762 		name_len_target *= 2;
2763 	} else {
2764 		name_len_target = copy_path_name(data_offset, fromName);
2765 	}
2766 
2767 	pSMB->MaxParameterCount = cpu_to_le16(2);
2768 	/* BB find exact max on data count below from sess*/
2769 	pSMB->MaxDataCount = cpu_to_le16(1000);
2770 	pSMB->SetupCount = 1;
2771 	pSMB->Reserved3 = 0;
2772 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2773 	byte_count = 3 /* pad */  + params + name_len_target;
2774 	pSMB->ParameterCount = cpu_to_le16(params);
2775 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2776 	pSMB->DataCount = cpu_to_le16(name_len_target);
2777 	pSMB->TotalDataCount = pSMB->DataCount;
2778 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2779 	pSMB->DataOffset = cpu_to_le16(offset);
2780 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2781 	pSMB->Reserved4 = 0;
2782 	in_len += byte_count;
2783 	pSMB->ByteCount = cpu_to_le16(byte_count);
2784 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2785 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2786 	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2787 	if (rc)
2788 		cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2789 			 rc);
2790 
2791 	cifs_buf_release(pSMB);
2792 	if (rc == -EAGAIN)
2793 		goto createHardLinkRetry;
2794 
2795 	return rc;
2796 }
2797 
CIFSCreateHardLink(const unsigned int xid,struct cifs_tcon * tcon,struct dentry * source_dentry,const char * from_name,const char * to_name,struct cifs_sb_info * cifs_sb)2798 int CIFSCreateHardLink(const unsigned int xid,
2799 		       struct cifs_tcon *tcon,
2800 		       struct dentry *source_dentry,
2801 		       const char *from_name, const char *to_name,
2802 		       struct cifs_sb_info *cifs_sb)
2803 {
2804 	int rc = 0;
2805 	NT_RENAME_REQ *pSMB = NULL;
2806 	RENAME_RSP *pSMBr = NULL;
2807 	unsigned int in_len;
2808 	int bytes_returned;
2809 	int name_len, name_len2;
2810 	__u16 count;
2811 	int remap = cifs_remap(cifs_sb);
2812 
2813 	cifs_dbg(FYI, "In CIFSCreateHardLink\n");
2814 winCreateHardLinkRetry:
2815 
2816 	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2817 		      (void **) &pSMBr);
2818 	if (rc < 0)
2819 		return rc;
2820 	in_len = rc;
2821 
2822 	pSMB->SearchAttributes =
2823 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2824 			ATTR_DIRECTORY);
2825 	pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2826 	pSMB->ClusterCount = 0;
2827 
2828 	pSMB->BufferFormat = 0x04;
2829 
2830 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2831 		name_len =
2832 		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2833 				       PATH_MAX, cifs_sb->local_nls, remap);
2834 		name_len++;	/* trailing null */
2835 		name_len *= 2;
2836 
2837 		/* protocol specifies ASCII buffer format (0x04) for unicode */
2838 		pSMB->OldFileName[name_len] = 0x04;
2839 		pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2840 		name_len2 =
2841 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2842 				       to_name, PATH_MAX, cifs_sb->local_nls,
2843 				       remap);
2844 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2845 		name_len2 *= 2;	/* convert to bytes */
2846 	} else {
2847 		name_len = copy_path_name(pSMB->OldFileName, from_name);
2848 		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */
2849 		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2850 		name_len2++;	/* signature byte */
2851 	}
2852 
2853 	count = 1 /* string type byte */  + name_len + name_len2;
2854 	in_len += count;
2855 	pSMB->ByteCount = cpu_to_le16(count);
2856 
2857 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2858 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2859 	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2860 	if (rc)
2861 		cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
2862 
2863 	cifs_buf_release(pSMB);
2864 	if (rc == -EAGAIN)
2865 		goto winCreateHardLinkRetry;
2866 
2867 	return rc;
2868 }
2869 
2870 int
CIFSSMBUnixQuerySymLink(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * searchName,char ** symlinkinfo,const struct nls_table * nls_codepage,int remap)2871 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2872 			const unsigned char *searchName, char **symlinkinfo,
2873 			const struct nls_table *nls_codepage, int remap)
2874 {
2875 /* SMB_QUERY_FILE_UNIX_LINK */
2876 	TRANSACTION2_QPI_REQ *pSMB = NULL;
2877 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
2878 	unsigned int in_len;
2879 	int rc = 0;
2880 	int bytes_returned;
2881 	int name_len;
2882 	__u16 params, byte_count;
2883 	char *data_start;
2884 
2885 	cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
2886 
2887 querySymLinkRetry:
2888 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2889 		      (void **) &pSMBr);
2890 	if (rc < 0)
2891 		return rc;
2892 	in_len = rc;
2893 
2894 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2895 		name_len =
2896 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
2897 					   searchName, PATH_MAX, nls_codepage,
2898 					   remap);
2899 		name_len++;	/* trailing null */
2900 		name_len *= 2;
2901 	} else {
2902 		name_len = copy_path_name(pSMB->FileName, searchName);
2903 	}
2904 
2905 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2906 	pSMB->TotalDataCount = 0;
2907 	pSMB->MaxParameterCount = cpu_to_le16(2);
2908 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2909 	pSMB->MaxSetupCount = 0;
2910 	pSMB->Reserved = 0;
2911 	pSMB->Flags = 0;
2912 	pSMB->Timeout = 0;
2913 	pSMB->Reserved2 = 0;
2914 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
2915 		struct smb_com_transaction2_qpi_req, InformationLevel));
2916 	pSMB->DataCount = 0;
2917 	pSMB->DataOffset = 0;
2918 	pSMB->SetupCount = 1;
2919 	pSMB->Reserved3 = 0;
2920 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2921 	byte_count = params + 1 /* pad */ ;
2922 	pSMB->TotalParameterCount = cpu_to_le16(params);
2923 	pSMB->ParameterCount = pSMB->TotalParameterCount;
2924 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2925 	pSMB->Reserved4 = 0;
2926 	in_len += byte_count;
2927 	pSMB->ByteCount = cpu_to_le16(byte_count);
2928 
2929 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
2930 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2931 	if (rc) {
2932 		cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
2933 	} else {
2934 		/* decode response */
2935 
2936 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2937 		/* BB also check enough total bytes returned */
2938 		if (rc || get_bcc(&pSMBr->hdr) < 2)
2939 			rc = smb_EIO2(smb_eio_trace_qsym_bcc_too_small,
2940 				      get_bcc(&pSMBr->hdr), 2);
2941 		else {
2942 			bool is_unicode;
2943 			u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2944 
2945 			data_start = ((char *) &pSMBr->hdr.Protocol) +
2946 					   le16_to_cpu(pSMBr->t2.DataOffset);
2947 
2948 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2949 				is_unicode = true;
2950 			else
2951 				is_unicode = false;
2952 
2953 			/* BB FIXME investigate remapping reserved chars here */
2954 			*symlinkinfo = cifs_strndup_from_utf16(data_start,
2955 					count, is_unicode, nls_codepage);
2956 			if (!*symlinkinfo)
2957 				rc = -ENOMEM;
2958 		}
2959 	}
2960 	cifs_buf_release(pSMB);
2961 	if (rc == -EAGAIN)
2962 		goto querySymLinkRetry;
2963 	return rc;
2964 }
2965 
cifs_query_reparse_point(const unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,const char * full_path,u32 * tag,struct kvec * rsp,int * rsp_buftype)2966 int cifs_query_reparse_point(const unsigned int xid,
2967 			     struct cifs_tcon *tcon,
2968 			     struct cifs_sb_info *cifs_sb,
2969 			     const char *full_path,
2970 			     u32 *tag, struct kvec *rsp,
2971 			     int *rsp_buftype)
2972 {
2973 	struct reparse_data_buffer *buf;
2974 	struct cifs_open_parms oparms;
2975 	TRANSACT_IOCTL_REQ *io_req = NULL;
2976 	TRANSACT_IOCTL_RSP *io_rsp = NULL;
2977 	struct cifs_fid fid;
2978 	unsigned int in_len;
2979 	__u32 data_offset, data_count, len;
2980 	__u8 *start, *end;
2981 	int io_rsp_len;
2982 	int oplock = 0;
2983 	int rc;
2984 
2985 	cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
2986 
2987 	if (cap_unix(tcon->ses))
2988 		return -EOPNOTSUPP;
2989 
2990 	if (!CIFS_REPARSE_SUPPORT(tcon))
2991 		return -EOPNOTSUPP;
2992 
2993 	oparms = (struct cifs_open_parms) {
2994 		.tcon = tcon,
2995 		.cifs_sb = cifs_sb,
2996 		.desired_access = FILE_READ_ATTRIBUTES,
2997 		.create_options = cifs_create_options(cifs_sb,
2998 						      OPEN_REPARSE_POINT),
2999 		.disposition = FILE_OPEN,
3000 		.path = full_path,
3001 		.fid = &fid,
3002 	};
3003 
3004 	rc = CIFS_open(xid, &oparms, &oplock, NULL);
3005 	if (rc)
3006 		return rc;
3007 
3008 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon,
3009 		      (void **)&io_req, (void **)&io_rsp);
3010 	if (rc < 0)
3011 		goto error;
3012 	in_len = rc;
3013 
3014 	io_req->TotalParameterCount = 0;
3015 	io_req->TotalDataCount = 0;
3016 	io_req->MaxParameterCount = cpu_to_le32(0);
3017 	/* BB find exact data count max from sess structure BB */
3018 	io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3019 	io_req->MaxSetupCount = 1;
3020 	io_req->Reserved = 0;
3021 	io_req->ParameterOffset = 0;
3022 	io_req->DataCount = 0;
3023 	io_req->DataOffset = 0;
3024 	io_req->SetupCount = 4;
3025 	io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3026 	io_req->ParameterCount = io_req->TotalParameterCount;
3027 	io_req->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3028 	io_req->IsFsctl = 1;
3029 	io_req->IsRootFlag = 0;
3030 	io_req->Fid = fid.netfid;
3031 	io_req->ByteCount = 0;
3032 
3033 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)io_req, in_len,
3034 			 (struct smb_hdr *)io_rsp, &io_rsp_len, 0);
3035 	if (rc)
3036 		goto error;
3037 
3038 	data_offset = le32_to_cpu(io_rsp->DataOffset);
3039 	data_count = le32_to_cpu(io_rsp->DataCount);
3040 	if (get_bcc(&io_rsp->hdr) < 2 || data_offset > 512 ||
3041 	    !data_count || data_count > 2048) {
3042 		rc = smb_EIO2(smb_eio_trace_qreparse_sizes_wrong,
3043 			      get_bcc(&io_rsp->hdr), data_count);
3044 		goto error;
3045 	}
3046 
3047 	/* SetupCount must be 1, otherwise offset to ByteCount is incorrect. */
3048 	if (io_rsp->SetupCount != 1) {
3049 		rc = smb_EIO2(smb_eio_trace_qreparse_setup_count,
3050 			      io_rsp->SetupCount, 1);
3051 		goto error;
3052 	}
3053 
3054 	/*
3055 	 * ReturnedDataLen is output length of executed IOCTL.
3056 	 * DataCount is output length transferred over network.
3057 	 * Check that we have full FSCTL_GET_REPARSE_POINT buffer.
3058 	 */
3059 	if (data_count != le16_to_cpu(io_rsp->ReturnedDataLen)) {
3060 		rc = smb_EIO2(smb_eio_trace_qreparse_ret_datalen,
3061 			      data_count, le16_to_cpu(io_rsp->ReturnedDataLen));
3062 		goto error;
3063 	}
3064 
3065 	end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
3066 	start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
3067 	if (start >= end) {
3068 		rc = smb_EIO2(smb_eio_trace_qreparse_data_area,
3069 			      (unsigned long)start - (unsigned long)io_rsp,
3070 			      (unsigned long)end - (unsigned long)io_rsp);
3071 		goto error;
3072 	}
3073 
3074 	data_count = le16_to_cpu(io_rsp->ByteCount);
3075 	buf = (struct reparse_data_buffer *)start;
3076 	len = sizeof(*buf);
3077 	if (data_count < len ||
3078 	    data_count < le16_to_cpu(buf->ReparseDataLength) + len) {
3079 		rc = smb_EIO2(smb_eio_trace_qreparse_rep_datalen,
3080 			      data_count, le16_to_cpu(buf->ReparseDataLength) + len);
3081 		goto error;
3082 	}
3083 
3084 	*tag = le32_to_cpu(buf->ReparseTag);
3085 	rsp->iov_base = io_rsp;
3086 	rsp->iov_len = io_rsp_len;
3087 	*rsp_buftype = CIFS_LARGE_BUFFER;
3088 	CIFSSMBClose(xid, tcon, fid.netfid);
3089 	return 0;
3090 
3091 error:
3092 	cifs_buf_release(io_req);
3093 	CIFSSMBClose(xid, tcon, fid.netfid);
3094 	return rc;
3095 }
3096 
cifs_create_reparse_inode(struct cifs_open_info_data * data,struct super_block * sb,const unsigned int xid,struct cifs_tcon * tcon,const char * full_path,bool directory,struct kvec * reparse_iov,struct kvec * xattr_iov)3097 struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data,
3098 					struct super_block *sb,
3099 					const unsigned int xid,
3100 					struct cifs_tcon *tcon,
3101 					const char *full_path,
3102 					bool directory,
3103 					struct kvec *reparse_iov,
3104 					struct kvec *xattr_iov)
3105 {
3106 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
3107 	struct cifs_open_parms oparms;
3108 	TRANSACT_IOCTL_REQ *io_req;
3109 	struct inode *new = NULL;
3110 	struct kvec in_iov[2];
3111 	struct kvec out_iov;
3112 	struct cifs_fid fid;
3113 	unsigned int in_len;
3114 	int oplock = 0;
3115 	int buf_type = 0;
3116 	int rc;
3117 
3118 	cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
3119 
3120 	/*
3121 	 * If server filesystem does not support reparse points then do not
3122 	 * attempt to create reparse point. This will prevent creating unusable
3123 	 * empty object on the server.
3124 	 */
3125 	if (!CIFS_REPARSE_SUPPORT(tcon))
3126 		return ERR_PTR(-EOPNOTSUPP);
3127 
3128 #ifndef CONFIG_CIFS_XATTR
3129 	if (xattr_iov)
3130 		return ERR_PTR(-EOPNOTSUPP);
3131 #endif
3132 
3133 	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
3134 			     FILE_READ_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA,
3135 			     FILE_CREATE,
3136 			     (directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
3137 			     ACL_NO_MODE);
3138 	oparms.fid = &fid;
3139 
3140 	rc = CIFS_open(xid, &oparms, &oplock, NULL);
3141 	if (rc)
3142 		return ERR_PTR(rc);
3143 
3144 #ifdef CONFIG_CIFS_XATTR
3145 	if (xattr_iov) {
3146 		struct smb2_file_full_ea_info *ea;
3147 
3148 		ea = &((struct smb2_create_ea_ctx *)xattr_iov->iov_base)->ea;
3149 		while (1) {
3150 			rc = CIFSSMBSetEA(xid,
3151 					  tcon,
3152 					  full_path,
3153 					  &ea->ea_data[0],
3154 					  &ea->ea_data[ea->ea_name_length+1],
3155 					  le16_to_cpu(ea->ea_value_length),
3156 					  cifs_sb->local_nls,
3157 					  cifs_sb);
3158 			if (rc)
3159 				goto out_close;
3160 			if (le32_to_cpu(ea->next_entry_offset) == 0)
3161 				break;
3162 			ea = (struct smb2_file_full_ea_info *)((u8 *)ea +
3163 				le32_to_cpu(ea->next_entry_offset));
3164 		}
3165 	}
3166 #endif
3167 
3168 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **)&io_req, NULL);
3169 	if (rc < 0)
3170 		goto out_close;
3171 	in_len = rc;
3172 	in_len += sizeof(io_req->Pad);
3173 
3174 	/* NT IOCTL response contains one-word long output setup buffer with size of output data. */
3175 	io_req->MaxSetupCount = 1;
3176 	/* NT IOCTL response does not contain output parameters. */
3177 	io_req->MaxParameterCount = cpu_to_le32(0);
3178 	/* FSCTL_SET_REPARSE_POINT response contains empty output data. */
3179 	io_req->MaxDataCount = cpu_to_le32(0);
3180 
3181 	io_req->TotalParameterCount = cpu_to_le32(0);
3182 	io_req->TotalDataCount = cpu_to_le32(reparse_iov->iov_len);
3183 	io_req->ParameterCount = io_req->TotalParameterCount;
3184 	io_req->ParameterOffset = cpu_to_le32(0);
3185 	io_req->DataCount = io_req->TotalDataCount;
3186 	io_req->DataOffset = cpu_to_le32(offsetof(typeof(*io_req), Data));
3187 	io_req->SetupCount = 4;
3188 	io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3189 	io_req->FunctionCode = cpu_to_le32(FSCTL_SET_REPARSE_POINT);
3190 	io_req->Fid = fid.netfid;
3191 	io_req->IsFsctl = 1;
3192 	io_req->IsRootFlag = 0;
3193 	io_req->ByteCount = cpu_to_le16(le32_to_cpu(io_req->DataCount) + sizeof(io_req->Pad));
3194 
3195 	in_iov[0].iov_base = (char *)io_req;
3196 	in_iov[0].iov_len = in_len;
3197 	in_iov[1] = *reparse_iov;
3198 	rc = SendReceive2(xid, tcon->ses, in_iov, ARRAY_SIZE(in_iov), &buf_type,
3199 			  CIFS_NO_RSP_BUF, &out_iov);
3200 
3201 	cifs_buf_release(io_req);
3202 
3203 	if (!rc)
3204 		rc = cifs_get_inode_info(&new, full_path, data, sb, xid, NULL);
3205 
3206 out_close:
3207 	CIFSSMBClose(xid, tcon, fid.netfid);
3208 
3209 	/*
3210 	 * If CREATE was successful but FSCTL_SET_REPARSE_POINT failed then
3211 	 * remove the intermediate object created by CREATE. Otherwise
3212 	 * empty object stay on the server when reparse call failed.
3213 	 */
3214 	if (rc)
3215 		CIFSSMBDelFile(xid, tcon, full_path, cifs_sb, NULL);
3216 
3217 	return rc ? ERR_PTR(rc) : new;
3218 }
3219 
3220 int
CIFSSMB_set_compression(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,__u16 compression_state)3221 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3222 		    __u16 fid, __u16 compression_state)
3223 {
3224 	int rc = 0;
3225 	int bytes_returned;
3226 	struct smb_com_transaction_compr_ioctl_req *pSMB;
3227 	struct smb_com_transaction_ioctl_rsp *pSMBr;
3228 	unsigned int in_len;
3229 
3230 	cifs_dbg(FYI, "Set compression for %u\n", fid);
3231 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3232 		      (void **) &pSMBr);
3233 	if (rc < 0)
3234 		return rc;
3235 	in_len = rc;
3236 
3237 	pSMB->compression_state = cpu_to_le16(compression_state);
3238 
3239 	pSMB->TotalParameterCount = 0;
3240 	pSMB->TotalDataCount = cpu_to_le32(2);
3241 	pSMB->MaxParameterCount = 0;
3242 	pSMB->MaxDataCount = 0;
3243 	pSMB->MaxSetupCount = 4;
3244 	pSMB->Reserved = 0;
3245 	pSMB->ParameterOffset = 0;
3246 	pSMB->DataCount = cpu_to_le32(2);
3247 	pSMB->DataOffset =
3248 		cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3249 				     compression_state));  /* 84 */
3250 	pSMB->SetupCount = 4;
3251 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3252 	pSMB->ParameterCount = 0;
3253 	pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3254 	pSMB->IsFsctl = 1; /* FSCTL */
3255 	pSMB->IsRootFlag = 0;
3256 	pSMB->Fid = fid; /* file handle always le */
3257 	/* 3 byte pad, followed by 2 byte compress state */
3258 	pSMB->ByteCount = cpu_to_le16(5);
3259 	in_len += 5;
3260 
3261 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3262 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3263 	if (rc)
3264 		cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3265 
3266 	cifs_buf_release(pSMB);
3267 
3268 	/*
3269 	 * Note: On -EAGAIN error only caller can retry on handle based calls
3270 	 * since file handle passed in no longer valid.
3271 	 */
3272 	return rc;
3273 }
3274 
3275 
3276 #ifdef CONFIG_CIFS_POSIX
3277 
3278 #ifdef CONFIG_FS_POSIX_ACL
3279 /**
3280  * cifs_init_posix_acl - convert ACL from cifs to POSIX ACL format
3281  * @ace: POSIX ACL entry to store converted ACL into
3282  * @cifs_ace: ACL in cifs format
3283  *
3284  * Convert an Access Control Entry from wire format to local POSIX xattr
3285  * format.
3286  *
3287  * Note that the @cifs_uid member is used to store both {g,u}id_t.
3288  */
cifs_init_posix_acl(struct posix_acl_entry * ace,struct cifs_posix_ace * cifs_ace)3289 static void cifs_init_posix_acl(struct posix_acl_entry *ace,
3290 				struct cifs_posix_ace *cifs_ace)
3291 {
3292 	/* u8 cifs fields do not need le conversion */
3293 	ace->e_perm = cifs_ace->cifs_e_perm;
3294 	ace->e_tag = cifs_ace->cifs_e_tag;
3295 
3296 	switch (ace->e_tag) {
3297 	case ACL_USER:
3298 		ace->e_uid = make_kuid(&init_user_ns,
3299 				       le64_to_cpu(cifs_ace->cifs_uid));
3300 		break;
3301 	case ACL_GROUP:
3302 		ace->e_gid = make_kgid(&init_user_ns,
3303 				       le64_to_cpu(cifs_ace->cifs_uid));
3304 		break;
3305 	}
3306 	return;
3307 }
3308 
3309 /**
3310  * cifs_to_posix_acl - copy cifs ACL format to POSIX ACL format
3311  * @acl: ACLs returned in POSIX ACL format
3312  * @src: ACLs in cifs format
3313  * @acl_type: type of POSIX ACL requested
3314  * @size_of_data_area: size of SMB we got
3315  *
3316  * This function converts ACLs from cifs format to POSIX ACL format.
3317  * If @acl is NULL then the size of the buffer required to store POSIX ACLs in
3318  * their uapi format is returned.
3319  */
cifs_to_posix_acl(struct posix_acl ** acl,char * src,const int acl_type,const int size_of_data_area)3320 static int cifs_to_posix_acl(struct posix_acl **acl, char *src,
3321 			     const int acl_type, const int size_of_data_area)
3322 {
3323 	int size =  0;
3324 	__u16 count;
3325 	struct cifs_posix_ace *pACE;
3326 	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3327 	struct posix_acl *kacl = NULL;
3328 	struct posix_acl_entry *pa, *pe;
3329 
3330 	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3331 		return -EOPNOTSUPP;
3332 
3333 	if (acl_type == ACL_TYPE_ACCESS) {
3334 		count = le16_to_cpu(cifs_acl->access_entry_count);
3335 		pACE = &cifs_acl->ace_array[0];
3336 		size = sizeof(struct cifs_posix_acl);
3337 		size += sizeof(struct cifs_posix_ace) * count;
3338 		/* check if we would go beyond end of SMB */
3339 		if (size_of_data_area < size) {
3340 			cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3341 				 size_of_data_area, size);
3342 			return -EINVAL;
3343 		}
3344 	} else if (acl_type == ACL_TYPE_DEFAULT) {
3345 		count = le16_to_cpu(cifs_acl->access_entry_count);
3346 		size = sizeof(struct cifs_posix_acl);
3347 		size += sizeof(struct cifs_posix_ace) * count;
3348 		/* skip past access ACEs to get to default ACEs */
3349 		pACE = &cifs_acl->ace_array[count];
3350 		count = le16_to_cpu(cifs_acl->default_entry_count);
3351 		size += sizeof(struct cifs_posix_ace) * count;
3352 		/* check if we would go beyond end of SMB */
3353 		if (size_of_data_area < size)
3354 			return -EINVAL;
3355 	} else {
3356 		/* illegal type */
3357 		return -EINVAL;
3358 	}
3359 
3360 	/* Allocate number of POSIX ACLs to store in VFS format. */
3361 	kacl = posix_acl_alloc(count, GFP_NOFS);
3362 	if (!kacl)
3363 		return -ENOMEM;
3364 
3365 	FOREACH_ACL_ENTRY(pa, kacl, pe) {
3366 		cifs_init_posix_acl(pa, pACE);
3367 		pACE++;
3368 	}
3369 
3370 	*acl = kacl;
3371 	return 0;
3372 }
3373 
3374 /**
3375  * cifs_init_ace - convert ACL entry from POSIX ACL to cifs format
3376  * @cifs_ace: the cifs ACL entry to store into
3377  * @local_ace: the POSIX ACL entry to convert
3378  */
cifs_init_ace(struct cifs_posix_ace * cifs_ace,const struct posix_acl_entry * local_ace)3379 static void cifs_init_ace(struct cifs_posix_ace *cifs_ace,
3380 			  const struct posix_acl_entry *local_ace)
3381 {
3382 	cifs_ace->cifs_e_perm = local_ace->e_perm;
3383 	cifs_ace->cifs_e_tag =  local_ace->e_tag;
3384 
3385 	switch (local_ace->e_tag) {
3386 	case ACL_USER:
3387 		cifs_ace->cifs_uid =
3388 			cpu_to_le64(from_kuid(&init_user_ns, local_ace->e_uid));
3389 		break;
3390 	case ACL_GROUP:
3391 		cifs_ace->cifs_uid =
3392 			cpu_to_le64(from_kgid(&init_user_ns, local_ace->e_gid));
3393 		break;
3394 	default:
3395 		cifs_ace->cifs_uid = cpu_to_le64(-1);
3396 	}
3397 }
3398 
3399 /**
3400  * posix_acl_to_cifs - convert ACLs from POSIX ACL to cifs format
3401  * @parm_data: ACLs in cifs format to convert to
3402  * @acl: ACLs in POSIX ACL format to convert from
3403  * @acl_type: the type of POSIX ACLs stored in @acl
3404  *
3405  * Return: the number cifs ACL entries after conversion
3406  */
posix_acl_to_cifs(char * parm_data,const struct posix_acl * acl,const int acl_type)3407 static __u16 posix_acl_to_cifs(char *parm_data, const struct posix_acl *acl,
3408 			       const int acl_type)
3409 {
3410 	__u16 rc = 0;
3411 	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3412 	const struct posix_acl_entry *pa, *pe;
3413 	int count;
3414 	int i = 0;
3415 
3416 	if ((acl == NULL) || (cifs_acl == NULL))
3417 		return 0;
3418 
3419 	count = acl->a_count;
3420 	cifs_dbg(FYI, "setting acl with %d entries\n", count);
3421 
3422 	/*
3423 	 * Note that the uapi POSIX ACL version is verified by the VFS and is
3424 	 * independent of the cifs ACL version. Changing the POSIX ACL version
3425 	 * is a uapi change and if it's changed we will pass down the POSIX ACL
3426 	 * version in struct posix_acl from the VFS. For now there's really
3427 	 * only one that all filesystems know how to deal with.
3428 	 */
3429 	cifs_acl->version = cpu_to_le16(1);
3430 	if (acl_type == ACL_TYPE_ACCESS) {
3431 		cifs_acl->access_entry_count = cpu_to_le16(count);
3432 		cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3433 	} else if (acl_type == ACL_TYPE_DEFAULT) {
3434 		cifs_acl->default_entry_count = cpu_to_le16(count);
3435 		cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3436 	} else {
3437 		cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3438 		return 0;
3439 	}
3440 	FOREACH_ACL_ENTRY(pa, acl, pe) {
3441 		cifs_init_ace(&cifs_acl->ace_array[i++], pa);
3442 	}
3443 	if (rc == 0) {
3444 		rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3445 		rc += sizeof(struct cifs_posix_acl);
3446 		/* BB add check to make sure ACL does not overflow SMB */
3447 	}
3448 	return rc;
3449 }
3450 
cifs_do_get_acl(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * searchName,struct posix_acl ** acl,const int acl_type,const struct nls_table * nls_codepage,int remap)3451 int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
3452 		    const unsigned char *searchName, struct posix_acl **acl,
3453 		    const int acl_type, const struct nls_table *nls_codepage,
3454 		    int remap)
3455 {
3456 /* SMB_QUERY_POSIX_ACL */
3457 	TRANSACTION2_QPI_REQ *pSMB = NULL;
3458 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3459 	unsigned int in_len;
3460 	int rc = 0;
3461 	int bytes_returned;
3462 	int name_len;
3463 	__u16 params, byte_count;
3464 
3465 	cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3466 
3467 queryAclRetry:
3468 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3469 		(void **) &pSMBr);
3470 	if (rc < 0)
3471 		return rc;
3472 	in_len = rc;
3473 
3474 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3475 		name_len =
3476 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3477 					   searchName, PATH_MAX, nls_codepage,
3478 					   remap);
3479 		name_len++;     /* trailing null */
3480 		name_len *= 2;
3481 		pSMB->FileName[name_len] = 0;
3482 		pSMB->FileName[name_len+1] = 0;
3483 	} else {
3484 		name_len = copy_path_name(pSMB->FileName, searchName);
3485 	}
3486 
3487 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3488 	pSMB->TotalDataCount = 0;
3489 	pSMB->MaxParameterCount = cpu_to_le16(2);
3490 	/* BB find exact max data count below from sess structure BB */
3491 	pSMB->MaxDataCount = cpu_to_le16(4000);
3492 	pSMB->MaxSetupCount = 0;
3493 	pSMB->Reserved = 0;
3494 	pSMB->Flags = 0;
3495 	pSMB->Timeout = 0;
3496 	pSMB->Reserved2 = 0;
3497 	pSMB->ParameterOffset = cpu_to_le16(
3498 		offsetof(struct smb_com_transaction2_qpi_req,
3499 			 InformationLevel));
3500 	pSMB->DataCount = 0;
3501 	pSMB->DataOffset = 0;
3502 	pSMB->SetupCount = 1;
3503 	pSMB->Reserved3 = 0;
3504 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3505 	byte_count = params + 1 /* pad */ ;
3506 	pSMB->TotalParameterCount = cpu_to_le16(params);
3507 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3508 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3509 	pSMB->Reserved4 = 0;
3510 	in_len += byte_count;
3511 	pSMB->ByteCount = cpu_to_le16(byte_count);
3512 
3513 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3514 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3515 	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3516 	if (rc) {
3517 		cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3518 	} else {
3519 		/* decode response */
3520 
3521 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3522 		/* BB also check enough total bytes returned */
3523 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3524 			rc = smb_EIO2(smb_eio_trace_getacl_bcc_too_small,
3525 				      get_bcc(&pSMBr->hdr), 2);
3526 		else {
3527 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3528 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3529 			rc = cifs_to_posix_acl(acl,
3530 				(char *)&pSMBr->hdr.Protocol+data_offset,
3531 				acl_type, count);
3532 		}
3533 	}
3534 	cifs_buf_release(pSMB);
3535 	/*
3536 	 * The else branch after SendReceive() doesn't return EAGAIN so if we
3537 	 * allocated @acl in cifs_to_posix_acl() we are guaranteed to return
3538 	 * here and don't leak POSIX ACLs.
3539 	 */
3540 	if (rc == -EAGAIN)
3541 		goto queryAclRetry;
3542 	return rc;
3543 }
3544 
cifs_do_set_acl(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * fileName,const struct posix_acl * acl,const int acl_type,const struct nls_table * nls_codepage,int remap)3545 int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
3546 		    const unsigned char *fileName, const struct posix_acl *acl,
3547 		    const int acl_type, const struct nls_table *nls_codepage,
3548 		    int remap)
3549 {
3550 	struct smb_com_transaction2_spi_req *pSMB = NULL;
3551 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3552 	unsigned int in_len;
3553 	char *parm_data;
3554 	int name_len;
3555 	int rc = 0;
3556 	int bytes_returned = 0;
3557 	__u16 params, byte_count, data_count, param_offset, offset;
3558 	size_t cifs_acl_size, bytes_available;
3559 
3560 	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3561 setAclRetry:
3562 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3563 		      (void **) &pSMBr);
3564 	if (rc < 0)
3565 		return rc;
3566 	in_len = rc;
3567 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3568 		name_len =
3569 			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3570 					   PATH_MAX, nls_codepage, remap);
3571 		name_len++;     /* trailing null */
3572 		name_len *= 2;
3573 	} else {
3574 		name_len = copy_path_name(pSMB->FileName, fileName);
3575 	}
3576 	params = 6 + name_len;
3577 	pSMB->MaxParameterCount = cpu_to_le16(2);
3578 	pSMB->MaxDataCount = cpu_to_le16(min_t(unsigned int, CIFSMaxBufSize, USHRT_MAX));
3579 	pSMB->MaxSetupCount = 0;
3580 	pSMB->Reserved = 0;
3581 	pSMB->Flags = 0;
3582 	pSMB->Timeout = 0;
3583 	pSMB->Reserved2 = 0;
3584 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3585 				InformationLevel);
3586 	offset = param_offset + params;
3587 	parm_data = ((char *)pSMB) + offset;
3588 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3589 
3590 	/* make sure we can fit the larger cifs_posix_aces in the buffer */
3591 	cifs_acl_size = sizeof(struct cifs_posix_acl) +
3592 		       (acl->a_count * sizeof(struct cifs_posix_ace));
3593 	bytes_available = (CIFSMaxBufSize + MAX_HEADER_SIZE(tcon->ses->server)) - offset;
3594 	if (cifs_acl_size > bytes_available || cifs_acl_size > USHRT_MAX) {
3595 		rc = -E2BIG;
3596 		goto setACLerrorExit;
3597 	}
3598 
3599 	/* convert to on the wire format for POSIX ACL */
3600 	data_count = posix_acl_to_cifs(parm_data, acl, acl_type);
3601 
3602 	if (data_count == 0) {
3603 		rc = -EOPNOTSUPP;
3604 		goto setACLerrorExit;
3605 	}
3606 	pSMB->DataOffset = cpu_to_le16(offset);
3607 	pSMB->SetupCount = 1;
3608 	pSMB->Reserved3 = 0;
3609 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3610 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3611 	byte_count = 3 /* pad */  + params + data_count;
3612 	pSMB->DataCount = cpu_to_le16(data_count);
3613 	pSMB->TotalDataCount = pSMB->DataCount;
3614 	pSMB->ParameterCount = cpu_to_le16(params);
3615 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3616 	pSMB->Reserved4 = 0;
3617 	in_len += byte_count;
3618 	pSMB->ByteCount = cpu_to_le16(byte_count);
3619 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3620 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3621 	if (rc)
3622 		cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3623 
3624 setACLerrorExit:
3625 	cifs_buf_release(pSMB);
3626 	if (rc == -EAGAIN)
3627 		goto setAclRetry;
3628 	return rc;
3629 }
3630 #else
cifs_do_get_acl(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * searchName,struct posix_acl ** acl,const int acl_type,const struct nls_table * nls_codepage,int remap)3631 int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
3632 		    const unsigned char *searchName, struct posix_acl **acl,
3633 		    const int acl_type, const struct nls_table *nls_codepage,
3634 		    int remap)
3635 {
3636 	return -EOPNOTSUPP;
3637 }
3638 
cifs_do_set_acl(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * fileName,const struct posix_acl * acl,const int acl_type,const struct nls_table * nls_codepage,int remap)3639 int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
3640 		    const unsigned char *fileName, const struct posix_acl *acl,
3641 		    const int acl_type, const struct nls_table *nls_codepage,
3642 		    int remap)
3643 {
3644 	return -EOPNOTSUPP;
3645 }
3646 #endif /* CONFIG_FS_POSIX_ACL */
3647 
3648 int
CIFSGetExtAttr(const unsigned int xid,struct cifs_tcon * tcon,const int netfid,__u64 * pExtAttrBits,__u64 * pMask)3649 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3650 	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3651 {
3652 	int rc = 0;
3653 	struct smb_t2_qfi_req *pSMB = NULL;
3654 	struct smb_t2_qfi_rsp *pSMBr = NULL;
3655 	unsigned int in_len;
3656 	int bytes_returned;
3657 	__u16 params, byte_count;
3658 
3659 	cifs_dbg(FYI, "In GetExtAttr\n");
3660 	if (tcon == NULL)
3661 		return -ENODEV;
3662 
3663 GetExtAttrRetry:
3664 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3665 		      (void **) &pSMBr);
3666 	if (rc < 0)
3667 		return rc;
3668 	in_len = rc;
3669 
3670 	params = 2 /* level */ + 2 /* fid */;
3671 	pSMB->t2.TotalDataCount = 0;
3672 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3673 	/* BB find exact max data count below from sess structure BB */
3674 	pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3675 	pSMB->t2.MaxSetupCount = 0;
3676 	pSMB->t2.Reserved = 0;
3677 	pSMB->t2.Flags = 0;
3678 	pSMB->t2.Timeout = 0;
3679 	pSMB->t2.Reserved2 = 0;
3680 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3681 					       Fid));
3682 	pSMB->t2.DataCount = 0;
3683 	pSMB->t2.DataOffset = 0;
3684 	pSMB->t2.SetupCount = 1;
3685 	pSMB->t2.Reserved3 = 0;
3686 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3687 	byte_count = params + 1 /* pad */ ;
3688 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3689 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3690 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3691 	pSMB->Pad = 0;
3692 	pSMB->Fid = netfid;
3693 	in_len += byte_count;
3694 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3695 
3696 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3697 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3698 	if (rc) {
3699 		cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3700 	} else {
3701 		/* decode response */
3702 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3703 		/* BB also check enough total bytes returned */
3704 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3705 			/* If rc should we check for EOPNOSUPP and
3706 			   disable the srvino flag? or in caller? */
3707 			rc = smb_EIO2(smb_eio_trace_getextattr_bcc_too_small,
3708 				      get_bcc(&pSMBr->hdr), 2);
3709 		else {
3710 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3711 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3712 			struct file_chattr_info *pfinfo;
3713 
3714 			if (count != 16) {
3715 				cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
3716 				rc = smb_EIO2(smb_eio_trace_getextattr_inv_size,
3717 					      count, 16);
3718 				goto GetExtAttrOut;
3719 			}
3720 			pfinfo = (struct file_chattr_info *)
3721 				 (data_offset + (char *) &pSMBr->hdr.Protocol);
3722 			*pExtAttrBits = le64_to_cpu(pfinfo->mode);
3723 			*pMask = le64_to_cpu(pfinfo->mask);
3724 		}
3725 	}
3726 GetExtAttrOut:
3727 	cifs_buf_release(pSMB);
3728 	if (rc == -EAGAIN)
3729 		goto GetExtAttrRetry;
3730 	return rc;
3731 }
3732 
3733 #endif /* CONFIG_POSIX */
3734 
3735 /*
3736  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3737  * all NT TRANSACTS that we init here have total parm and data under about 400
3738  * bytes (to fit in small cifs buffer size), which is the case so far, it
3739  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3740  * returned setup area) and MaxParameterCount (returned parms size) must be set
3741  * by caller
3742  */
3743 static int
smb_init_nttransact(const __u16 sub_command,const int setup_count,const int parm_len,struct cifs_tcon * tcon,void ** ret_buf)3744 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3745 		   const int parm_len, struct cifs_tcon *tcon,
3746 		   void **ret_buf)
3747 {
3748 	int rc;
3749 	__u32 temp_offset;
3750 	struct smb_com_ntransact_req *pSMB;
3751 	unsigned int in_len;
3752 
3753 	rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3754 				(void **)&pSMB);
3755 	if (rc < 0)
3756 		return rc;
3757 	in_len = rc;
3758 	*ret_buf = (void *)pSMB;
3759 	pSMB->Reserved = 0;
3760 	pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3761 	pSMB->TotalDataCount  = 0;
3762 	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3763 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3764 	pSMB->DataCount  = pSMB->TotalDataCount;
3765 	temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3766 		(setup_count * 2);
3767 	pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3768 	pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3769 	pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3770 	pSMB->SubCommand = cpu_to_le16(sub_command);
3771 	return in_len;
3772 }
3773 
3774 static int
validate_ntransact(char * buf,char ** ppparm,char ** ppdata,__u32 * pparmlen,__u32 * pdatalen)3775 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3776 		   __u32 *pparmlen, __u32 *pdatalen)
3777 {
3778 	char *end_of_smb;
3779 	__u32 data_count, data_offset, parm_count, parm_offset;
3780 	struct smb_com_ntransact_rsp *pSMBr;
3781 	u16 bcc;
3782 
3783 	*pdatalen = 0;
3784 	*pparmlen = 0;
3785 
3786 	if (buf == NULL)
3787 		return -EINVAL;
3788 
3789 	pSMBr = (struct smb_com_ntransact_rsp *)buf;
3790 
3791 	bcc = get_bcc(&pSMBr->hdr);
3792 	end_of_smb = 2 /* sizeof byte count */ + bcc +
3793 			(char *)&pSMBr->ByteCount;
3794 
3795 	data_offset = le32_to_cpu(pSMBr->DataOffset);
3796 	data_count = le32_to_cpu(pSMBr->DataCount);
3797 	parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3798 	parm_count = le32_to_cpu(pSMBr->ParameterCount);
3799 
3800 	*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3801 	*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3802 
3803 	/* should we also check that parm and data areas do not overlap? */
3804 	if (*ppparm > end_of_smb) {
3805 		cifs_dbg(FYI, "parms start after end of smb\n");
3806 		return -EINVAL;
3807 	} else if (parm_count + *ppparm > end_of_smb) {
3808 		cifs_dbg(FYI, "parm end after end of smb\n");
3809 		return -EINVAL;
3810 	} else if (*ppdata > end_of_smb) {
3811 		cifs_dbg(FYI, "data starts after end of smb\n");
3812 		return -EINVAL;
3813 	} else if (data_count + *ppdata > end_of_smb) {
3814 		cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3815 			 *ppdata, data_count, (data_count + *ppdata),
3816 			 end_of_smb, pSMBr);
3817 		return -EINVAL;
3818 	} else if (parm_count + data_count > bcc) {
3819 		cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3820 		return -EINVAL;
3821 	}
3822 	*pdatalen = data_count;
3823 	*pparmlen = parm_count;
3824 	return 0;
3825 }
3826 
3827 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3828 int
CIFSSMBGetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct smb_ntsd ** acl_inf,__u32 * pbuflen,__u32 info)3829 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3830 		  struct smb_ntsd **acl_inf, __u32 *pbuflen, __u32 info)
3831 {
3832 	int rc = 0;
3833 	int buf_type = 0;
3834 	QUERY_SEC_DESC_REQ *pSMB;
3835 	struct kvec iov[1];
3836 	struct kvec rsp_iov;
3837 	unsigned int in_len;
3838 
3839 	cifs_dbg(FYI, "GetCifsACL\n");
3840 
3841 	*pbuflen = 0;
3842 	*acl_inf = NULL;
3843 
3844 	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3845 			8 /* parm len */, tcon, (void **) &pSMB);
3846 	if (rc < 0)
3847 		return rc;
3848 	in_len = rc;
3849 
3850 	pSMB->MaxParameterCount = cpu_to_le32(4);
3851 	/* BB TEST with big acls that might need to be e.g. larger than 16K */
3852 	pSMB->MaxSetupCount = 0;
3853 	pSMB->Fid = fid; /* file handle always le */
3854 	pSMB->AclFlags = cpu_to_le32(info);
3855 	pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3856 	in_len += 11;
3857 	iov[0].iov_base = (char *)pSMB;
3858 	iov[0].iov_len = in_len;
3859 
3860 	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3861 			  0, &rsp_iov);
3862 	cifs_small_buf_release(pSMB);
3863 	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3864 	if (rc) {
3865 		cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3866 	} else {                /* decode response */
3867 		__le32 *parm;
3868 		__u32 parm_len;
3869 		__u32 acl_len;
3870 		struct smb_com_ntransact_rsp *pSMBr;
3871 		char *pdata;
3872 
3873 /* validate_nttransact */
3874 		rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3875 					&pdata, &parm_len, pbuflen);
3876 		if (rc)
3877 			goto qsec_out;
3878 		pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3879 
3880 		cifs_dbg(FYI, "smb %p parm %p data %p\n",
3881 			 pSMBr, parm, *acl_inf);
3882 
3883 		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3884 			rc = smb_EIO2(smb_eio_trace_getcifsacl_param_count,
3885 				      le32_to_cpu(pSMBr->ParameterCount), 4);
3886 			*pbuflen = 0;
3887 			goto qsec_out;
3888 		}
3889 
3890 /* BB check that data area is minimum length and as big as acl_len */
3891 
3892 		acl_len = le32_to_cpu(*parm);
3893 		if (acl_len != *pbuflen) {
3894 			cifs_dbg(VFS, "acl length %d does not match %d\n",
3895 				 acl_len, *pbuflen);
3896 			if (*pbuflen > acl_len)
3897 				*pbuflen = acl_len;
3898 		}
3899 
3900 		/* check if buffer is big enough for the acl
3901 		   header followed by the smallest SID */
3902 		if ((*pbuflen < sizeof(struct smb_ntsd) + 8) ||
3903 		    (*pbuflen >= 64 * 1024)) {
3904 			cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3905 			rc = -EINVAL;
3906 			*pbuflen = 0;
3907 		} else {
3908 			*acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3909 			if (*acl_inf == NULL) {
3910 				*pbuflen = 0;
3911 				rc = -ENOMEM;
3912 			}
3913 		}
3914 	}
3915 qsec_out:
3916 	free_rsp_buf(buf_type, rsp_iov.iov_base);
3917 	return rc;
3918 }
3919 
3920 int
CIFSSMBSetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct smb_ntsd * pntsd,__u32 acllen,int aclflag)3921 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3922 			struct smb_ntsd *pntsd, __u32 acllen, int aclflag)
3923 {
3924 	__u16 byte_count, param_count, data_count, param_offset, data_offset;
3925 	int rc = 0;
3926 	int bytes_returned = 0;
3927 	SET_SEC_DESC_REQ *pSMB = NULL;
3928 	unsigned int in_len;
3929 	void *pSMBr;
3930 
3931 setCifsAclRetry:
3932 	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3933 	if (rc < 0)
3934 		return rc;
3935 	in_len = rc;
3936 
3937 	pSMB->MaxSetupCount = 0;
3938 	pSMB->Reserved = 0;
3939 
3940 	param_count = 8;
3941 	param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid);
3942 	data_count = acllen;
3943 	data_offset = param_offset + param_count;
3944 	byte_count = 3 /* pad */  + param_count;
3945 
3946 	pSMB->DataCount = cpu_to_le32(data_count);
3947 	pSMB->TotalDataCount = pSMB->DataCount;
3948 	pSMB->MaxParameterCount = cpu_to_le32(4);
3949 	pSMB->MaxDataCount = cpu_to_le32(16384);
3950 	pSMB->ParameterCount = cpu_to_le32(param_count);
3951 	pSMB->ParameterOffset = cpu_to_le32(param_offset);
3952 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3953 	pSMB->DataOffset = cpu_to_le32(data_offset);
3954 	pSMB->SetupCount = 0;
3955 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3956 	pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3957 
3958 	pSMB->Fid = fid; /* file handle always le */
3959 	pSMB->Reserved2 = 0;
3960 	pSMB->AclFlags = cpu_to_le32(aclflag);
3961 
3962 	if (pntsd && acllen) {
3963 		memcpy((char *)pSMBr + data_offset, pntsd, acllen);
3964 		in_len += byte_count + data_count;
3965 	} else
3966 		in_len += byte_count;
3967 
3968 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
3969 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3970 
3971 	cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3972 		 bytes_returned, rc);
3973 	if (rc)
3974 		cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3975 	cifs_buf_release(pSMB);
3976 
3977 	if (rc == -EAGAIN)
3978 		goto setCifsAclRetry;
3979 
3980 	return (rc);
3981 }
3982 
3983 
3984 /* Legacy Query Path Information call for lookup to old servers such
3985    as Win9x/WinME */
3986 int
SMBQueryInformation(const unsigned int xid,struct cifs_tcon * tcon,const char * search_name,FILE_ALL_INFO * data,const struct nls_table * nls_codepage,int remap)3987 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3988 		    const char *search_name, FILE_ALL_INFO *data,
3989 		    const struct nls_table *nls_codepage, int remap)
3990 {
3991 	QUERY_INFORMATION_REQ *pSMB;
3992 	QUERY_INFORMATION_RSP *pSMBr;
3993 	unsigned int in_len;
3994 	int rc = 0;
3995 	int bytes_returned;
3996 	int name_len;
3997 
3998 	cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
3999 QInfRetry:
4000 	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
4001 		      (void **) &pSMBr);
4002 	if (rc < 0)
4003 		return rc;
4004 	in_len = rc;
4005 
4006 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4007 		name_len =
4008 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4009 					   search_name, PATH_MAX, nls_codepage,
4010 					   remap);
4011 		name_len++;     /* trailing null */
4012 		name_len *= 2;
4013 	} else {
4014 		name_len = copy_path_name(pSMB->FileName, search_name);
4015 	}
4016 	pSMB->BufferFormat = 0x04;
4017 	name_len++; /* account for buffer type byte */
4018 	in_len += name_len;
4019 	pSMB->ByteCount = cpu_to_le16(name_len);
4020 
4021 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4022 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4023 	if (rc) {
4024 		cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
4025 	} else if (data) {
4026 		struct timespec64 ts;
4027 		__u32 time = le32_to_cpu(pSMBr->last_write_time);
4028 
4029 		/* decode response */
4030 		/* BB FIXME - add time zone adjustment BB */
4031 		memset(data, 0, sizeof(FILE_ALL_INFO));
4032 		ts.tv_nsec = 0;
4033 		ts.tv_sec = time;
4034 		/* decode time fields */
4035 		data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4036 		data->LastWriteTime = data->ChangeTime;
4037 		data->LastAccessTime = 0;
4038 		data->AllocationSize =
4039 			cpu_to_le64(le32_to_cpu(pSMBr->size));
4040 		data->EndOfFile = data->AllocationSize;
4041 		data->Attributes =
4042 			cpu_to_le32(le16_to_cpu(pSMBr->attr));
4043 	} else {
4044 		/* bad buffer passed in */
4045 		rc = smb_EIO(smb_eio_trace_null_pointers);
4046 	}
4047 
4048 	cifs_buf_release(pSMB);
4049 
4050 	if (rc == -EAGAIN)
4051 		goto QInfRetry;
4052 
4053 	return rc;
4054 }
4055 
4056 int
CIFSSMBQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_ALL_INFO * pFindData)4057 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4058 		 u16 netfid, FILE_ALL_INFO *pFindData)
4059 {
4060 	struct smb_t2_qfi_req *pSMB = NULL;
4061 	struct smb_t2_qfi_rsp *pSMBr = NULL;
4062 	unsigned int in_len;
4063 	int rc = 0;
4064 	int bytes_returned;
4065 	__u16 params, byte_count;
4066 
4067 QFileInfoRetry:
4068 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4069 		      (void **) &pSMBr);
4070 	if (rc < 0)
4071 		return rc;
4072 	in_len = rc;
4073 
4074 	params = 2 /* level */ + 2 /* fid */;
4075 	pSMB->t2.TotalDataCount = 0;
4076 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4077 	/* BB find exact max data count below from sess structure BB */
4078 	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4079 	pSMB->t2.MaxSetupCount = 0;
4080 	pSMB->t2.Reserved = 0;
4081 	pSMB->t2.Flags = 0;
4082 	pSMB->t2.Timeout = 0;
4083 	pSMB->t2.Reserved2 = 0;
4084 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4085 					       Fid));
4086 	pSMB->t2.DataCount = 0;
4087 	pSMB->t2.DataOffset = 0;
4088 	pSMB->t2.SetupCount = 1;
4089 	pSMB->t2.Reserved3 = 0;
4090 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4091 	byte_count = params + 1 /* pad */ ;
4092 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4093 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4094 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4095 	pSMB->Pad = 0;
4096 	pSMB->Fid = netfid;
4097 	in_len += byte_count;
4098 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4099 
4100 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4101 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4102 	if (rc) {
4103 		cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
4104 	} else {		/* decode response */
4105 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4106 
4107 		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4108 			rc = smb_EIO2(smb_eio_trace_qfileinfo_invalid,
4109 				      get_bcc(&pSMBr->hdr), 40);
4110 		else if (get_bcc(&pSMBr->hdr) < 40)
4111 			rc = smb_EIO2(smb_eio_trace_qfileinfo_bcc_too_small,
4112 				      get_bcc(&pSMBr->hdr), 40);
4113 		else if (pFindData) {
4114 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4115 			memcpy((char *) pFindData,
4116 			       (char *) &pSMBr->hdr.Protocol +
4117 			       data_offset, sizeof(FILE_ALL_INFO));
4118 		} else
4119 		    rc = -ENOMEM;
4120 	}
4121 	cifs_buf_release(pSMB);
4122 	if (rc == -EAGAIN)
4123 		goto QFileInfoRetry;
4124 
4125 	return rc;
4126 }
4127 
4128 int
CIFSSMBQPathInfo(const unsigned int xid,struct cifs_tcon * tcon,const char * search_name,FILE_ALL_INFO * data,int legacy,const struct nls_table * nls_codepage,int remap)4129 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4130 		 const char *search_name, FILE_ALL_INFO *data,
4131 		 int legacy /* old style infolevel */,
4132 		 const struct nls_table *nls_codepage, int remap)
4133 {
4134 	/* level 263 SMB_QUERY_FILE_ALL_INFO */
4135 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4136 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4137 	unsigned int in_len;
4138 	int rc = 0;
4139 	int bytes_returned;
4140 	int name_len;
4141 	__u16 params, byte_count;
4142 
4143 	/* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4144 QPathInfoRetry:
4145 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4146 		      (void **) &pSMBr);
4147 	if (rc < 0)
4148 		return rc;
4149 	in_len = rc;
4150 
4151 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4152 		name_len =
4153 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4154 				       PATH_MAX, nls_codepage, remap);
4155 		name_len++;	/* trailing null */
4156 		name_len *= 2;
4157 	} else {
4158 		name_len = copy_path_name(pSMB->FileName, search_name);
4159 	}
4160 
4161 	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4162 	pSMB->TotalDataCount = 0;
4163 	pSMB->MaxParameterCount = cpu_to_le16(2);
4164 	/* BB find exact max SMB PDU from sess structure BB */
4165 	pSMB->MaxDataCount = cpu_to_le16(4000);
4166 	pSMB->MaxSetupCount = 0;
4167 	pSMB->Reserved = 0;
4168 	pSMB->Flags = 0;
4169 	pSMB->Timeout = 0;
4170 	pSMB->Reserved2 = 0;
4171 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4172 		struct smb_com_transaction2_qpi_req, InformationLevel));
4173 	pSMB->DataCount = 0;
4174 	pSMB->DataOffset = 0;
4175 	pSMB->SetupCount = 1;
4176 	pSMB->Reserved3 = 0;
4177 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4178 	byte_count = params + 1 /* pad */ ;
4179 	pSMB->TotalParameterCount = cpu_to_le16(params);
4180 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4181 	if (legacy)
4182 		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4183 	else
4184 		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4185 	pSMB->Reserved4 = 0;
4186 	in_len += byte_count;
4187 	pSMB->ByteCount = cpu_to_le16(byte_count);
4188 
4189 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4190 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4191 	if (rc) {
4192 		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4193 	} else {		/* decode response */
4194 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4195 
4196 		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4197 			rc = smb_EIO2(smb_eio_trace_qpathinfo_invalid,
4198 				      get_bcc(&pSMBr->hdr), 40);
4199 		else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4200 			rc = smb_EIO2(smb_eio_trace_qpathinfo_bcc_too_small,
4201 				      get_bcc(&pSMBr->hdr), 40);
4202 		else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4203 			/* 24 or 26 expected but we do not read last field */
4204 			rc = smb_EIO2(smb_eio_trace_qpathinfo_bcc_too_small,
4205 				      get_bcc(&pSMBr->hdr), 24);
4206 		else if (data) {
4207 			int size;
4208 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4209 
4210 			/*
4211 			 * On legacy responses we do not read the last field,
4212 			 * EAsize, fortunately since it varies by subdialect and
4213 			 * also note it differs on Set vs Get, ie two bytes or 4
4214 			 * bytes depending but we don't care here.
4215 			 */
4216 			if (legacy)
4217 				size = sizeof(FILE_INFO_STANDARD);
4218 			else
4219 				size = sizeof(FILE_ALL_INFO);
4220 			memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4221 			       data_offset, size);
4222 		} else
4223 		    rc = -ENOMEM;
4224 	}
4225 	cifs_buf_release(pSMB);
4226 	if (rc == -EAGAIN)
4227 		goto QPathInfoRetry;
4228 
4229 	return rc;
4230 }
4231 
4232 int
CIFSSMBUnixQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_UNIX_BASIC_INFO * pFindData)4233 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4234 		 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4235 {
4236 	struct smb_t2_qfi_req *pSMB = NULL;
4237 	struct smb_t2_qfi_rsp *pSMBr = NULL;
4238 	unsigned int in_len;
4239 	int rc = 0;
4240 	int bytes_returned;
4241 	__u16 params, byte_count;
4242 
4243 UnixQFileInfoRetry:
4244 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4245 		      (void **) &pSMBr);
4246 	if (rc < 0)
4247 		return rc;
4248 	in_len = rc;
4249 
4250 	params = 2 /* level */ + 2 /* fid */;
4251 	pSMB->t2.TotalDataCount = 0;
4252 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4253 	/* BB find exact max data count below from sess structure BB */
4254 	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4255 	pSMB->t2.MaxSetupCount = 0;
4256 	pSMB->t2.Reserved = 0;
4257 	pSMB->t2.Flags = 0;
4258 	pSMB->t2.Timeout = 0;
4259 	pSMB->t2.Reserved2 = 0;
4260 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4261 					       Fid));
4262 	pSMB->t2.DataCount = 0;
4263 	pSMB->t2.DataOffset = 0;
4264 	pSMB->t2.SetupCount = 1;
4265 	pSMB->t2.Reserved3 = 0;
4266 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4267 	byte_count = params + 1 /* pad */ ;
4268 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4269 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4270 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4271 	pSMB->Pad = 0;
4272 	pSMB->Fid = netfid;
4273 	in_len += byte_count;
4274 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4275 
4276 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4277 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4278 	if (rc) {
4279 		cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
4280 	} else {		/* decode response */
4281 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4282 
4283 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4284 			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4285 			rc = smb_EIO2(smb_eio_trace_unixqfileinfo_bcc_too_small,
4286 				      get_bcc(&pSMBr->hdr), sizeof(FILE_UNIX_BASIC_INFO));
4287 		} else {
4288 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4289 			memcpy((char *) pFindData,
4290 			       (char *) &pSMBr->hdr.Protocol +
4291 			       data_offset,
4292 			       sizeof(FILE_UNIX_BASIC_INFO));
4293 		}
4294 	}
4295 
4296 	cifs_buf_release(pSMB);
4297 	if (rc == -EAGAIN)
4298 		goto UnixQFileInfoRetry;
4299 
4300 	return rc;
4301 }
4302 
4303 int
CIFSSMBUnixQPathInfo(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * searchName,FILE_UNIX_BASIC_INFO * pFindData,const struct nls_table * nls_codepage,int remap)4304 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4305 		     const unsigned char *searchName,
4306 		     FILE_UNIX_BASIC_INFO *pFindData,
4307 		     const struct nls_table *nls_codepage, int remap)
4308 {
4309 /* SMB_QUERY_FILE_UNIX_BASIC */
4310 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4311 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4312 	unsigned int in_len;
4313 	int rc = 0;
4314 	int bytes_returned = 0;
4315 	int name_len;
4316 	__u16 params, byte_count;
4317 
4318 	cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4319 UnixQPathInfoRetry:
4320 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4321 		      (void **) &pSMBr);
4322 	if (rc < 0)
4323 		return rc;
4324 	in_len = rc;
4325 
4326 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4327 		name_len =
4328 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4329 				       PATH_MAX, nls_codepage, remap);
4330 		name_len++;	/* trailing null */
4331 		name_len *= 2;
4332 	} else {
4333 		name_len = copy_path_name(pSMB->FileName, searchName);
4334 	}
4335 
4336 	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4337 	pSMB->TotalDataCount = 0;
4338 	pSMB->MaxParameterCount = cpu_to_le16(2);
4339 	/* BB find exact max SMB PDU from sess structure BB */
4340 	pSMB->MaxDataCount = cpu_to_le16(4000);
4341 	pSMB->MaxSetupCount = 0;
4342 	pSMB->Reserved = 0;
4343 	pSMB->Flags = 0;
4344 	pSMB->Timeout = 0;
4345 	pSMB->Reserved2 = 0;
4346 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4347 		struct smb_com_transaction2_qpi_req, InformationLevel));
4348 	pSMB->DataCount = 0;
4349 	pSMB->DataOffset = 0;
4350 	pSMB->SetupCount = 1;
4351 	pSMB->Reserved3 = 0;
4352 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4353 	byte_count = params + 1 /* pad */ ;
4354 	pSMB->TotalParameterCount = cpu_to_le16(params);
4355 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4356 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4357 	pSMB->Reserved4 = 0;
4358 	in_len += byte_count;
4359 	pSMB->ByteCount = cpu_to_le16(byte_count);
4360 
4361 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4362 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4363 	if (rc) {
4364 		cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
4365 	} else {		/* decode response */
4366 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4367 
4368 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4369 			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4370 			rc = smb_EIO2(smb_eio_trace_unixqpathinfo_bcc_too_small,
4371 				      get_bcc(&pSMBr->hdr), sizeof(FILE_UNIX_BASIC_INFO));
4372 		} else {
4373 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4374 			memcpy((char *) pFindData,
4375 			       (char *) &pSMBr->hdr.Protocol +
4376 			       data_offset,
4377 			       sizeof(FILE_UNIX_BASIC_INFO));
4378 		}
4379 	}
4380 	cifs_buf_release(pSMB);
4381 	if (rc == -EAGAIN)
4382 		goto UnixQPathInfoRetry;
4383 
4384 	return rc;
4385 }
4386 
4387 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4388 int
CIFSFindFirst(const unsigned int xid,struct cifs_tcon * tcon,const char * searchName,struct cifs_sb_info * cifs_sb,__u16 * pnetfid,__u16 search_flags,struct cifs_search_info * psrch_inf,bool msearch)4389 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4390 	      const char *searchName, struct cifs_sb_info *cifs_sb,
4391 	      __u16 *pnetfid, __u16 search_flags,
4392 	      struct cifs_search_info *psrch_inf, bool msearch)
4393 {
4394 /* level 257 SMB_ */
4395 	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4396 	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4397 	T2_FFIRST_RSP_PARMS *parms;
4398 	struct nls_table *nls_codepage;
4399 	unsigned int in_len, lnoff;
4400 	__u16 params, byte_count;
4401 	int bytes_returned = 0;
4402 	int name_len, remap;
4403 	int rc = 0;
4404 
4405 	cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4406 
4407 findFirstRetry:
4408 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4409 		      (void **) &pSMBr);
4410 	if (rc < 0)
4411 		return rc;
4412 	in_len = rc;
4413 
4414 	nls_codepage = cifs_sb->local_nls;
4415 	remap = cifs_remap(cifs_sb);
4416 
4417 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4418 		name_len =
4419 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4420 				       PATH_MAX, nls_codepage, remap);
4421 		/* We can not add the asterisk earlier in case
4422 		it got remapped to 0xF03A as if it were part of the
4423 		directory name instead of a wildcard */
4424 		name_len *= 2;
4425 		if (msearch) {
4426 			pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4427 			pSMB->FileName[name_len+1] = 0;
4428 			pSMB->FileName[name_len+2] = '*';
4429 			pSMB->FileName[name_len+3] = 0;
4430 			name_len += 4; /* now the trailing null */
4431 			/* null terminate just in case */
4432 			pSMB->FileName[name_len] = 0;
4433 			pSMB->FileName[name_len+1] = 0;
4434 			name_len += 2;
4435 		} else if (!searchName[0]) {
4436 			pSMB->FileName[0] = CIFS_DIR_SEP(cifs_sb);
4437 			pSMB->FileName[1] = 0;
4438 			pSMB->FileName[2] = 0;
4439 			pSMB->FileName[3] = 0;
4440 			name_len = 4;
4441 		}
4442 	} else {
4443 		name_len = copy_path_name(pSMB->FileName, searchName);
4444 		if (msearch) {
4445 			if (WARN_ON_ONCE(name_len > PATH_MAX-2))
4446 				name_len = PATH_MAX-2;
4447 			/* overwrite nul byte */
4448 			pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
4449 			pSMB->FileName[name_len] = '*';
4450 			pSMB->FileName[name_len+1] = 0;
4451 			name_len += 2;
4452 		} else if (!searchName[0]) {
4453 			pSMB->FileName[0] = CIFS_DIR_SEP(cifs_sb);
4454 			pSMB->FileName[1] = 0;
4455 			name_len = 2;
4456 		}
4457 	}
4458 
4459 	params = 12 + name_len /* includes null */ ;
4460 	pSMB->TotalDataCount = 0;	/* no EAs */
4461 	pSMB->MaxParameterCount = cpu_to_le16(10);
4462 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4463 	pSMB->MaxSetupCount = 0;
4464 	pSMB->Reserved = 0;
4465 	pSMB->Flags = 0;
4466 	pSMB->Timeout = 0;
4467 	pSMB->Reserved2 = 0;
4468 	byte_count = params + 1 /* pad */ ;
4469 	pSMB->TotalParameterCount = cpu_to_le16(params);
4470 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4471 	pSMB->ParameterOffset = cpu_to_le16(
4472 	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes));
4473 	pSMB->DataCount = 0;
4474 	pSMB->DataOffset = 0;
4475 	pSMB->SetupCount = 1;	/* one byte, no need to make endian neutral */
4476 	pSMB->Reserved3 = 0;
4477 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4478 	pSMB->SearchAttributes =
4479 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4480 			ATTR_DIRECTORY);
4481 	pSMB->SearchCount = cpu_to_le16(msearch ? CIFSMaxBufSize/sizeof(FILE_UNIX_INFO) : 1);
4482 	pSMB->SearchFlags = cpu_to_le16(search_flags);
4483 	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4484 
4485 	/* BB what should we set StorageType to? Does it matter? BB */
4486 	pSMB->SearchStorageType = 0;
4487 	in_len += byte_count;
4488 	pSMB->ByteCount = cpu_to_le16(byte_count);
4489 
4490 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4491 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4492 	cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4493 
4494 	if (rc) {
4495 		/*
4496 		 * BB: add logic to retry regular search if Unix search rejected
4497 		 * unexpectedly by server.
4498 		 */
4499 		/* BB: add code to handle unsupported level rc */
4500 		cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4501 		cifs_buf_release(pSMB);
4502 		/*
4503 		 * BB: eventually could optimize out free and realloc of buf for
4504 		 * this case.
4505 		 */
4506 		if (rc == -EAGAIN)
4507 			goto findFirstRetry;
4508 		return rc;
4509 	}
4510 	/* decode response */
4511 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4512 	if (rc) {
4513 		cifs_buf_release(pSMB);
4514 		return rc;
4515 	}
4516 
4517 	psrch_inf->unicode = !!(pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);
4518 	psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4519 	psrch_inf->smallBuf = false;
4520 	psrch_inf->srch_entries_start = (char *)&pSMBr->hdr.Protocol +
4521 		le16_to_cpu(pSMBr->t2.DataOffset);
4522 
4523 	parms = (T2_FFIRST_RSP_PARMS *)((char *)&pSMBr->hdr.Protocol +
4524 					le16_to_cpu(pSMBr->t2.ParameterOffset));
4525 	psrch_inf->endOfSearch = !!parms->EndofSearch;
4526 
4527 	psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
4528 	psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4529 		psrch_inf->entries_in_buffer;
4530 	lnoff = le16_to_cpu(parms->LastNameOffset);
4531 	if (CIFSMaxBufSize < lnoff) {
4532 		cifs_dbg(VFS, "ignoring corrupt resume name\n");
4533 		psrch_inf->last_entry = NULL;
4534 	} else {
4535 		psrch_inf->last_entry = psrch_inf->srch_entries_start + lnoff;
4536 		if (pnetfid)
4537 			*pnetfid = parms->SearchHandle;
4538 	}
4539 	return 0;
4540 }
4541 
CIFSFindNext(const unsigned int xid,struct cifs_tcon * tcon,__u16 searchHandle,__u16 search_flags,struct cifs_search_info * psrch_inf)4542 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4543 		 __u16 searchHandle, __u16 search_flags,
4544 		 struct cifs_search_info *psrch_inf)
4545 {
4546 	TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4547 	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4548 	T2_FNEXT_RSP_PARMS *parms;
4549 	unsigned int name_len, in_len;
4550 	unsigned int lnoff;
4551 	__u16 params, byte_count;
4552 	char *response_data;
4553 	int bytes_returned;
4554 	int rc = 0;
4555 
4556 	cifs_dbg(FYI, "In FindNext\n");
4557 
4558 	if (psrch_inf->endOfSearch)
4559 		return -ENOENT;
4560 
4561 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4562 		(void **) &pSMBr);
4563 	if (rc < 0)
4564 		return rc;
4565 	in_len = rc;
4566 
4567 	params = 14; /* includes 2 bytes of null string, converted to LE below*/
4568 	byte_count = 0;
4569 	pSMB->TotalDataCount = 0;       /* no EAs */
4570 	pSMB->MaxParameterCount = cpu_to_le16(8);
4571 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4572 	pSMB->MaxSetupCount = 0;
4573 	pSMB->Reserved = 0;
4574 	pSMB->Flags = 0;
4575 	pSMB->Timeout = 0;
4576 	pSMB->Reserved2 = 0;
4577 	pSMB->ParameterOffset =  cpu_to_le16(
4578 	      offsetof(struct smb_com_transaction2_fnext_req, SearchHandle));
4579 	pSMB->DataCount = 0;
4580 	pSMB->DataOffset = 0;
4581 	pSMB->SetupCount = 1;
4582 	pSMB->Reserved3 = 0;
4583 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4584 	pSMB->SearchHandle = searchHandle;      /* always kept as le */
4585 	pSMB->SearchCount =
4586 		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4587 	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4588 	pSMB->ResumeKey = psrch_inf->resume_key;
4589 	pSMB->SearchFlags = cpu_to_le16(search_flags);
4590 
4591 	name_len = psrch_inf->resume_name_len;
4592 	params += name_len;
4593 	if (name_len < PATH_MAX) {
4594 		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4595 		byte_count += name_len;
4596 		/* 14 byte parm len above enough for 2 byte null terminator */
4597 		pSMB->ResumeFileName[name_len] = 0;
4598 		pSMB->ResumeFileName[name_len+1] = 0;
4599 	} else {
4600 		cifs_buf_release(pSMB);
4601 		return -EINVAL;
4602 	}
4603 	byte_count = params + 1 /* pad */ ;
4604 	pSMB->TotalParameterCount = cpu_to_le16(params);
4605 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4606 	in_len += byte_count;
4607 	pSMB->ByteCount = cpu_to_le16(byte_count);
4608 
4609 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4610 			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4611 	cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4612 
4613 	if (rc) {
4614 		cifs_buf_release(pSMB);
4615 		if (rc == -EBADF) {
4616 			psrch_inf->endOfSearch = true;
4617 			rc = 0; /* search probably was closed at end of search*/
4618 		} else {
4619 			cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4620 		}
4621 		return rc;
4622 	}
4623 
4624 	/* decode response */
4625 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4626 	if (rc) {
4627 		cifs_buf_release(pSMB);
4628 		return rc;
4629 	}
4630 	/* BB fixme add lock for file (srch_info) struct here */
4631 	psrch_inf->unicode = !!(pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);
4632 	response_data = (char *)&pSMBr->hdr.Protocol +
4633 		le16_to_cpu(pSMBr->t2.ParameterOffset);
4634 	parms = (T2_FNEXT_RSP_PARMS *)response_data;
4635 	response_data = (char *)&pSMBr->hdr.Protocol +
4636 		le16_to_cpu(pSMBr->t2.DataOffset);
4637 
4638 	if (psrch_inf->smallBuf)
4639 		cifs_small_buf_release(psrch_inf->ntwrk_buf_start);
4640 	else
4641 		cifs_buf_release(psrch_inf->ntwrk_buf_start);
4642 
4643 	psrch_inf->srch_entries_start = response_data;
4644 	psrch_inf->ntwrk_buf_start = (char *)pSMB;
4645 	psrch_inf->smallBuf = false;
4646 	psrch_inf->endOfSearch = !!parms->EndofSearch;
4647 	psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
4648 	psrch_inf->index_of_last_entry += psrch_inf->entries_in_buffer;
4649 	lnoff = le16_to_cpu(parms->LastNameOffset);
4650 	if (CIFSMaxBufSize < lnoff) {
4651 		cifs_dbg(VFS, "ignoring corrupt resume name\n");
4652 		psrch_inf->last_entry = NULL;
4653 	} else {
4654 		psrch_inf->last_entry =
4655 			psrch_inf->srch_entries_start + lnoff;
4656 	}
4657 	/* BB fixme add unlock here */
4658 
4659 	/*
4660 	 * BB: On error, should we leave previous search buf
4661 	 * (and count and last entry fields) intact or free the previous one?
4662 	 *
4663 	 * Note: On -EAGAIN error only caller can retry on handle based calls
4664 	 * since file handle passed in no longer valid.
4665 	 */
4666 	return 0;
4667 }
4668 
4669 int
CIFSFindClose(const unsigned int xid,struct cifs_tcon * tcon,const __u16 searchHandle)4670 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4671 	      const __u16 searchHandle)
4672 {
4673 	int rc = 0;
4674 	FINDCLOSE_REQ *pSMB = NULL;
4675 	unsigned int in_len;
4676 
4677 	cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4678 	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4679 
4680 	/* no sense returning error if session restarted
4681 		as file handle has been closed */
4682 	if (rc == -EAGAIN)
4683 		return 0;
4684 	if (rc < 0)
4685 		return rc;
4686 	in_len = rc;
4687 
4688 	pSMB->FileID = searchHandle;
4689 	pSMB->ByteCount = 0;
4690 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
4691 	cifs_small_buf_release(pSMB);
4692 	if (rc)
4693 		cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4694 
4695 	cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4696 
4697 	/* Since session is dead, search handle closed on server already */
4698 	if (rc == -EAGAIN)
4699 		rc = 0;
4700 
4701 	return rc;
4702 }
4703 
4704 int
CIFSGetSrvInodeNumber(const unsigned int xid,struct cifs_tcon * tcon,const char * search_name,__u64 * inode_number,const struct nls_table * nls_codepage,int remap)4705 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4706 		      const char *search_name, __u64 *inode_number,
4707 		      const struct nls_table *nls_codepage, int remap)
4708 {
4709 	int rc = 0;
4710 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4711 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4712 	unsigned int in_len;
4713 	int name_len, bytes_returned;
4714 	__u16 params, byte_count;
4715 
4716 	cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4717 	if (tcon == NULL)
4718 		return -ENODEV;
4719 
4720 GetInodeNumberRetry:
4721 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4722 		      (void **) &pSMBr);
4723 	if (rc < 0)
4724 		return rc;
4725 	in_len = rc;
4726 
4727 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4728 		name_len =
4729 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4730 					   search_name, PATH_MAX, nls_codepage,
4731 					   remap);
4732 		name_len++;     /* trailing null */
4733 		name_len *= 2;
4734 	} else {
4735 		name_len = copy_path_name(pSMB->FileName, search_name);
4736 	}
4737 
4738 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4739 	pSMB->TotalDataCount = 0;
4740 	pSMB->MaxParameterCount = cpu_to_le16(2);
4741 	/* BB find exact max data count below from sess structure BB */
4742 	pSMB->MaxDataCount = cpu_to_le16(4000);
4743 	pSMB->MaxSetupCount = 0;
4744 	pSMB->Reserved = 0;
4745 	pSMB->Flags = 0;
4746 	pSMB->Timeout = 0;
4747 	pSMB->Reserved2 = 0;
4748 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4749 		struct smb_com_transaction2_qpi_req, InformationLevel));
4750 	pSMB->DataCount = 0;
4751 	pSMB->DataOffset = 0;
4752 	pSMB->SetupCount = 1;
4753 	pSMB->Reserved3 = 0;
4754 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4755 	byte_count = params + 1 /* pad */ ;
4756 	pSMB->TotalParameterCount = cpu_to_le16(params);
4757 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4758 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4759 	pSMB->Reserved4 = 0;
4760 	in_len += byte_count;
4761 	pSMB->ByteCount = cpu_to_le16(byte_count);
4762 
4763 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4764 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4765 	if (rc) {
4766 		cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4767 	} else {
4768 		/* decode response */
4769 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4770 		/* BB also check enough total bytes returned */
4771 		if (rc || get_bcc(&pSMBr->hdr) < 2)
4772 			/* If rc should we check for EOPNOSUPP and
4773 			disable the srvino flag? or in caller? */
4774 			rc = smb_EIO2(smb_eio_trace_getsrvinonum_bcc_too_small,
4775 				      get_bcc(&pSMBr->hdr), 2);
4776 		else {
4777 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4778 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4779 			struct file_internal_info *pfinfo;
4780 			/* BB Do we need a cast or hash here ? */
4781 			if (count < 8) {
4782 				cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
4783 				rc = smb_EIO2(smb_eio_trace_getsrvinonum_size,
4784 					      count, 8);
4785 				goto GetInodeNumOut;
4786 			}
4787 			pfinfo = (struct file_internal_info *)
4788 				(data_offset + (char *) &pSMBr->hdr.Protocol);
4789 			*inode_number = le64_to_cpu(pfinfo->UniqueId);
4790 		}
4791 	}
4792 GetInodeNumOut:
4793 	cifs_buf_release(pSMB);
4794 	if (rc == -EAGAIN)
4795 		goto GetInodeNumberRetry;
4796 	return rc;
4797 }
4798 
4799 int
CIFSGetDFSRefer(const unsigned int xid,struct cifs_ses * ses,const char * search_name,struct dfs_info3_param ** target_nodes,unsigned int * num_of_nodes,const struct nls_table * nls_codepage,int remap)4800 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4801 		const char *search_name, struct dfs_info3_param **target_nodes,
4802 		unsigned int *num_of_nodes,
4803 		const struct nls_table *nls_codepage, int remap)
4804 {
4805 /* TRANS2_GET_DFS_REFERRAL */
4806 	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4807 	TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4808 	unsigned int in_len;
4809 	int rc = 0;
4810 	int bytes_returned;
4811 	int name_len;
4812 	__u16 params, byte_count;
4813 	*num_of_nodes = 0;
4814 	*target_nodes = NULL;
4815 
4816 	cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4817 	if (ses == NULL || ses->tcon_ipc == NULL)
4818 		return -ENODEV;
4819 
4820 getDFSRetry:
4821 	/*
4822 	 * Use smb_init_no_reconnect() instead of smb_init() as
4823 	 * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
4824 	 * causing an infinite recursion.
4825 	 */
4826 	rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
4827 		      (void **)&pSMB, (void **)&pSMBr);
4828 	if (rc < 0)
4829 		return rc;
4830 	in_len = rc;
4831 
4832 	/* server pointer checked in called function,
4833 	but should never be null here anyway */
4834 	pSMB->hdr.Mid = get_next_mid(ses->server);
4835 	pSMB->hdr.Tid = ses->tcon_ipc->tid;
4836 	pSMB->hdr.Uid = ses->Suid;
4837 	if (ses->capabilities & CAP_STATUS32)
4838 		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4839 	if (ses->capabilities & CAP_DFS)
4840 		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4841 
4842 	if (ses->capabilities & CAP_UNICODE) {
4843 		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4844 		name_len =
4845 		    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4846 				       search_name, PATH_MAX, nls_codepage,
4847 				       remap);
4848 		name_len++;	/* trailing null */
4849 		name_len *= 2;
4850 	} else {	/* BB improve the check for buffer overruns BB */
4851 		name_len = copy_path_name(pSMB->RequestFileName, search_name);
4852 	}
4853 
4854 	if (ses->server->sign)
4855 		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4856 
4857 	pSMB->hdr.Uid = ses->Suid;
4858 
4859 	params = 2 /* level */  + name_len /*includes null */ ;
4860 	pSMB->TotalDataCount = 0;
4861 	pSMB->DataCount = 0;
4862 	pSMB->DataOffset = 0;
4863 	pSMB->MaxParameterCount = 0;
4864 	/* BB find exact max SMB PDU from sess structure BB */
4865 	pSMB->MaxDataCount = cpu_to_le16(4000);
4866 	pSMB->MaxSetupCount = 0;
4867 	pSMB->Reserved = 0;
4868 	pSMB->Flags = 0;
4869 	pSMB->Timeout = 0;
4870 	pSMB->Reserved2 = 0;
4871 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4872 	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel));
4873 	pSMB->SetupCount = 1;
4874 	pSMB->Reserved3 = 0;
4875 	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4876 	byte_count = params + 3 /* pad */ ;
4877 	pSMB->ParameterCount = cpu_to_le16(params);
4878 	pSMB->TotalParameterCount = pSMB->ParameterCount;
4879 	pSMB->MaxReferralLevel = cpu_to_le16(3);
4880 	in_len += byte_count;
4881 	pSMB->ByteCount = cpu_to_le16(byte_count);
4882 
4883 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, in_len,
4884 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4885 	if (rc) {
4886 		cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4887 		goto GetDFSRefExit;
4888 	}
4889 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4890 
4891 	/* BB Also check if enough total bytes returned? */
4892 	if (rc || get_bcc(&pSMBr->hdr) < 17) {
4893 		rc = smb_EIO2(smb_eio_trace_getdfsrefer_bcc_too_small,
4894 			      get_bcc(&pSMBr->hdr), 17);
4895 		goto GetDFSRefExit;
4896 	}
4897 
4898 	cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d  Offset %d\n",
4899 		 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4900 
4901 	/* parse returned result into more usable form */
4902 	rc = parse_dfs_referrals(&pSMBr->dfs_data,
4903 				 le16_to_cpu(pSMBr->t2.DataCount),
4904 				 num_of_nodes, target_nodes, nls_codepage,
4905 				 remap, search_name,
4906 				 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4907 
4908 GetDFSRefExit:
4909 	cifs_buf_release(pSMB);
4910 
4911 	if (rc == -EAGAIN)
4912 		goto getDFSRetry;
4913 
4914 	return rc;
4915 }
4916 
4917 /* Query File System Info such as free space to old servers such as Win 9x */
4918 int
SMBOldQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4919 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4920 	      struct kstatfs *FSData)
4921 {
4922 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4923 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4924 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4925 	FILE_SYSTEM_ALLOC_INFO *response_data;
4926 	unsigned int in_len;
4927 	int rc = 0;
4928 	int bytes_returned = 0;
4929 	__u16 params, byte_count;
4930 
4931 	cifs_dbg(FYI, "OldQFSInfo\n");
4932 oldQFSInfoRetry:
4933 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4934 		(void **) &pSMBr);
4935 	if (rc < 0)
4936 		return rc;
4937 	in_len = rc;
4938 
4939 	params = 2;     /* level */
4940 	pSMB->TotalDataCount = 0;
4941 	pSMB->MaxParameterCount = cpu_to_le16(2);
4942 	pSMB->MaxDataCount = cpu_to_le16(1000);
4943 	pSMB->MaxSetupCount = 0;
4944 	pSMB->Reserved = 0;
4945 	pSMB->Flags = 0;
4946 	pSMB->Timeout = 0;
4947 	pSMB->Reserved2 = 0;
4948 	byte_count = params + 1 /* pad */ ;
4949 	pSMB->TotalParameterCount = cpu_to_le16(params);
4950 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4951 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4952 		struct smb_com_transaction2_qfsi_req, InformationLevel));
4953 	pSMB->DataCount = 0;
4954 	pSMB->DataOffset = 0;
4955 	pSMB->SetupCount = 1;
4956 	pSMB->Reserved3 = 0;
4957 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4958 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4959 	in_len += byte_count;
4960 	pSMB->ByteCount = cpu_to_le16(byte_count);
4961 
4962 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
4963 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4964 	if (rc) {
4965 		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4966 	} else {                /* decode response */
4967 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4968 
4969 		if (rc || get_bcc(&pSMBr->hdr) < 18)
4970 			rc = smb_EIO2(smb_eio_trace_oldqfsinfo_bcc_too_small,
4971 				      get_bcc(&pSMBr->hdr), 18);
4972 		else {
4973 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4974 			cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d\n",
4975 				 get_bcc(&pSMBr->hdr), data_offset);
4976 
4977 			response_data = (FILE_SYSTEM_ALLOC_INFO *)
4978 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
4979 			FSData->f_bsize =
4980 				le16_to_cpu(response_data->BytesPerSector) *
4981 				le32_to_cpu(response_data->
4982 					SectorsPerAllocationUnit);
4983 			/*
4984 			 * much prefer larger but if server doesn't report
4985 			 * a valid size than 4K is a reasonable minimum
4986 			 */
4987 			if (FSData->f_bsize < 512)
4988 				FSData->f_bsize = 4096;
4989 
4990 			FSData->f_blocks =
4991 			       le32_to_cpu(response_data->TotalAllocationUnits);
4992 			FSData->f_bfree = FSData->f_bavail =
4993 				le32_to_cpu(response_data->FreeAllocationUnits);
4994 			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
4995 				 (unsigned long long)FSData->f_blocks,
4996 				 (unsigned long long)FSData->f_bfree,
4997 				 FSData->f_bsize);
4998 		}
4999 	}
5000 	cifs_buf_release(pSMB);
5001 
5002 	if (rc == -EAGAIN)
5003 		goto oldQFSInfoRetry;
5004 
5005 	return rc;
5006 }
5007 
5008 int
CIFSSMBQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5009 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5010 	       struct kstatfs *FSData)
5011 {
5012 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5013 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5014 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5015 	FILE_SYSTEM_SIZE_INFO *response_data;
5016 	unsigned int in_len;
5017 	int rc = 0;
5018 	int bytes_returned = 0;
5019 	__u16 params, byte_count;
5020 
5021 	cifs_dbg(FYI, "In QFSInfo\n");
5022 QFSInfoRetry:
5023 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5024 		      (void **) &pSMBr);
5025 	if (rc < 0)
5026 		return rc;
5027 	in_len = rc;
5028 
5029 	params = 2;	/* level */
5030 	pSMB->TotalDataCount = 0;
5031 	pSMB->MaxParameterCount = cpu_to_le16(2);
5032 	pSMB->MaxDataCount = cpu_to_le16(1000);
5033 	pSMB->MaxSetupCount = 0;
5034 	pSMB->Reserved = 0;
5035 	pSMB->Flags = 0;
5036 	pSMB->Timeout = 0;
5037 	pSMB->Reserved2 = 0;
5038 	byte_count = params + 1 /* pad */ ;
5039 	pSMB->TotalParameterCount = cpu_to_le16(params);
5040 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5041 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5042 		struct smb_com_transaction2_qfsi_req, InformationLevel));
5043 	pSMB->DataCount = 0;
5044 	pSMB->DataOffset = 0;
5045 	pSMB->SetupCount = 1;
5046 	pSMB->Reserved3 = 0;
5047 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5048 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5049 	in_len += byte_count;
5050 	pSMB->ByteCount = cpu_to_le16(byte_count);
5051 
5052 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5053 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5054 	if (rc) {
5055 		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5056 	} else {		/* decode response */
5057 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5058 
5059 		if (rc || get_bcc(&pSMBr->hdr) < 24)
5060 			rc = smb_EIO2(smb_eio_trace_qfsinfo_bcc_too_small,
5061 				      get_bcc(&pSMBr->hdr), 24);
5062 		else {
5063 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5064 
5065 			response_data =
5066 			    (FILE_SYSTEM_SIZE_INFO
5067 			     *) (((char *) &pSMBr->hdr.Protocol) +
5068 				 data_offset);
5069 			FSData->f_bsize =
5070 			    le32_to_cpu(response_data->BytesPerSector) *
5071 			    le32_to_cpu(response_data->
5072 					SectorsPerAllocationUnit);
5073 			/*
5074 			 * much prefer larger but if server doesn't report
5075 			 * a valid size than 4K is a reasonable minimum
5076 			 */
5077 			if (FSData->f_bsize < 512)
5078 				FSData->f_bsize = 4096;
5079 
5080 			FSData->f_blocks =
5081 			    le64_to_cpu(response_data->TotalAllocationUnits);
5082 			FSData->f_bfree = FSData->f_bavail =
5083 			    le64_to_cpu(response_data->AvailableAllocationUnits);
5084 			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
5085 				 (unsigned long long)FSData->f_blocks,
5086 				 (unsigned long long)FSData->f_bfree,
5087 				 FSData->f_bsize);
5088 		}
5089 	}
5090 	cifs_buf_release(pSMB);
5091 
5092 	if (rc == -EAGAIN)
5093 		goto QFSInfoRetry;
5094 
5095 	return rc;
5096 }
5097 
5098 int
CIFSSMBQFSAttributeInfo(const unsigned int xid,struct cifs_tcon * tcon)5099 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5100 {
5101 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5102 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5103 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5104 	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5105 	unsigned int in_len;
5106 	int rc = 0;
5107 	int bytes_returned = 0;
5108 	__u16 params, byte_count;
5109 
5110 	cifs_dbg(FYI, "In QFSAttributeInfo\n");
5111 QFSAttributeRetry:
5112 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5113 		      (void **) &pSMBr);
5114 	if (rc < 0)
5115 		return rc;
5116 	in_len = rc;
5117 
5118 	params = 2;	/* level */
5119 	pSMB->TotalDataCount = 0;
5120 	pSMB->MaxParameterCount = cpu_to_le16(2);
5121 	/* BB find exact max SMB PDU from sess structure BB */
5122 	pSMB->MaxDataCount = cpu_to_le16(1000);
5123 	pSMB->MaxSetupCount = 0;
5124 	pSMB->Reserved = 0;
5125 	pSMB->Flags = 0;
5126 	pSMB->Timeout = 0;
5127 	pSMB->Reserved2 = 0;
5128 	byte_count = params + 1 /* pad */ ;
5129 	pSMB->TotalParameterCount = cpu_to_le16(params);
5130 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5131 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5132 		struct smb_com_transaction2_qfsi_req, InformationLevel));
5133 	pSMB->DataCount = 0;
5134 	pSMB->DataOffset = 0;
5135 	pSMB->SetupCount = 1;
5136 	pSMB->Reserved3 = 0;
5137 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5138 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5139 	in_len += byte_count;
5140 	pSMB->ByteCount = cpu_to_le16(byte_count);
5141 
5142 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5143 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5144 	if (rc) {
5145 		cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5146 	} else {		/* decode response */
5147 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5148 
5149 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5150 			/* BB also check if enough bytes returned */
5151 			rc = smb_EIO2(smb_eio_trace_qfsattrinfo_bcc_too_small,
5152 				      get_bcc(&pSMBr->hdr), 13);
5153 		} else {
5154 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5155 			response_data =
5156 			    (FILE_SYSTEM_ATTRIBUTE_INFO
5157 			     *) (((char *) &pSMBr->hdr.Protocol) +
5158 				 data_offset);
5159 			memcpy(&tcon->fsAttrInfo, response_data,
5160 			       sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5161 		}
5162 	}
5163 	cifs_buf_release(pSMB);
5164 
5165 	if (rc == -EAGAIN)
5166 		goto QFSAttributeRetry;
5167 
5168 	return rc;
5169 }
5170 
5171 int
CIFSSMBQFSDeviceInfo(const unsigned int xid,struct cifs_tcon * tcon)5172 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5173 {
5174 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5175 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5176 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5177 	FILE_SYSTEM_DEVICE_INFO *response_data;
5178 	unsigned int in_len;
5179 	int rc = 0;
5180 	int bytes_returned = 0;
5181 	__u16 params, byte_count;
5182 
5183 	cifs_dbg(FYI, "In QFSDeviceInfo\n");
5184 QFSDeviceRetry:
5185 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5186 		      (void **) &pSMBr);
5187 	if (rc < 0)
5188 		return rc;
5189 	in_len = rc;
5190 
5191 	params = 2;	/* level */
5192 	pSMB->TotalDataCount = 0;
5193 	pSMB->MaxParameterCount = cpu_to_le16(2);
5194 	/* BB find exact max SMB PDU from sess structure BB */
5195 	pSMB->MaxDataCount = cpu_to_le16(1000);
5196 	pSMB->MaxSetupCount = 0;
5197 	pSMB->Reserved = 0;
5198 	pSMB->Flags = 0;
5199 	pSMB->Timeout = 0;
5200 	pSMB->Reserved2 = 0;
5201 	byte_count = params + 1 /* pad */ ;
5202 	pSMB->TotalParameterCount = cpu_to_le16(params);
5203 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5204 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5205 		struct smb_com_transaction2_qfsi_req, InformationLevel));
5206 
5207 	pSMB->DataCount = 0;
5208 	pSMB->DataOffset = 0;
5209 	pSMB->SetupCount = 1;
5210 	pSMB->Reserved3 = 0;
5211 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5212 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5213 	in_len += byte_count;
5214 	pSMB->ByteCount = cpu_to_le16(byte_count);
5215 
5216 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5217 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5218 	if (rc) {
5219 		cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5220 	} else {		/* decode response */
5221 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5222 
5223 		if (rc || get_bcc(&pSMBr->hdr) <
5224 			  sizeof(FILE_SYSTEM_DEVICE_INFO))
5225 			rc = smb_EIO2(smb_eio_trace_qfsdevinfo_bcc_too_small,
5226 				      get_bcc(&pSMBr->hdr),
5227 				      sizeof(FILE_SYSTEM_DEVICE_INFO));
5228 		else {
5229 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5230 			response_data =
5231 			    (FILE_SYSTEM_DEVICE_INFO *)
5232 				(((char *) &pSMBr->hdr.Protocol) +
5233 				 data_offset);
5234 			memcpy(&tcon->fsDevInfo, response_data,
5235 			       sizeof(FILE_SYSTEM_DEVICE_INFO));
5236 		}
5237 	}
5238 	cifs_buf_release(pSMB);
5239 
5240 	if (rc == -EAGAIN)
5241 		goto QFSDeviceRetry;
5242 
5243 	return rc;
5244 }
5245 
5246 int
CIFSSMBQFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon)5247 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5248 {
5249 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5250 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5251 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5252 	FILE_SYSTEM_UNIX_INFO *response_data;
5253 	unsigned int in_len;
5254 	int rc = 0;
5255 	int bytes_returned = 0;
5256 	__u16 params, byte_count;
5257 
5258 	cifs_dbg(FYI, "In QFSUnixInfo\n");
5259 QFSUnixRetry:
5260 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5261 				   (void **) &pSMB, (void **) &pSMBr);
5262 	if (rc < 0)
5263 		return rc;
5264 	in_len = rc;
5265 
5266 	params = 2;	/* level */
5267 	pSMB->TotalDataCount = 0;
5268 	pSMB->DataCount = 0;
5269 	pSMB->DataOffset = 0;
5270 	pSMB->MaxParameterCount = cpu_to_le16(2);
5271 	/* BB find exact max SMB PDU from sess structure BB */
5272 	pSMB->MaxDataCount = cpu_to_le16(100);
5273 	pSMB->MaxSetupCount = 0;
5274 	pSMB->Reserved = 0;
5275 	pSMB->Flags = 0;
5276 	pSMB->Timeout = 0;
5277 	pSMB->Reserved2 = 0;
5278 	byte_count = params + 1 /* pad */ ;
5279 	pSMB->ParameterCount = cpu_to_le16(params);
5280 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5281 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5282 			smb_com_transaction2_qfsi_req, InformationLevel));
5283 	pSMB->SetupCount = 1;
5284 	pSMB->Reserved3 = 0;
5285 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5286 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5287 	in_len += byte_count;
5288 	pSMB->ByteCount = cpu_to_le16(byte_count);
5289 
5290 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5291 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5292 	if (rc) {
5293 		cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5294 	} else {		/* decode response */
5295 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5296 
5297 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5298 			rc = smb_EIO2(smb_eio_trace_qfsunixinfo_bcc_too_small,
5299 				      get_bcc(&pSMBr->hdr), 13);
5300 		} else {
5301 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5302 			response_data =
5303 			    (FILE_SYSTEM_UNIX_INFO
5304 			     *) (((char *) &pSMBr->hdr.Protocol) +
5305 				 data_offset);
5306 			memcpy(&tcon->fsUnixInfo, response_data,
5307 			       sizeof(FILE_SYSTEM_UNIX_INFO));
5308 		}
5309 	}
5310 	cifs_buf_release(pSMB);
5311 
5312 	if (rc == -EAGAIN)
5313 		goto QFSUnixRetry;
5314 
5315 
5316 	return rc;
5317 }
5318 
5319 int
CIFSSMBSetFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon,__u64 cap)5320 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5321 {
5322 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5323 	TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5324 	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5325 	unsigned int in_len;
5326 	int rc = 0;
5327 	int bytes_returned = 0;
5328 	__u16 params, param_offset, offset, byte_count;
5329 
5330 	cifs_dbg(FYI, "In SETFSUnixInfo\n");
5331 SETFSUnixRetry:
5332 	/* BB switch to small buf init to save memory */
5333 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5334 					(void **) &pSMB, (void **) &pSMBr);
5335 	if (rc < 0)
5336 		return rc;
5337 	in_len = rc;
5338 
5339 	params = 4;	/* 2 bytes zero followed by info level. */
5340 	pSMB->MaxSetupCount = 0;
5341 	pSMB->Reserved = 0;
5342 	pSMB->Flags = 0;
5343 	pSMB->Timeout = 0;
5344 	pSMB->Reserved2 = 0;
5345 	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum);
5346 	offset = param_offset + params;
5347 
5348 	pSMB->MaxParameterCount = cpu_to_le16(4);
5349 	/* BB find exact max SMB PDU from sess structure BB */
5350 	pSMB->MaxDataCount = cpu_to_le16(100);
5351 	pSMB->SetupCount = 1;
5352 	pSMB->Reserved3 = 0;
5353 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5354 	byte_count = 1 /* pad */ + params + 12;
5355 
5356 	pSMB->DataCount = cpu_to_le16(12);
5357 	pSMB->ParameterCount = cpu_to_le16(params);
5358 	pSMB->TotalDataCount = pSMB->DataCount;
5359 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5360 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5361 	pSMB->DataOffset = cpu_to_le16(offset);
5362 
5363 	/* Params. */
5364 	pSMB->FileNum = 0;
5365 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5366 
5367 	/* Data. */
5368 	pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5369 	pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5370 	pSMB->ClientUnixCap = cpu_to_le64(cap);
5371 
5372 	in_len += byte_count;
5373 	pSMB->ByteCount = cpu_to_le16(byte_count);
5374 
5375 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5376 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5377 	if (rc) {
5378 		cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5379 	} else {		/* decode response */
5380 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5381 		if (rc)
5382 			rc = -EIO;	/* bad smb */
5383 	}
5384 	cifs_buf_release(pSMB);
5385 
5386 	if (rc == -EAGAIN)
5387 		goto SETFSUnixRetry;
5388 
5389 	return rc;
5390 }
5391 
5392 
5393 
5394 int
CIFSSMBQFSPosixInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5395 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5396 		   struct kstatfs *FSData)
5397 {
5398 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5399 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5400 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5401 	FILE_SYSTEM_POSIX_INFO *response_data;
5402 	unsigned int in_len;
5403 	int rc = 0;
5404 	int bytes_returned = 0;
5405 	__u16 params, byte_count;
5406 
5407 	cifs_dbg(FYI, "In QFSPosixInfo\n");
5408 QFSPosixRetry:
5409 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5410 		      (void **) &pSMBr);
5411 	if (rc < 0)
5412 		return rc;
5413 	in_len = rc;
5414 
5415 	params = 2;	/* level */
5416 	pSMB->TotalDataCount = 0;
5417 	pSMB->DataCount = 0;
5418 	pSMB->DataOffset = 0;
5419 	pSMB->MaxParameterCount = cpu_to_le16(2);
5420 	/* BB find exact max SMB PDU from sess structure BB */
5421 	pSMB->MaxDataCount = cpu_to_le16(100);
5422 	pSMB->MaxSetupCount = 0;
5423 	pSMB->Reserved = 0;
5424 	pSMB->Flags = 0;
5425 	pSMB->Timeout = 0;
5426 	pSMB->Reserved2 = 0;
5427 	byte_count = params + 1 /* pad */ ;
5428 	pSMB->ParameterCount = cpu_to_le16(params);
5429 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5430 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5431 			smb_com_transaction2_qfsi_req, InformationLevel));
5432 	pSMB->SetupCount = 1;
5433 	pSMB->Reserved3 = 0;
5434 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5435 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5436 	in_len += byte_count;
5437 	pSMB->ByteCount = cpu_to_le16(byte_count);
5438 
5439 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5440 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5441 	if (rc) {
5442 		cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5443 	} else {		/* decode response */
5444 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5445 
5446 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5447 			rc = smb_EIO2(smb_eio_trace_qfsposixinfo_bcc_too_small,
5448 				      get_bcc(&pSMBr->hdr), 13);
5449 		} else {
5450 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5451 			response_data =
5452 			    (FILE_SYSTEM_POSIX_INFO
5453 			     *) (((char *) &pSMBr->hdr.Protocol) +
5454 				 data_offset);
5455 			FSData->f_bsize =
5456 					le32_to_cpu(response_data->BlockSize);
5457 			/*
5458 			 * much prefer larger but if server doesn't report
5459 			 * a valid size than 4K is a reasonable minimum
5460 			 */
5461 			if (FSData->f_bsize < 512)
5462 				FSData->f_bsize = 4096;
5463 
5464 			FSData->f_blocks =
5465 					le64_to_cpu(response_data->TotalBlocks);
5466 			FSData->f_bfree =
5467 			    le64_to_cpu(response_data->BlocksAvail);
5468 			if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5469 				FSData->f_bavail = FSData->f_bfree;
5470 			} else {
5471 				FSData->f_bavail =
5472 				    le64_to_cpu(response_data->UserBlocksAvail);
5473 			}
5474 			if (response_data->TotalFileNodes != cpu_to_le64(-1))
5475 				FSData->f_files =
5476 				     le64_to_cpu(response_data->TotalFileNodes);
5477 			if (response_data->FreeFileNodes != cpu_to_le64(-1))
5478 				FSData->f_ffree =
5479 				      le64_to_cpu(response_data->FreeFileNodes);
5480 		}
5481 	}
5482 	cifs_buf_release(pSMB);
5483 
5484 	if (rc == -EAGAIN)
5485 		goto QFSPosixRetry;
5486 
5487 	return rc;
5488 }
5489 
5490 
5491 /*
5492  * We can not use write of zero bytes trick to set file size due to need for
5493  * large file support. Also note that this SetPathInfo is preferred to
5494  * SetFileInfo based method in next routine which is only needed to work around
5495  * a sharing violation bugin Samba which this routine can run into.
5496  */
5497 int
CIFSSMBSetEOF(const unsigned int xid,struct cifs_tcon * tcon,const char * file_name,__u64 size,struct cifs_sb_info * cifs_sb,bool set_allocation,struct dentry * dentry)5498 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5499 	      const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5500 	      bool set_allocation, struct dentry *dentry)
5501 {
5502 	struct smb_com_transaction2_spi_req *pSMB = NULL;
5503 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5504 	struct file_end_of_file_info *parm_data;
5505 	unsigned int in_len;
5506 	int name_len;
5507 	int rc = 0;
5508 	int bytes_returned = 0;
5509 	int remap = cifs_remap(cifs_sb);
5510 
5511 	__u16 params, byte_count, data_count, param_offset, offset;
5512 
5513 	cifs_dbg(FYI, "In SetEOF\n");
5514 SetEOFRetry:
5515 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5516 		      (void **) &pSMBr);
5517 	if (rc < 0)
5518 		return rc;
5519 	in_len = rc;
5520 
5521 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5522 		name_len =
5523 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5524 				       PATH_MAX, cifs_sb->local_nls, remap);
5525 		name_len++;	/* trailing null */
5526 		name_len *= 2;
5527 	} else {
5528 		name_len = copy_path_name(pSMB->FileName, file_name);
5529 	}
5530 	params = 6 + name_len;
5531 	data_count = sizeof(struct file_end_of_file_info);
5532 	pSMB->MaxParameterCount = cpu_to_le16(2);
5533 	pSMB->MaxDataCount = cpu_to_le16(4100);
5534 	pSMB->MaxSetupCount = 0;
5535 	pSMB->Reserved = 0;
5536 	pSMB->Flags = 0;
5537 	pSMB->Timeout = 0;
5538 	pSMB->Reserved2 = 0;
5539 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5540 				InformationLevel);
5541 	offset = param_offset + params;
5542 	if (set_allocation) {
5543 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5544 			pSMB->InformationLevel =
5545 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5546 		else
5547 			pSMB->InformationLevel =
5548 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5549 	} else /* Set File Size */  {
5550 	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5551 		    pSMB->InformationLevel =
5552 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5553 	    else
5554 		    pSMB->InformationLevel =
5555 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5556 	}
5557 
5558 	parm_data =
5559 	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5560 				       offset);
5561 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5562 	pSMB->DataOffset = cpu_to_le16(offset);
5563 	pSMB->SetupCount = 1;
5564 	pSMB->Reserved3 = 0;
5565 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5566 	byte_count = 3 /* pad */  + params + data_count;
5567 	pSMB->DataCount = cpu_to_le16(data_count);
5568 	pSMB->TotalDataCount = pSMB->DataCount;
5569 	pSMB->ParameterCount = cpu_to_le16(params);
5570 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5571 	pSMB->Reserved4 = 0;
5572 	in_len += byte_count;
5573 	parm_data->FileSize = cpu_to_le64(size);
5574 	pSMB->ByteCount = cpu_to_le16(byte_count);
5575 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5576 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5577 	if (rc)
5578 		cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5579 
5580 	cifs_buf_release(pSMB);
5581 
5582 	if (rc == -EAGAIN)
5583 		goto SetEOFRetry;
5584 
5585 	return rc;
5586 }
5587 
5588 int
CIFSSMBSetFileSize(const unsigned int xid,struct cifs_tcon * tcon,struct cifsFileInfo * cfile,__u64 size,bool set_allocation)5589 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5590 		   struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5591 {
5592 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5593 	struct file_end_of_file_info *parm_data;
5594 	unsigned int in_len;
5595 	int rc = 0;
5596 	__u16 params, param_offset, offset, byte_count, count;
5597 
5598 	cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5599 		 (long long)size);
5600 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5601 	if (rc < 0)
5602 		return rc;
5603 	in_len = rc;
5604 
5605 	pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5606 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5607 
5608 	params = 6;
5609 	pSMB->MaxSetupCount = 0;
5610 	pSMB->Reserved = 0;
5611 	pSMB->Flags = 0;
5612 	pSMB->Timeout = 0;
5613 	pSMB->Reserved2 = 0;
5614 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
5615 	offset = param_offset + params;
5616 
5617 	count = sizeof(struct file_end_of_file_info);
5618 	pSMB->MaxParameterCount = cpu_to_le16(2);
5619 	/* BB find exact max SMB PDU from sess structure BB */
5620 	pSMB->MaxDataCount = cpu_to_le16(1000);
5621 	pSMB->SetupCount = 1;
5622 	pSMB->Reserved3 = 0;
5623 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5624 	byte_count = 3 /* pad */  + params + count;
5625 	pSMB->DataCount = cpu_to_le16(count);
5626 	pSMB->ParameterCount = cpu_to_le16(params);
5627 	pSMB->TotalDataCount = pSMB->DataCount;
5628 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5629 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5630 	parm_data =
5631 		(struct file_end_of_file_info *)(((char *)pSMB) + offset);
5632 	pSMB->DataOffset = cpu_to_le16(offset);
5633 	parm_data->FileSize = cpu_to_le64(size);
5634 	pSMB->Fid = cfile->fid.netfid;
5635 	if (set_allocation) {
5636 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5637 			pSMB->InformationLevel =
5638 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5639 		else
5640 			pSMB->InformationLevel =
5641 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5642 	} else /* Set File Size */  {
5643 	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5644 		    pSMB->InformationLevel =
5645 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5646 	    else
5647 		    pSMB->InformationLevel =
5648 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5649 	}
5650 	pSMB->Reserved4 = 0;
5651 	in_len += byte_count;
5652 	pSMB->ByteCount = cpu_to_le16(byte_count);
5653 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
5654 	cifs_small_buf_release(pSMB);
5655 	if (rc) {
5656 		cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5657 			 rc);
5658 	}
5659 
5660 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5661 		since file handle passed in no longer valid */
5662 
5663 	return rc;
5664 }
5665 
5666 int
SMBSetInformation(const unsigned int xid,struct cifs_tcon * tcon,const char * fileName,__le32 attributes,__le64 write_time,const struct nls_table * nls_codepage,struct cifs_sb_info * cifs_sb)5667 SMBSetInformation(const unsigned int xid, struct cifs_tcon *tcon,
5668 		  const char *fileName, __le32 attributes, __le64 write_time,
5669 		  const struct nls_table *nls_codepage,
5670 		  struct cifs_sb_info *cifs_sb)
5671 {
5672 	SETATTR_REQ *pSMB;
5673 	SETATTR_RSP *pSMBr;
5674 	struct timespec64 ts;
5675 	unsigned int in_len;
5676 	int bytes_returned;
5677 	int name_len;
5678 	int rc;
5679 
5680 	cifs_dbg(FYI, "In %s path %s\n", __func__, fileName);
5681 
5682 retry:
5683 	rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5684 		      (void **) &pSMBr);
5685 	if (rc < 0)
5686 		return rc;
5687 	in_len = rc;
5688 
5689 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5690 		name_len =
5691 			cifsConvertToUTF16((__le16 *) pSMB->fileName,
5692 					   fileName, PATH_MAX, nls_codepage,
5693 					   cifs_remap(cifs_sb));
5694 		name_len++;     /* trailing null */
5695 		name_len *= 2;
5696 	} else {
5697 		name_len = copy_path_name(pSMB->fileName, fileName);
5698 	}
5699 	/* Only few attributes can be set by this command, others are not accepted by Win9x. */
5700 	pSMB->attr = cpu_to_le16(le32_to_cpu(attributes) &
5701 			(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE));
5702 	/* Zero write time value (in both NT and SETATTR formats) means to not change it. */
5703 	if (le64_to_cpu(write_time) != 0) {
5704 		ts = cifs_NTtimeToUnix(write_time);
5705 		pSMB->last_write_time = cpu_to_le32(ts.tv_sec);
5706 	}
5707 	pSMB->BufferFormat = 0x04;
5708 	name_len++; /* account for buffer type byte */
5709 	in_len += name_len;
5710 	pSMB->ByteCount = cpu_to_le16(name_len);
5711 
5712 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5713 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5714 	if (rc)
5715 		cifs_dbg(FYI, "Send error in %s = %d\n", __func__, rc);
5716 
5717 	cifs_buf_release(pSMB);
5718 
5719 	if (rc == -EAGAIN)
5720 		goto retry;
5721 
5722 	return rc;
5723 }
5724 
5725 /* Some legacy servers such as NT4 require that the file times be set on
5726    an open handle, rather than by pathname - this is awkward due to
5727    potential access conflicts on the open, but it is unavoidable for these
5728    old servers since the only other choice is to go from 100 nanosecond DCE
5729    time and resort to the original setpathinfo level which takes the ancient
5730    DOS time format with 2 second granularity */
5731 int
CIFSSMBSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const FILE_BASIC_INFO * data,__u16 fid,__u32 pid_of_opener)5732 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5733 		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5734 {
5735 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5736 	unsigned int in_len;
5737 	char *data_offset;
5738 	int rc = 0;
5739 	__u16 params, param_offset, offset, byte_count, count;
5740 
5741 	cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5742 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5743 	if (rc < 0)
5744 		return rc;
5745 	in_len = rc;
5746 
5747 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5748 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5749 
5750 	params = 6;
5751 	pSMB->MaxSetupCount = 0;
5752 	pSMB->Reserved = 0;
5753 	pSMB->Flags = 0;
5754 	pSMB->Timeout = 0;
5755 	pSMB->Reserved2 = 0;
5756 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
5757 	offset = param_offset + params;
5758 
5759 	data_offset = (char *)pSMB + offset;
5760 
5761 	count = sizeof(FILE_BASIC_INFO);
5762 	pSMB->MaxParameterCount = cpu_to_le16(2);
5763 	/* BB find max SMB PDU from sess */
5764 	pSMB->MaxDataCount = cpu_to_le16(1000);
5765 	pSMB->SetupCount = 1;
5766 	pSMB->Reserved3 = 0;
5767 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5768 	byte_count = 3 /* pad */  + params + count;
5769 	pSMB->DataCount = cpu_to_le16(count);
5770 	pSMB->ParameterCount = cpu_to_le16(params);
5771 	pSMB->TotalDataCount = pSMB->DataCount;
5772 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5773 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5774 	pSMB->DataOffset = cpu_to_le16(offset);
5775 	pSMB->Fid = fid;
5776 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5777 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5778 	else
5779 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5780 	pSMB->Reserved4 = 0;
5781 	in_len += byte_count;
5782 	pSMB->ByteCount = cpu_to_le16(byte_count);
5783 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5784 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
5785 	cifs_small_buf_release(pSMB);
5786 	if (rc)
5787 		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5788 			 rc);
5789 
5790 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5791 		since file handle passed in no longer valid */
5792 
5793 	return rc;
5794 }
5795 
5796 int
CIFSSMBSetFileDisposition(const unsigned int xid,struct cifs_tcon * tcon,bool delete_file,__u16 fid,__u32 pid_of_opener)5797 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5798 			  bool delete_file, __u16 fid, __u32 pid_of_opener)
5799 {
5800 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5801 	unsigned int in_len;
5802 	char *data_offset;
5803 	int rc = 0;
5804 	__u16 params, param_offset, offset, byte_count, count;
5805 
5806 	cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5807 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5808 	if (rc < 0)
5809 		return rc;
5810 	in_len = rc;
5811 
5812 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5813 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5814 
5815 	params = 6;
5816 	pSMB->MaxSetupCount = 0;
5817 	pSMB->Reserved = 0;
5818 	pSMB->Flags = 0;
5819 	pSMB->Timeout = 0;
5820 	pSMB->Reserved2 = 0;
5821 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
5822 	offset = param_offset + params;
5823 	data_offset = (char *)(pSMB) + offset;
5824 
5825 	count = 1;
5826 	pSMB->MaxParameterCount = cpu_to_le16(2);
5827 	/* BB find max SMB PDU from sess */
5828 	pSMB->MaxDataCount = cpu_to_le16(1000);
5829 	pSMB->SetupCount = 1;
5830 	pSMB->Reserved3 = 0;
5831 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5832 	byte_count = 3 /* pad */  + params + count;
5833 	pSMB->DataCount = cpu_to_le16(count);
5834 	pSMB->ParameterCount = cpu_to_le16(params);
5835 	pSMB->TotalDataCount = pSMB->DataCount;
5836 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5837 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5838 	pSMB->DataOffset = cpu_to_le16(offset);
5839 	pSMB->Fid = fid;
5840 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5841 	pSMB->Reserved4 = 0;
5842 	in_len += byte_count;
5843 	pSMB->ByteCount = cpu_to_le16(byte_count);
5844 	*data_offset = delete_file ? 1 : 0;
5845 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
5846 	cifs_small_buf_release(pSMB);
5847 	if (rc)
5848 		cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5849 
5850 	return rc;
5851 }
5852 
5853 int
CIFSSMBSetPathInfo(const unsigned int xid,struct cifs_tcon * tcon,const char * fileName,const FILE_BASIC_INFO * data,const struct nls_table * nls_codepage,struct cifs_sb_info * cifs_sb)5854 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5855 		   const char *fileName, const FILE_BASIC_INFO *data,
5856 		   const struct nls_table *nls_codepage,
5857 		     struct cifs_sb_info *cifs_sb)
5858 {
5859 	TRANSACTION2_SPI_REQ *pSMB = NULL;
5860 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
5861 	unsigned int in_len;
5862 	int name_len;
5863 	int rc = 0;
5864 	int bytes_returned = 0;
5865 	char *data_offset;
5866 	__u16 params, param_offset, offset, byte_count, count;
5867 	int remap = cifs_remap(cifs_sb);
5868 
5869 	cifs_dbg(FYI, "In SetTimes\n");
5870 
5871 SetTimesRetry:
5872 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5873 		      (void **) &pSMBr);
5874 	if (rc < 0)
5875 		return rc;
5876 	in_len = rc;
5877 
5878 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5879 		name_len =
5880 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5881 				       PATH_MAX, nls_codepage, remap);
5882 		name_len++;	/* trailing null */
5883 		name_len *= 2;
5884 	} else {
5885 		name_len = copy_path_name(pSMB->FileName, fileName);
5886 	}
5887 
5888 	params = 6 + name_len;
5889 	count = sizeof(FILE_BASIC_INFO);
5890 	pSMB->MaxParameterCount = cpu_to_le16(2);
5891 	/* BB find max SMB PDU from sess structure BB */
5892 	pSMB->MaxDataCount = cpu_to_le16(1000);
5893 	pSMB->MaxSetupCount = 0;
5894 	pSMB->Reserved = 0;
5895 	pSMB->Flags = 0;
5896 	pSMB->Timeout = 0;
5897 	pSMB->Reserved2 = 0;
5898 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5899 				InformationLevel);
5900 	offset = param_offset + params;
5901 	data_offset = (char *)pSMB + offsetof(typeof(*pSMB), hdr.Protocol) + offset;
5902 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5903 	pSMB->DataOffset = cpu_to_le16(offset);
5904 	pSMB->SetupCount = 1;
5905 	pSMB->Reserved3 = 0;
5906 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5907 	byte_count = 3 /* pad */  + params + count;
5908 
5909 	pSMB->DataCount = cpu_to_le16(count);
5910 	pSMB->ParameterCount = cpu_to_le16(params);
5911 	pSMB->TotalDataCount = pSMB->DataCount;
5912 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5913 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5914 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5915 	else
5916 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5917 	pSMB->Reserved4 = 0;
5918 	in_len += byte_count;
5919 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5920 	pSMB->ByteCount = cpu_to_le16(byte_count);
5921 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
5922 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5923 	if (rc)
5924 		cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5925 
5926 	cifs_buf_release(pSMB);
5927 
5928 	if (rc == -EAGAIN)
5929 		goto SetTimesRetry;
5930 
5931 	return rc;
5932 }
5933 
5934 static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO * data_offset,const struct cifs_unix_set_info_args * args)5935 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5936 			const struct cifs_unix_set_info_args *args)
5937 {
5938 	u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5939 	u64 mode = args->mode;
5940 
5941 	if (uid_valid(args->uid))
5942 		uid = from_kuid(&init_user_ns, args->uid);
5943 	if (gid_valid(args->gid))
5944 		gid = from_kgid(&init_user_ns, args->gid);
5945 
5946 	/*
5947 	 * Samba server ignores set of file size to zero due to bugs in some
5948 	 * older clients, but we should be precise - we use SetFileSize to
5949 	 * set file size and do not want to truncate file size to zero
5950 	 * accidentally as happened on one Samba server beta by putting
5951 	 * zero instead of -1 here
5952 	 */
5953 	data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5954 	data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5955 	data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5956 	data_offset->LastAccessTime = cpu_to_le64(args->atime);
5957 	data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5958 	data_offset->Uid = cpu_to_le64(uid);
5959 	data_offset->Gid = cpu_to_le64(gid);
5960 	/* better to leave device as zero when it is  */
5961 	data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5962 	data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5963 	data_offset->Permissions = cpu_to_le64(mode);
5964 
5965 	if (S_ISREG(mode))
5966 		data_offset->Type = cpu_to_le32(UNIX_FILE);
5967 	else if (S_ISDIR(mode))
5968 		data_offset->Type = cpu_to_le32(UNIX_DIR);
5969 	else if (S_ISLNK(mode))
5970 		data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5971 	else if (S_ISCHR(mode))
5972 		data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5973 	else if (S_ISBLK(mode))
5974 		data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5975 	else if (S_ISFIFO(mode))
5976 		data_offset->Type = cpu_to_le32(UNIX_FIFO);
5977 	else if (S_ISSOCK(mode))
5978 		data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5979 }
5980 
5981 int
CIFSSMBUnixSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const struct cifs_unix_set_info_args * args,u16 fid,u32 pid_of_opener)5982 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5983 		       const struct cifs_unix_set_info_args *args,
5984 		       u16 fid, u32 pid_of_opener)
5985 {
5986 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5987 	unsigned int in_len;
5988 	char *data_offset;
5989 	int rc = 0;
5990 	u16 params, param_offset, offset, byte_count, count;
5991 
5992 	cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5993 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5994 	if (rc < 0)
5995 		return rc;
5996 	in_len = rc;
5997 
5998 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5999 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
6000 
6001 	params = 6;
6002 	pSMB->MaxSetupCount = 0;
6003 	pSMB->Reserved = 0;
6004 	pSMB->Flags = 0;
6005 	pSMB->Timeout = 0;
6006 	pSMB->Reserved2 = 0;
6007 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid);
6008 	offset = param_offset + params;
6009 
6010 	data_offset = (char *)pSMB + offset;
6011 
6012 	count = sizeof(FILE_UNIX_BASIC_INFO);
6013 
6014 	pSMB->MaxParameterCount = cpu_to_le16(2);
6015 	/* BB find max SMB PDU from sess */
6016 	pSMB->MaxDataCount = cpu_to_le16(1000);
6017 	pSMB->SetupCount = 1;
6018 	pSMB->Reserved3 = 0;
6019 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6020 	byte_count = 3 /* pad */  + params + count;
6021 	pSMB->DataCount = cpu_to_le16(count);
6022 	pSMB->ParameterCount = cpu_to_le16(params);
6023 	pSMB->TotalDataCount = pSMB->DataCount;
6024 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6025 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6026 	pSMB->DataOffset = cpu_to_le16(offset);
6027 	pSMB->Fid = fid;
6028 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6029 	pSMB->Reserved4 = 0;
6030 	in_len += byte_count;
6031 	pSMB->ByteCount = cpu_to_le16(byte_count);
6032 
6033 	cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6034 
6035 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, in_len, 0);
6036 	cifs_small_buf_release(pSMB);
6037 	if (rc)
6038 		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
6039 			 rc);
6040 
6041 	/* Note: On -EAGAIN error only caller can retry on handle based calls
6042 		since file handle passed in no longer valid */
6043 
6044 	return rc;
6045 }
6046 
6047 int
CIFSSMBUnixSetPathInfo(const unsigned int xid,struct cifs_tcon * tcon,const char * file_name,const struct cifs_unix_set_info_args * args,const struct nls_table * nls_codepage,int remap)6048 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6049 		       const char *file_name,
6050 		       const struct cifs_unix_set_info_args *args,
6051 		       const struct nls_table *nls_codepage, int remap)
6052 {
6053 	TRANSACTION2_SPI_REQ *pSMB = NULL;
6054 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
6055 	unsigned int in_len;
6056 	int name_len;
6057 	int rc = 0;
6058 	int bytes_returned = 0;
6059 	FILE_UNIX_BASIC_INFO *data_offset;
6060 	__u16 params, param_offset, offset, count, byte_count;
6061 
6062 	cifs_dbg(FYI, "In SetUID/GID/Mode\n");
6063 setPermsRetry:
6064 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6065 		      (void **) &pSMBr);
6066 	if (rc < 0)
6067 		return rc;
6068 	in_len = rc;
6069 
6070 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6071 		name_len =
6072 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
6073 				       PATH_MAX, nls_codepage, remap);
6074 		name_len++;	/* trailing null */
6075 		name_len *= 2;
6076 	} else {
6077 		name_len = copy_path_name(pSMB->FileName, file_name);
6078 	}
6079 
6080 	params = 6 + name_len;
6081 	count = sizeof(FILE_UNIX_BASIC_INFO);
6082 	pSMB->MaxParameterCount = cpu_to_le16(2);
6083 	/* BB find max SMB PDU from sess structure BB */
6084 	pSMB->MaxDataCount = cpu_to_le16(1000);
6085 	pSMB->MaxSetupCount = 0;
6086 	pSMB->Reserved = 0;
6087 	pSMB->Flags = 0;
6088 	pSMB->Timeout = 0;
6089 	pSMB->Reserved2 = 0;
6090 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
6091 				InformationLevel);
6092 	offset = param_offset + params;
6093 	data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset);
6094 	memset(data_offset, 0, count);
6095 	pSMB->DataOffset = cpu_to_le16(offset);
6096 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6097 	pSMB->SetupCount = 1;
6098 	pSMB->Reserved3 = 0;
6099 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6100 	byte_count = 3 /* pad */  + params + count;
6101 	pSMB->ParameterCount = cpu_to_le16(params);
6102 	pSMB->DataCount = cpu_to_le16(count);
6103 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6104 	pSMB->TotalDataCount = pSMB->DataCount;
6105 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6106 	pSMB->Reserved4 = 0;
6107 	in_len += byte_count;
6108 
6109 	cifs_fill_unix_set_info(data_offset, args);
6110 
6111 	pSMB->ByteCount = cpu_to_le16(byte_count);
6112 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
6113 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6114 	if (rc)
6115 		cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
6116 
6117 	cifs_buf_release(pSMB);
6118 	if (rc == -EAGAIN)
6119 		goto setPermsRetry;
6120 	return rc;
6121 }
6122 
6123 #ifdef CONFIG_CIFS_XATTR
6124 /*
6125  * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6126  * function used by listxattr and getxattr type calls. When ea_name is set,
6127  * it looks for that attribute name and stuffs that value into the EAData
6128  * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6129  * buffer. In both cases, the return value is either the length of the
6130  * resulting data or a negative error code. If EAData is a NULL pointer then
6131  * the data isn't copied to it, but the length is returned.
6132  */
6133 ssize_t
CIFSSMBQAllEAs(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * searchName,const unsigned char * ea_name,char * EAData,size_t buf_size,struct cifs_sb_info * cifs_sb)6134 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6135 		const unsigned char *searchName, const unsigned char *ea_name,
6136 		char *EAData, size_t buf_size,
6137 		struct cifs_sb_info *cifs_sb)
6138 {
6139 		/* BB assumes one setup word */
6140 	TRANSACTION2_QPI_REQ *pSMB = NULL;
6141 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
6142 	int remap = cifs_remap(cifs_sb);
6143 	struct nls_table *nls_codepage = cifs_sb->local_nls;
6144 	unsigned int in_len;
6145 	int rc = 0;
6146 	int bytes_returned;
6147 	int list_len;
6148 	struct fealist *ea_response_data;
6149 	struct fea *temp_fea;
6150 	char *temp_ptr;
6151 	char *end_of_smb;
6152 	__u16 params, byte_count, data_offset;
6153 	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6154 
6155 	cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6156 QAllEAsRetry:
6157 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6158 		      (void **) &pSMBr);
6159 	if (rc < 0)
6160 		return rc;
6161 	in_len = rc;
6162 
6163 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6164 		list_len =
6165 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6166 				       PATH_MAX, nls_codepage, remap);
6167 		list_len++;	/* trailing null */
6168 		list_len *= 2;
6169 	} else {
6170 		list_len = copy_path_name(pSMB->FileName, searchName);
6171 	}
6172 
6173 	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6174 	pSMB->TotalDataCount = 0;
6175 	pSMB->MaxParameterCount = cpu_to_le16(2);
6176 	/* BB find exact max SMB PDU from sess structure BB */
6177 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6178 	pSMB->MaxSetupCount = 0;
6179 	pSMB->Reserved = 0;
6180 	pSMB->Flags = 0;
6181 	pSMB->Timeout = 0;
6182 	pSMB->Reserved2 = 0;
6183 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
6184 		struct smb_com_transaction2_qpi_req, InformationLevel));
6185 	pSMB->DataCount = 0;
6186 	pSMB->DataOffset = 0;
6187 	pSMB->SetupCount = 1;
6188 	pSMB->Reserved3 = 0;
6189 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6190 	byte_count = params + 1 /* pad */ ;
6191 	pSMB->TotalParameterCount = cpu_to_le16(params);
6192 	pSMB->ParameterCount = pSMB->TotalParameterCount;
6193 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6194 	pSMB->Reserved4 = 0;
6195 	in_len += byte_count;
6196 	pSMB->ByteCount = cpu_to_le16(byte_count);
6197 
6198 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
6199 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6200 	if (rc) {
6201 		cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6202 		goto QAllEAsOut;
6203 	}
6204 
6205 
6206 	/* BB also check enough total bytes returned */
6207 	/* BB we need to improve the validity checking
6208 	of these trans2 responses */
6209 
6210 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6211 	if (rc || get_bcc(&pSMBr->hdr) < 4) {
6212 		rc = smb_EIO2(smb_eio_trace_qalleas_bcc_too_small,
6213 			      get_bcc(&pSMBr->hdr), 4);
6214 		goto QAllEAsOut;
6215 	}
6216 
6217 	/* check that length of list is not more than bcc */
6218 	/* check that each entry does not go beyond length
6219 	   of list */
6220 	/* check that each element of each entry does not
6221 	   go beyond end of list */
6222 	/* validate_trans2_offsets() */
6223 	/* BB check if start of smb + data_offset > &bcc+ bcc */
6224 
6225 	data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6226 	ea_response_data = (struct fealist *)
6227 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
6228 
6229 	list_len = le32_to_cpu(ea_response_data->list_len);
6230 	cifs_dbg(FYI, "ea length %d\n", list_len);
6231 	if (list_len <= 8) {
6232 		cifs_dbg(FYI, "empty EA list returned from server\n");
6233 		/* didn't find the named attribute */
6234 		if (ea_name)
6235 			rc = -ENODATA;
6236 		goto QAllEAsOut;
6237 	}
6238 
6239 	/* make sure list_len doesn't go past end of SMB */
6240 	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6241 	if ((char *)ea_response_data + list_len > end_of_smb) {
6242 		cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6243 		rc = smb_EIO2(smb_eio_trace_qalleas_overlong,
6244 			      (unsigned long)ea_response_data + list_len - (unsigned long)pSMBr,
6245 			      (unsigned long)end_of_smb - (unsigned long)pSMBr);
6246 		goto QAllEAsOut;
6247 	}
6248 
6249 	/* account for ea list len */
6250 	list_len -= 4;
6251 	temp_fea = &ea_response_data->list;
6252 	temp_ptr = (char *)temp_fea;
6253 	while (list_len > 0) {
6254 		unsigned int name_len;
6255 		__u16 value_len;
6256 
6257 		list_len -= 4;
6258 		temp_ptr += 4;
6259 		/* make sure we can read name_len and value_len */
6260 		if (list_len < 0) {
6261 			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6262 			rc = smb_EIO1(smb_eio_trace_qalleas_ea_overlong, list_len);
6263 			goto QAllEAsOut;
6264 		}
6265 
6266 		name_len = temp_fea->name_len;
6267 		value_len = le16_to_cpu(temp_fea->value_len);
6268 		list_len -= name_len + 1 + value_len;
6269 		if (list_len < 0) {
6270 			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6271 			rc = smb_EIO1(smb_eio_trace_qalleas_ea_overlong, list_len);
6272 			goto QAllEAsOut;
6273 		}
6274 
6275 		if (ea_name) {
6276 			if (ea_name_len == name_len &&
6277 			    memcmp(ea_name, temp_ptr, name_len) == 0) {
6278 				temp_ptr += name_len + 1;
6279 				rc = value_len;
6280 				if (buf_size == 0)
6281 					goto QAllEAsOut;
6282 				if ((size_t)value_len > buf_size) {
6283 					rc = -ERANGE;
6284 					goto QAllEAsOut;
6285 				}
6286 				memcpy(EAData, temp_ptr, value_len);
6287 				goto QAllEAsOut;
6288 			}
6289 		} else {
6290 			/* account for prefix user. and trailing null */
6291 			rc += (5 + 1 + name_len);
6292 			if (rc < (int) buf_size) {
6293 				memcpy(EAData, "user.", 5);
6294 				EAData += 5;
6295 				memcpy(EAData, temp_ptr, name_len);
6296 				EAData += name_len;
6297 				/* null terminate name */
6298 				*EAData = 0;
6299 				++EAData;
6300 			} else if (buf_size == 0) {
6301 				/* skip copy - calc size only */
6302 			} else {
6303 				/* stop before overrun buffer */
6304 				rc = -ERANGE;
6305 				break;
6306 			}
6307 		}
6308 		temp_ptr += name_len + 1 + value_len;
6309 		temp_fea = (struct fea *)temp_ptr;
6310 	}
6311 
6312 	/* didn't find the named attribute */
6313 	if (ea_name)
6314 		rc = -ENODATA;
6315 
6316 QAllEAsOut:
6317 	cifs_buf_release(pSMB);
6318 	if (rc == -EAGAIN)
6319 		goto QAllEAsRetry;
6320 
6321 	return (ssize_t)rc;
6322 }
6323 
6324 int
CIFSSMBSetEA(const unsigned int xid,struct cifs_tcon * tcon,const char * fileName,const char * ea_name,const void * ea_value,const __u16 ea_value_len,const struct nls_table * nls_codepage,struct cifs_sb_info * cifs_sb)6325 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6326 	     const char *fileName, const char *ea_name, const void *ea_value,
6327 	     const __u16 ea_value_len, const struct nls_table *nls_codepage,
6328 	     struct cifs_sb_info *cifs_sb)
6329 {
6330 	struct smb_com_transaction2_spi_req *pSMB = NULL;
6331 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6332 	struct fealist *parm_data;
6333 	unsigned int in_len;
6334 	int name_len;
6335 	int rc = 0;
6336 	int bytes_returned = 0;
6337 	__u16 params, param_offset;
6338 	unsigned int byte_count, offset, count;
6339 	int remap = cifs_remap(cifs_sb);
6340 	unsigned int total_len;
6341 
6342 	cifs_dbg(FYI, "In SetEA\n");
6343 SetEARetry:
6344 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6345 		      (void **) &pSMBr);
6346 	if (rc < 0)
6347 		return rc;
6348 	in_len = rc;
6349 
6350 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6351 		name_len =
6352 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6353 				       PATH_MAX, nls_codepage, remap);
6354 		name_len++;	/* trailing null */
6355 		name_len *= 2;
6356 	} else {
6357 		name_len = copy_path_name(pSMB->FileName, fileName);
6358 	}
6359 
6360 	params = 6 + name_len;
6361 
6362 	/* done calculating parms using name_len of file name,
6363 	now use name_len to calculate length of ea name
6364 	we are going to create in the inode xattrs */
6365 	if (ea_name == NULL)
6366 		name_len = 0;
6367 	else
6368 		name_len = strnlen(ea_name, 255);
6369 
6370 	count = sizeof(*parm_data) + 1 + ea_value_len + name_len;
6371 	pSMB->MaxParameterCount = cpu_to_le16(2);
6372 	/* BB find max SMB PDU from sess */
6373 	pSMB->MaxDataCount = cpu_to_le16(1000);
6374 	pSMB->MaxSetupCount = 0;
6375 	pSMB->Reserved = 0;
6376 	pSMB->Flags = 0;
6377 	pSMB->Timeout = 0;
6378 	pSMB->Reserved2 = 0;
6379 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
6380 				InformationLevel);
6381 	offset = param_offset + params;
6382 	pSMB->InformationLevel =
6383 		cpu_to_le16(SMB_SET_FILE_EA);
6384 
6385 	parm_data = (void *)pSMB + offset;
6386 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6387 	pSMB->DataOffset = cpu_to_le16(offset);
6388 	pSMB->SetupCount = 1;
6389 	pSMB->Reserved3 = 0;
6390 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6391 	byte_count = 3 /* pad */  + params + count;
6392 	if (check_add_overflow(in_len, byte_count, &total_len) ||
6393 	    byte_count > U16_MAX ||
6394 	    total_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
6395 		cifs_dbg(VFS, "EA request too large: %u bytes\n", total_len);
6396 		cifs_buf_release(pSMB);
6397 		return -E2BIG;
6398 	}
6399 	pSMB->DataCount = cpu_to_le16(count);
6400 	parm_data->list_len = cpu_to_le32(count);
6401 	parm_data->list.EA_flags = 0;
6402 	/* we checked above that name len is less than 255 */
6403 	parm_data->list.name_len = (__u8)name_len;
6404 	/* EA names are always ASCII and NUL-terminated */
6405 	strscpy(parm_data->list.name, ea_name ?: "", name_len + 1);
6406 	parm_data->list.value_len = cpu_to_le16(ea_value_len);
6407 	/* caller ensures that ea_value_len is less than 64K but
6408 	we need to ensure that it fits within the smb */
6409 
6410 	/*BB add length check to see if it would fit in
6411 	     negotiated SMB buffer size BB */
6412 	/* if (ea_value_len > buffer_size - 512 (enough for header)) */
6413 	if (ea_value_len)
6414 		memcpy(parm_data->list.name + name_len + 1,
6415 		       ea_value, ea_value_len);
6416 
6417 	pSMB->TotalDataCount = pSMB->DataCount;
6418 	pSMB->ParameterCount = cpu_to_le16(params);
6419 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6420 	pSMB->Reserved4 = 0;
6421 	in_len += byte_count;
6422 	pSMB->ByteCount = cpu_to_le16(byte_count);
6423 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, in_len,
6424 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6425 	if (rc)
6426 		cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6427 
6428 	cifs_buf_release(pSMB);
6429 
6430 	if (rc == -EAGAIN)
6431 		goto SetEARetry;
6432 
6433 	return rc;
6434 }
6435 #endif
6436