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