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