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