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