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