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