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