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