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; /* successful open = not delete pending */
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; /* successful open = not delete pending */
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 unsigned int rreq_debug_id = rdata->rreq->debug_id;
1315 unsigned int subreq_debug_index = rdata->subreq.debug_index;
1316
1317 cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n",
1318 __func__, mid->mid, mid->mid_state, rdata->result,
1319 rdata->subreq.len);
1320
1321 switch (mid->mid_state) {
1322 case MID_RESPONSE_RECEIVED:
1323 /* result already set, check signature */
1324 if (server->sign) {
1325 int rc = 0;
1326
1327 iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);
1328 rc = cifs_verify_signature(&rqst, server,
1329 mid->sequence_number);
1330 if (rc)
1331 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1332 rc);
1333 }
1334 /* FIXME: should this be counted toward the initiating task? */
1335 task_io_account_read(rdata->got_bytes);
1336 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1337 break;
1338 case MID_REQUEST_SUBMITTED:
1339 trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_req_submitted);
1340 goto do_retry;
1341 case MID_RETRY_NEEDED:
1342 trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_retry_needed);
1343 do_retry:
1344 __set_bit(NETFS_SREQ_NEED_RETRY, &rdata->subreq.flags);
1345 rdata->result = -EAGAIN;
1346 if (server->sign && rdata->got_bytes)
1347 /* reset bytes number since we can not check a sign */
1348 rdata->got_bytes = 0;
1349 /* FIXME: should this be counted toward the initiating task? */
1350 task_io_account_read(rdata->got_bytes);
1351 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1352 break;
1353 case MID_RESPONSE_MALFORMED:
1354 trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_malformed);
1355 rdata->result = -EIO;
1356 break;
1357 default:
1358 trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_unknown);
1359 rdata->result = -EIO;
1360 break;
1361 }
1362
1363 if (rdata->result == -ENODATA) {
1364 rdata->result = 0;
1365 __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
1366 trace_smb3_read_err(rdata->rreq->debug_id,
1367 rdata->subreq.debug_index,
1368 rdata->xid,
1369 rdata->req->cfile->fid.persistent_fid,
1370 tcon->tid, tcon->ses->Suid,
1371 rdata->subreq.start + rdata->subreq.transferred,
1372 rdata->subreq.len - rdata->subreq.transferred,
1373 rdata->result);
1374 } else {
1375 size_t trans = rdata->subreq.transferred + rdata->got_bytes;
1376 if (trans < rdata->subreq.len &&
1377 rdata->subreq.start + trans == ictx->remote_i_size) {
1378 rdata->result = 0;
1379 __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
1380 } else if (rdata->got_bytes > 0) {
1381 __set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags);
1382 }
1383 if (rdata->got_bytes)
1384 __set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags);
1385 trace_smb3_read_done(rdata->rreq->debug_id,
1386 rdata->subreq.debug_index,
1387 rdata->xid,
1388 rdata->req->cfile->fid.persistent_fid,
1389 tcon->tid, tcon->ses->Suid,
1390 rdata->subreq.start + rdata->subreq.transferred,
1391 rdata->got_bytes);
1392 }
1393
1394 trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, rdata->credits.value,
1395 server->credits, server->in_flight,
1396 0, cifs_trace_rw_credits_read_response_clear);
1397 rdata->credits.value = 0;
1398 rdata->subreq.error = rdata->result;
1399 rdata->subreq.transferred += rdata->got_bytes;
1400 trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_progress);
1401 netfs_read_subreq_terminated(&rdata->subreq);
1402 release_mid(mid);
1403 add_credits(server, &credits, 0);
1404 trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0,
1405 server->credits, server->in_flight,
1406 credits.value, cifs_trace_rw_credits_read_response_add);
1407 }
1408
1409 /* cifs_async_readv - send an async write, and set up mid to handle result */
1410 int
cifs_async_readv(struct cifs_io_subrequest * rdata)1411 cifs_async_readv(struct cifs_io_subrequest *rdata)
1412 {
1413 int rc;
1414 READ_REQ *smb = NULL;
1415 int wct;
1416 struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
1417 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1418 .rq_nvec = 2 };
1419
1420 cifs_dbg(FYI, "%s: offset=%llu bytes=%zu\n",
1421 __func__, rdata->subreq.start, rdata->subreq.len);
1422
1423 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1424 wct = 12;
1425 else {
1426 wct = 10; /* old style read */
1427 if ((rdata->subreq.start >> 32) > 0) {
1428 /* can not handle this big offset for old */
1429 return -EIO;
1430 }
1431 }
1432
1433 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1434 if (rc)
1435 return rc;
1436
1437 smb->hdr.Pid = cpu_to_le16((__u16)rdata->req->pid);
1438 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->req->pid >> 16));
1439
1440 smb->AndXCommand = 0xFF; /* none */
1441 smb->Fid = rdata->req->cfile->fid.netfid;
1442 smb->OffsetLow = cpu_to_le32(rdata->subreq.start & 0xFFFFFFFF);
1443 if (wct == 12)
1444 smb->OffsetHigh = cpu_to_le32(rdata->subreq.start >> 32);
1445 smb->Remaining = 0;
1446 smb->MaxCount = cpu_to_le16(rdata->subreq.len & 0xFFFF);
1447 smb->MaxCountHigh = cpu_to_le32(rdata->subreq.len >> 16);
1448 if (wct == 12)
1449 smb->ByteCount = 0;
1450 else {
1451 /* old style read */
1452 struct smb_com_readx_req *smbr =
1453 (struct smb_com_readx_req *)smb;
1454 smbr->ByteCount = 0;
1455 }
1456
1457 /* 4 for RFC1001 length + 1 for BCC */
1458 rdata->iov[0].iov_base = smb;
1459 rdata->iov[0].iov_len = 4;
1460 rdata->iov[1].iov_base = (char *)smb + 4;
1461 rdata->iov[1].iov_len = get_rfc1002_length(smb);
1462
1463 trace_smb3_read_enter(rdata->rreq->debug_id,
1464 rdata->subreq.debug_index,
1465 rdata->xid,
1466 rdata->req->cfile->fid.netfid,
1467 tcon->tid, tcon->ses->Suid,
1468 rdata->subreq.start, rdata->subreq.len);
1469
1470 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1471 cifs_readv_callback, NULL, rdata, 0, NULL);
1472
1473 if (rc == 0)
1474 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1475 cifs_small_buf_release(smb);
1476 return rc;
1477 }
1478
1479 int
CIFSSMBRead(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,char ** buf,int * pbuf_type)1480 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1481 unsigned int *nbytes, char **buf, int *pbuf_type)
1482 {
1483 int rc = -EACCES;
1484 READ_REQ *pSMB = NULL;
1485 READ_RSP *pSMBr = NULL;
1486 char *pReadData = NULL;
1487 int wct;
1488 int resp_buf_type = 0;
1489 struct kvec iov[1];
1490 struct kvec rsp_iov;
1491 __u32 pid = io_parms->pid;
1492 __u16 netfid = io_parms->netfid;
1493 __u64 offset = io_parms->offset;
1494 struct cifs_tcon *tcon = io_parms->tcon;
1495 unsigned int count = io_parms->length;
1496
1497 cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1498 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1499 wct = 12;
1500 else {
1501 wct = 10; /* old style read */
1502 if ((offset >> 32) > 0) {
1503 /* can not handle this big offset for old */
1504 return -EIO;
1505 }
1506 }
1507
1508 *nbytes = 0;
1509 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1510 if (rc)
1511 return rc;
1512
1513 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1514 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1515
1516 /* tcon and ses pointer are checked in smb_init */
1517 if (tcon->ses->server == NULL)
1518 return -ECONNABORTED;
1519
1520 pSMB->AndXCommand = 0xFF; /* none */
1521 pSMB->Fid = netfid;
1522 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1523 if (wct == 12)
1524 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1525
1526 pSMB->Remaining = 0;
1527 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1528 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1529 if (wct == 12)
1530 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1531 else {
1532 /* old style read */
1533 struct smb_com_readx_req *pSMBW =
1534 (struct smb_com_readx_req *)pSMB;
1535 pSMBW->ByteCount = 0;
1536 }
1537
1538 iov[0].iov_base = (char *)pSMB;
1539 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1540 rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1541 CIFS_LOG_ERROR, &rsp_iov);
1542 cifs_small_buf_release(pSMB);
1543 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1544 pSMBr = (READ_RSP *)rsp_iov.iov_base;
1545 if (rc) {
1546 cifs_dbg(VFS, "Send error in read = %d\n", rc);
1547 } else {
1548 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1549 data_length = data_length << 16;
1550 data_length += le16_to_cpu(pSMBr->DataLength);
1551 *nbytes = data_length;
1552
1553 /*check that DataLength would not go beyond end of SMB */
1554 if ((data_length > CIFSMaxBufSize)
1555 || (data_length > count)) {
1556 cifs_dbg(FYI, "bad length %d for count %d\n",
1557 data_length, count);
1558 rc = -EIO;
1559 *nbytes = 0;
1560 } else {
1561 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1562 le16_to_cpu(pSMBr->DataOffset);
1563 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1564 cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1565 rc = -EFAULT;
1566 }*/ /* can not use copy_to_user when using page cache*/
1567 if (*buf)
1568 memcpy(*buf, pReadData, data_length);
1569 }
1570 }
1571
1572 if (*buf) {
1573 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1574 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1575 /* return buffer to caller to free */
1576 *buf = rsp_iov.iov_base;
1577 if (resp_buf_type == CIFS_SMALL_BUFFER)
1578 *pbuf_type = CIFS_SMALL_BUFFER;
1579 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1580 *pbuf_type = CIFS_LARGE_BUFFER;
1581 } /* else no valid buffer on return - leave as null */
1582
1583 /* Note: On -EAGAIN error only caller can retry on handle based calls
1584 since file handle passed in no longer valid */
1585 return rc;
1586 }
1587
1588
1589 int
CIFSSMBWrite(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,const char * buf)1590 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1591 unsigned int *nbytes, const char *buf)
1592 {
1593 int rc = -EACCES;
1594 WRITE_REQ *pSMB = NULL;
1595 WRITE_RSP *pSMBr = NULL;
1596 int bytes_returned, wct;
1597 __u32 bytes_sent;
1598 __u16 byte_count;
1599 __u32 pid = io_parms->pid;
1600 __u16 netfid = io_parms->netfid;
1601 __u64 offset = io_parms->offset;
1602 struct cifs_tcon *tcon = io_parms->tcon;
1603 unsigned int count = io_parms->length;
1604
1605 *nbytes = 0;
1606
1607 /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1608 if (tcon->ses == NULL)
1609 return -ECONNABORTED;
1610
1611 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1612 wct = 14;
1613 else {
1614 wct = 12;
1615 if ((offset >> 32) > 0) {
1616 /* can not handle big offset for old srv */
1617 return -EIO;
1618 }
1619 }
1620
1621 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1622 (void **) &pSMBr);
1623 if (rc)
1624 return rc;
1625
1626 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1627 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1628
1629 /* tcon and ses pointer are checked in smb_init */
1630 if (tcon->ses->server == NULL)
1631 return -ECONNABORTED;
1632
1633 pSMB->AndXCommand = 0xFF; /* none */
1634 pSMB->Fid = netfid;
1635 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1636 if (wct == 14)
1637 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1638
1639 pSMB->Reserved = 0xFFFFFFFF;
1640 pSMB->WriteMode = 0;
1641 pSMB->Remaining = 0;
1642
1643 /* Can increase buffer size if buffer is big enough in some cases ie we
1644 can send more if LARGE_WRITE_X capability returned by the server and if
1645 our buffer is big enough or if we convert to iovecs on socket writes
1646 and eliminate the copy to the CIFS buffer */
1647 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1648 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1649 } else {
1650 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1651 & ~0xFF;
1652 }
1653
1654 if (bytes_sent > count)
1655 bytes_sent = count;
1656 pSMB->DataOffset =
1657 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1658 if (buf)
1659 memcpy(pSMB->Data, buf, bytes_sent);
1660 else if (count != 0) {
1661 /* No buffer */
1662 cifs_buf_release(pSMB);
1663 return -EINVAL;
1664 } /* else setting file size with write of zero bytes */
1665 if (wct == 14)
1666 byte_count = bytes_sent + 1; /* pad */
1667 else /* wct == 12 */
1668 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1669
1670 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1671 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1672 inc_rfc1001_len(pSMB, byte_count);
1673
1674 if (wct == 14)
1675 pSMB->ByteCount = cpu_to_le16(byte_count);
1676 else { /* old style write has byte count 4 bytes earlier
1677 so 4 bytes pad */
1678 struct smb_com_writex_req *pSMBW =
1679 (struct smb_com_writex_req *)pSMB;
1680 pSMBW->ByteCount = cpu_to_le16(byte_count);
1681 }
1682
1683 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1684 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1685 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1686 if (rc) {
1687 cifs_dbg(FYI, "Send error in write = %d\n", rc);
1688 } else {
1689 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1690 *nbytes = (*nbytes) << 16;
1691 *nbytes += le16_to_cpu(pSMBr->Count);
1692
1693 /*
1694 * Mask off high 16 bits when bytes written as returned by the
1695 * server is greater than bytes requested by the client. Some
1696 * OS/2 servers are known to set incorrect CountHigh values.
1697 */
1698 if (*nbytes > count)
1699 *nbytes &= 0xFFFF;
1700 }
1701
1702 cifs_buf_release(pSMB);
1703
1704 /* Note: On -EAGAIN error only caller can retry on handle based calls
1705 since file handle passed in no longer valid */
1706
1707 return rc;
1708 }
1709
1710 /*
1711 * Check the mid_state and signature on received buffer (if any), and queue the
1712 * workqueue completion task.
1713 */
1714 static void
cifs_writev_callback(struct mid_q_entry * mid)1715 cifs_writev_callback(struct mid_q_entry *mid)
1716 {
1717 struct cifs_io_subrequest *wdata = mid->callback_data;
1718 struct TCP_Server_Info *server = wdata->server;
1719 struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
1720 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1721 struct cifs_credits credits = {
1722 .value = 1,
1723 .instance = 0,
1724 .rreq_debug_id = wdata->rreq->debug_id,
1725 .rreq_debug_index = wdata->subreq.debug_index,
1726 };
1727 ssize_t result;
1728 size_t written;
1729
1730 switch (mid->mid_state) {
1731 case MID_RESPONSE_RECEIVED:
1732 result = cifs_check_receive(mid, tcon->ses->server, 0);
1733 if (result != 0)
1734 break;
1735
1736 written = le16_to_cpu(smb->CountHigh);
1737 written <<= 16;
1738 written += le16_to_cpu(smb->Count);
1739 /*
1740 * Mask off high 16 bits when bytes written as returned
1741 * by the server is greater than bytes requested by the
1742 * client. OS/2 servers are known to set incorrect
1743 * CountHigh values.
1744 */
1745 if (written > wdata->subreq.len)
1746 written &= 0xFFFF;
1747
1748 if (written < wdata->subreq.len) {
1749 result = -ENOSPC;
1750 } else {
1751 result = written;
1752 if (written > 0)
1753 __set_bit(NETFS_SREQ_MADE_PROGRESS, &wdata->subreq.flags);
1754 }
1755 break;
1756 case MID_REQUEST_SUBMITTED:
1757 trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_req_submitted);
1758 __set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags);
1759 result = -EAGAIN;
1760 break;
1761 case MID_RETRY_NEEDED:
1762 trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_retry_needed);
1763 __set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags);
1764 result = -EAGAIN;
1765 break;
1766 case MID_RESPONSE_MALFORMED:
1767 trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_malformed);
1768 result = -EIO;
1769 break;
1770 default:
1771 trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_unknown);
1772 result = -EIO;
1773 break;
1774 }
1775
1776 trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index,
1777 wdata->credits.value,
1778 server->credits, server->in_flight,
1779 0, cifs_trace_rw_credits_write_response_clear);
1780 wdata->credits.value = 0;
1781 cifs_write_subrequest_terminated(wdata, result);
1782 release_mid(mid);
1783 trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index, 0,
1784 server->credits, server->in_flight,
1785 credits.value, cifs_trace_rw_credits_write_response_add);
1786 add_credits(tcon->ses->server, &credits, 0);
1787 }
1788
1789 /* cifs_async_writev - send an async write, and set up mid to handle result */
1790 void
cifs_async_writev(struct cifs_io_subrequest * wdata)1791 cifs_async_writev(struct cifs_io_subrequest *wdata)
1792 {
1793 int rc = -EACCES;
1794 WRITE_REQ *smb = NULL;
1795 int wct;
1796 struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
1797 struct kvec iov[2];
1798 struct smb_rqst rqst = { };
1799
1800 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1801 wct = 14;
1802 } else {
1803 wct = 12;
1804 if (wdata->subreq.start >> 32 > 0) {
1805 /* can not handle big offset for old srv */
1806 rc = -EIO;
1807 goto out;
1808 }
1809 }
1810
1811 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
1812 if (rc)
1813 goto async_writev_out;
1814
1815 smb->hdr.Pid = cpu_to_le16((__u16)wdata->req->pid);
1816 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->req->pid >> 16));
1817
1818 smb->AndXCommand = 0xFF; /* none */
1819 smb->Fid = wdata->req->cfile->fid.netfid;
1820 smb->OffsetLow = cpu_to_le32(wdata->subreq.start & 0xFFFFFFFF);
1821 if (wct == 14)
1822 smb->OffsetHigh = cpu_to_le32(wdata->subreq.start >> 32);
1823 smb->Reserved = 0xFFFFFFFF;
1824 smb->WriteMode = 0;
1825 smb->Remaining = 0;
1826
1827 smb->DataOffset =
1828 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1829
1830 /* 4 for RFC1001 length + 1 for BCC */
1831 iov[0].iov_len = 4;
1832 iov[0].iov_base = smb;
1833 iov[1].iov_len = get_rfc1002_length(smb) + 1;
1834 iov[1].iov_base = (char *)smb + 4;
1835
1836 rqst.rq_iov = iov;
1837 rqst.rq_nvec = 2;
1838 rqst.rq_iter = wdata->subreq.io_iter;
1839
1840 cifs_dbg(FYI, "async write at %llu %zu bytes\n",
1841 wdata->subreq.start, wdata->subreq.len);
1842
1843 smb->DataLengthLow = cpu_to_le16(wdata->subreq.len & 0xFFFF);
1844 smb->DataLengthHigh = cpu_to_le16(wdata->subreq.len >> 16);
1845
1846 if (wct == 14) {
1847 inc_rfc1001_len(&smb->hdr, wdata->subreq.len + 1);
1848 put_bcc(wdata->subreq.len + 1, &smb->hdr);
1849 } else {
1850 /* wct == 12 */
1851 struct smb_com_writex_req *smbw =
1852 (struct smb_com_writex_req *)smb;
1853 inc_rfc1001_len(&smbw->hdr, wdata->subreq.len + 5);
1854 put_bcc(wdata->subreq.len + 5, &smbw->hdr);
1855 iov[1].iov_len += 4; /* pad bigger by four bytes */
1856 }
1857
1858 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
1859 cifs_writev_callback, NULL, wdata, 0, NULL);
1860 /* Can't touch wdata if rc == 0 */
1861 if (rc == 0)
1862 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1863
1864 async_writev_out:
1865 cifs_small_buf_release(smb);
1866 out:
1867 if (rc) {
1868 add_credits_and_wake_if(wdata->server, &wdata->credits, 0);
1869 cifs_write_subrequest_terminated(wdata, rc);
1870 }
1871 }
1872
1873 int
CIFSSMBWrite2(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,struct kvec * iov,int n_vec)1874 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
1875 unsigned int *nbytes, struct kvec *iov, int n_vec)
1876 {
1877 int rc;
1878 WRITE_REQ *pSMB = NULL;
1879 int wct;
1880 int smb_hdr_len;
1881 int resp_buf_type = 0;
1882 __u32 pid = io_parms->pid;
1883 __u16 netfid = io_parms->netfid;
1884 __u64 offset = io_parms->offset;
1885 struct cifs_tcon *tcon = io_parms->tcon;
1886 unsigned int count = io_parms->length;
1887 struct kvec rsp_iov;
1888
1889 *nbytes = 0;
1890
1891 cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
1892
1893 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1894 wct = 14;
1895 } else {
1896 wct = 12;
1897 if ((offset >> 32) > 0) {
1898 /* can not handle big offset for old srv */
1899 return -EIO;
1900 }
1901 }
1902 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1903 if (rc)
1904 return rc;
1905
1906 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1907 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1908
1909 /* tcon and ses pointer are checked in smb_init */
1910 if (tcon->ses->server == NULL)
1911 return -ECONNABORTED;
1912
1913 pSMB->AndXCommand = 0xFF; /* none */
1914 pSMB->Fid = netfid;
1915 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1916 if (wct == 14)
1917 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1918 pSMB->Reserved = 0xFFFFFFFF;
1919 pSMB->WriteMode = 0;
1920 pSMB->Remaining = 0;
1921
1922 pSMB->DataOffset =
1923 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1924
1925 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1926 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1927 /* header + 1 byte pad */
1928 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
1929 if (wct == 14)
1930 inc_rfc1001_len(pSMB, count + 1);
1931 else /* wct == 12 */
1932 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
1933 if (wct == 14)
1934 pSMB->ByteCount = cpu_to_le16(count + 1);
1935 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1936 struct smb_com_writex_req *pSMBW =
1937 (struct smb_com_writex_req *)pSMB;
1938 pSMBW->ByteCount = cpu_to_le16(count + 5);
1939 }
1940 iov[0].iov_base = pSMB;
1941 if (wct == 14)
1942 iov[0].iov_len = smb_hdr_len + 4;
1943 else /* wct == 12 pad bigger by four bytes */
1944 iov[0].iov_len = smb_hdr_len + 8;
1945
1946 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
1947 &rsp_iov);
1948 cifs_small_buf_release(pSMB);
1949 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1950 if (rc) {
1951 cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
1952 } else if (resp_buf_type == 0) {
1953 /* presumably this can not happen, but best to be safe */
1954 rc = -EIO;
1955 } else {
1956 WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
1957 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1958 *nbytes = (*nbytes) << 16;
1959 *nbytes += le16_to_cpu(pSMBr->Count);
1960
1961 /*
1962 * Mask off high 16 bits when bytes written as returned by the
1963 * server is greater than bytes requested by the client. OS/2
1964 * servers are known to set incorrect CountHigh values.
1965 */
1966 if (*nbytes > count)
1967 *nbytes &= 0xFFFF;
1968 }
1969
1970 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1971
1972 /* Note: On -EAGAIN error only caller can retry on handle based calls
1973 since file handle passed in no longer valid */
1974
1975 return rc;
1976 }
1977
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)1978 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
1979 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
1980 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
1981 {
1982 int rc = 0;
1983 LOCK_REQ *pSMB = NULL;
1984 struct kvec iov[2];
1985 struct kvec rsp_iov;
1986 int resp_buf_type;
1987 __u16 count;
1988
1989 cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
1990 num_lock, num_unlock);
1991
1992 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1993 if (rc)
1994 return rc;
1995
1996 pSMB->Timeout = 0;
1997 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
1998 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
1999 pSMB->LockType = lock_type;
2000 pSMB->AndXCommand = 0xFF; /* none */
2001 pSMB->Fid = netfid; /* netfid stays le */
2002
2003 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2004 inc_rfc1001_len(pSMB, count);
2005 pSMB->ByteCount = cpu_to_le16(count);
2006
2007 iov[0].iov_base = (char *)pSMB;
2008 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2009 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2010 iov[1].iov_base = (char *)buf;
2011 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2012
2013 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2014 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
2015 CIFS_NO_RSP_BUF, &rsp_iov);
2016 cifs_small_buf_release(pSMB);
2017 if (rc)
2018 cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2019
2020 return rc;
2021 }
2022
2023 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)2024 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2025 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2026 const __u64 offset, const __u32 numUnlock,
2027 const __u32 numLock, const __u8 lockType,
2028 const bool waitFlag, const __u8 oplock_level)
2029 {
2030 int rc = 0;
2031 LOCK_REQ *pSMB = NULL;
2032 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2033 int bytes_returned;
2034 int flags = 0;
2035 __u16 count;
2036
2037 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2038 (int)waitFlag, numLock);
2039 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2040
2041 if (rc)
2042 return rc;
2043
2044 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2045 /* no response expected */
2046 flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
2047 pSMB->Timeout = 0;
2048 } else if (waitFlag) {
2049 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2050 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2051 } else {
2052 pSMB->Timeout = 0;
2053 }
2054
2055 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2056 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2057 pSMB->LockType = lockType;
2058 pSMB->OplockLevel = oplock_level;
2059 pSMB->AndXCommand = 0xFF; /* none */
2060 pSMB->Fid = smb_file_id; /* netfid stays le */
2061
2062 if ((numLock != 0) || (numUnlock != 0)) {
2063 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2064 /* BB where to store pid high? */
2065 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2066 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2067 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2068 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2069 count = sizeof(LOCKING_ANDX_RANGE);
2070 } else {
2071 /* oplock break */
2072 count = 0;
2073 }
2074 inc_rfc1001_len(pSMB, count);
2075 pSMB->ByteCount = cpu_to_le16(count);
2076
2077 if (waitFlag)
2078 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2079 (struct smb_hdr *) pSMB, &bytes_returned);
2080 else
2081 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2082 cifs_small_buf_release(pSMB);
2083 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2084 if (rc)
2085 cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2086
2087 /* Note: On -EAGAIN error only caller can retry on handle based calls
2088 since file handle passed in no longer valid */
2089 return rc;
2090 }
2091
2092 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)2093 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2094 const __u16 smb_file_id, const __u32 netpid,
2095 const loff_t start_offset, const __u64 len,
2096 struct file_lock *pLockData, const __u16 lock_type,
2097 const bool waitFlag)
2098 {
2099 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2100 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2101 struct cifs_posix_lock *parm_data;
2102 int rc = 0;
2103 int timeout = 0;
2104 int bytes_returned = 0;
2105 int resp_buf_type = 0;
2106 __u16 params, param_offset, offset, byte_count, count;
2107 struct kvec iov[1];
2108 struct kvec rsp_iov;
2109
2110 cifs_dbg(FYI, "Posix Lock\n");
2111
2112 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2113
2114 if (rc)
2115 return rc;
2116
2117 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2118
2119 params = 6;
2120 pSMB->MaxSetupCount = 0;
2121 pSMB->Reserved = 0;
2122 pSMB->Flags = 0;
2123 pSMB->Reserved2 = 0;
2124 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2125 offset = param_offset + params;
2126
2127 count = sizeof(struct cifs_posix_lock);
2128 pSMB->MaxParameterCount = cpu_to_le16(2);
2129 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2130 pSMB->SetupCount = 1;
2131 pSMB->Reserved3 = 0;
2132 if (pLockData)
2133 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2134 else
2135 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2136 byte_count = 3 /* pad */ + params + count;
2137 pSMB->DataCount = cpu_to_le16(count);
2138 pSMB->ParameterCount = cpu_to_le16(params);
2139 pSMB->TotalDataCount = pSMB->DataCount;
2140 pSMB->TotalParameterCount = pSMB->ParameterCount;
2141 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2142 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2143 parm_data = (struct cifs_posix_lock *)
2144 (((char *)pSMB) + offset + 4);
2145
2146 parm_data->lock_type = cpu_to_le16(lock_type);
2147 if (waitFlag) {
2148 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2149 parm_data->lock_flags = cpu_to_le16(1);
2150 pSMB->Timeout = cpu_to_le32(-1);
2151 } else
2152 pSMB->Timeout = 0;
2153
2154 parm_data->pid = cpu_to_le32(netpid);
2155 parm_data->start = cpu_to_le64(start_offset);
2156 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2157
2158 pSMB->DataOffset = cpu_to_le16(offset);
2159 pSMB->Fid = smb_file_id;
2160 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2161 pSMB->Reserved4 = 0;
2162 inc_rfc1001_len(pSMB, byte_count);
2163 pSMB->ByteCount = cpu_to_le16(byte_count);
2164 if (waitFlag) {
2165 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2166 (struct smb_hdr *) pSMBr, &bytes_returned);
2167 } else {
2168 iov[0].iov_base = (char *)pSMB;
2169 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2170 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2171 &resp_buf_type, timeout, &rsp_iov);
2172 pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2173 }
2174 cifs_small_buf_release(pSMB);
2175
2176 if (rc) {
2177 cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2178 } else if (pLockData) {
2179 /* lock structure can be returned on get */
2180 __u16 data_offset;
2181 __u16 data_count;
2182 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2183
2184 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2185 rc = -EIO; /* bad smb */
2186 goto plk_err_exit;
2187 }
2188 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2189 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2190 if (data_count < sizeof(struct cifs_posix_lock)) {
2191 rc = -EIO;
2192 goto plk_err_exit;
2193 }
2194 parm_data = (struct cifs_posix_lock *)
2195 ((char *)&pSMBr->hdr.Protocol + data_offset);
2196 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2197 pLockData->c.flc_type = F_UNLCK;
2198 else {
2199 if (parm_data->lock_type ==
2200 cpu_to_le16(CIFS_RDLCK))
2201 pLockData->c.flc_type = F_RDLCK;
2202 else if (parm_data->lock_type ==
2203 cpu_to_le16(CIFS_WRLCK))
2204 pLockData->c.flc_type = F_WRLCK;
2205
2206 pLockData->fl_start = le64_to_cpu(parm_data->start);
2207 pLockData->fl_end = pLockData->fl_start +
2208 (le64_to_cpu(parm_data->length) ?
2209 le64_to_cpu(parm_data->length) - 1 : 0);
2210 pLockData->c.flc_pid = -le32_to_cpu(parm_data->pid);
2211 }
2212 }
2213
2214 plk_err_exit:
2215 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2216
2217 /* Note: On -EAGAIN error only caller can retry on handle based calls
2218 since file handle passed in no longer valid */
2219
2220 return rc;
2221 }
2222
2223
2224 int
CIFSSMBClose(const unsigned int xid,struct cifs_tcon * tcon,int smb_file_id)2225 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2226 {
2227 int rc = 0;
2228 CLOSE_REQ *pSMB = NULL;
2229 cifs_dbg(FYI, "In CIFSSMBClose\n");
2230
2231 /* do not retry on dead session on close */
2232 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2233 if (rc == -EAGAIN)
2234 return 0;
2235 if (rc)
2236 return rc;
2237
2238 pSMB->FileID = (__u16) smb_file_id;
2239 pSMB->LastWriteTime = 0xFFFFFFFF;
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_closes);
2244 if (rc) {
2245 if (rc != -EINTR) {
2246 /* EINTR is expected when user ctl-c to kill app */
2247 cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2248 }
2249 }
2250
2251 /* Since session is dead, file will be closed on server already */
2252 if (rc == -EAGAIN)
2253 rc = 0;
2254
2255 return rc;
2256 }
2257
2258 int
CIFSSMBFlush(const unsigned int xid,struct cifs_tcon * tcon,int smb_file_id)2259 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2260 {
2261 int rc = 0;
2262 FLUSH_REQ *pSMB = NULL;
2263 cifs_dbg(FYI, "In CIFSSMBFlush\n");
2264
2265 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2266 if (rc)
2267 return rc;
2268
2269 pSMB->FileID = (__u16) smb_file_id;
2270 pSMB->ByteCount = 0;
2271 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2272 cifs_small_buf_release(pSMB);
2273 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2274 if (rc)
2275 cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2276
2277 return rc;
2278 }
2279
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)2280 int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2281 struct dentry *source_dentry,
2282 const char *from_name, const char *to_name,
2283 struct cifs_sb_info *cifs_sb)
2284 {
2285 int rc = 0;
2286 RENAME_REQ *pSMB = NULL;
2287 RENAME_RSP *pSMBr = NULL;
2288 int bytes_returned;
2289 int name_len, name_len2;
2290 __u16 count;
2291 int remap = cifs_remap(cifs_sb);
2292
2293 cifs_dbg(FYI, "In CIFSSMBRename\n");
2294 renameRetry:
2295 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2296 (void **) &pSMBr);
2297 if (rc)
2298 return rc;
2299
2300 pSMB->BufferFormat = 0x04;
2301 pSMB->SearchAttributes =
2302 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2303 ATTR_DIRECTORY);
2304
2305 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2306 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2307 from_name, PATH_MAX,
2308 cifs_sb->local_nls, remap);
2309 name_len++; /* trailing null */
2310 name_len *= 2;
2311 pSMB->OldFileName[name_len] = 0x04; /* pad */
2312 /* protocol requires ASCII signature byte on Unicode string */
2313 pSMB->OldFileName[name_len + 1] = 0x00;
2314 name_len2 =
2315 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2316 to_name, PATH_MAX, cifs_sb->local_nls,
2317 remap);
2318 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2319 name_len2 *= 2; /* convert to bytes */
2320 } else {
2321 name_len = copy_path_name(pSMB->OldFileName, from_name);
2322 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2323 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2324 name_len2++; /* signature byte */
2325 }
2326
2327 count = 1 /* 1st signature byte */ + name_len + name_len2;
2328 inc_rfc1001_len(pSMB, count);
2329 pSMB->ByteCount = cpu_to_le16(count);
2330
2331 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2332 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2333 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2334 if (rc)
2335 cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2336
2337 cifs_buf_release(pSMB);
2338
2339 if (rc == -EAGAIN)
2340 goto renameRetry;
2341
2342 return rc;
2343 }
2344
CIFSSMBRenameOpenFile(const unsigned int xid,struct cifs_tcon * pTcon,int netfid,const char * target_name,const struct nls_table * nls_codepage,int remap)2345 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2346 int netfid, const char *target_name,
2347 const struct nls_table *nls_codepage, int remap)
2348 {
2349 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2350 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2351 struct set_file_rename *rename_info;
2352 char *data_offset;
2353 char dummy_string[30];
2354 int rc = 0;
2355 int bytes_returned = 0;
2356 int len_of_str;
2357 __u16 params, param_offset, offset, count, byte_count;
2358
2359 cifs_dbg(FYI, "Rename to File by handle\n");
2360 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2361 (void **) &pSMBr);
2362 if (rc)
2363 return rc;
2364
2365 params = 6;
2366 pSMB->MaxSetupCount = 0;
2367 pSMB->Reserved = 0;
2368 pSMB->Flags = 0;
2369 pSMB->Timeout = 0;
2370 pSMB->Reserved2 = 0;
2371 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2372 offset = param_offset + params;
2373
2374 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2375 data_offset = (char *)(pSMB) + offset + 4;
2376 rename_info = (struct set_file_rename *) data_offset;
2377 pSMB->MaxParameterCount = cpu_to_le16(2);
2378 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2379 pSMB->SetupCount = 1;
2380 pSMB->Reserved3 = 0;
2381 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2382 byte_count = 3 /* pad */ + params;
2383 pSMB->ParameterCount = cpu_to_le16(params);
2384 pSMB->TotalParameterCount = pSMB->ParameterCount;
2385 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2386 pSMB->DataOffset = cpu_to_le16(offset);
2387 /* construct random name ".cifs_tmp<inodenum><mid>" */
2388 rename_info->overwrite = cpu_to_le32(1);
2389 rename_info->root_fid = 0;
2390 /* unicode only call */
2391 if (target_name == NULL) {
2392 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2393 len_of_str =
2394 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2395 dummy_string, 24, nls_codepage, remap);
2396 } else {
2397 len_of_str =
2398 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2399 target_name, PATH_MAX, nls_codepage,
2400 remap);
2401 }
2402 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2403 count = sizeof(struct set_file_rename) + (2 * len_of_str);
2404 byte_count += count;
2405 pSMB->DataCount = cpu_to_le16(count);
2406 pSMB->TotalDataCount = pSMB->DataCount;
2407 pSMB->Fid = netfid;
2408 pSMB->InformationLevel =
2409 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2410 pSMB->Reserved4 = 0;
2411 inc_rfc1001_len(pSMB, byte_count);
2412 pSMB->ByteCount = cpu_to_le16(byte_count);
2413 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2414 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2415 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2416 if (rc)
2417 cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2418 rc);
2419
2420 cifs_buf_release(pSMB);
2421
2422 /* Note: On -EAGAIN error only caller can retry on handle based calls
2423 since file handle passed in no longer valid */
2424
2425 return rc;
2426 }
2427
2428 int
CIFSUnixCreateSymLink(const unsigned int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2429 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2430 const char *fromName, const char *toName,
2431 const struct nls_table *nls_codepage, int remap)
2432 {
2433 TRANSACTION2_SPI_REQ *pSMB = NULL;
2434 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2435 char *data_offset;
2436 int name_len;
2437 int name_len_target;
2438 int rc = 0;
2439 int bytes_returned = 0;
2440 __u16 params, param_offset, offset, byte_count;
2441
2442 cifs_dbg(FYI, "In Symlink Unix style\n");
2443 createSymLinkRetry:
2444 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2445 (void **) &pSMBr);
2446 if (rc)
2447 return rc;
2448
2449 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2450 name_len =
2451 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2452 /* find define for this maxpathcomponent */
2453 PATH_MAX, nls_codepage, remap);
2454 name_len++; /* trailing null */
2455 name_len *= 2;
2456
2457 } else {
2458 name_len = copy_path_name(pSMB->FileName, fromName);
2459 }
2460 params = 6 + name_len;
2461 pSMB->MaxSetupCount = 0;
2462 pSMB->Reserved = 0;
2463 pSMB->Flags = 0;
2464 pSMB->Timeout = 0;
2465 pSMB->Reserved2 = 0;
2466 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2467 InformationLevel) - 4;
2468 offset = param_offset + params;
2469
2470 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2471 data_offset = (char *)pSMB + offset + 4;
2472 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2473 name_len_target =
2474 cifsConvertToUTF16((__le16 *) data_offset, toName,
2475 /* find define for this maxpathcomponent */
2476 PATH_MAX, nls_codepage, remap);
2477 name_len_target++; /* trailing null */
2478 name_len_target *= 2;
2479 } else {
2480 name_len_target = copy_path_name(data_offset, toName);
2481 }
2482
2483 pSMB->MaxParameterCount = cpu_to_le16(2);
2484 /* BB find exact max on data count below from sess */
2485 pSMB->MaxDataCount = cpu_to_le16(1000);
2486 pSMB->SetupCount = 1;
2487 pSMB->Reserved3 = 0;
2488 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2489 byte_count = 3 /* pad */ + params + name_len_target;
2490 pSMB->DataCount = cpu_to_le16(name_len_target);
2491 pSMB->ParameterCount = cpu_to_le16(params);
2492 pSMB->TotalDataCount = pSMB->DataCount;
2493 pSMB->TotalParameterCount = pSMB->ParameterCount;
2494 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2495 pSMB->DataOffset = cpu_to_le16(offset);
2496 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2497 pSMB->Reserved4 = 0;
2498 inc_rfc1001_len(pSMB, byte_count);
2499 pSMB->ByteCount = cpu_to_le16(byte_count);
2500 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2501 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2502 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2503 if (rc)
2504 cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2505 rc);
2506
2507 cifs_buf_release(pSMB);
2508
2509 if (rc == -EAGAIN)
2510 goto createSymLinkRetry;
2511
2512 return rc;
2513 }
2514
2515 int
CIFSUnixCreateHardLink(const unsigned int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2516 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2517 const char *fromName, const char *toName,
2518 const struct nls_table *nls_codepage, int remap)
2519 {
2520 TRANSACTION2_SPI_REQ *pSMB = NULL;
2521 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2522 char *data_offset;
2523 int name_len;
2524 int name_len_target;
2525 int rc = 0;
2526 int bytes_returned = 0;
2527 __u16 params, param_offset, offset, byte_count;
2528
2529 cifs_dbg(FYI, "In Create Hard link Unix style\n");
2530 createHardLinkRetry:
2531 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2532 (void **) &pSMBr);
2533 if (rc)
2534 return rc;
2535
2536 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2537 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2538 PATH_MAX, nls_codepage, remap);
2539 name_len++; /* trailing null */
2540 name_len *= 2;
2541
2542 } else {
2543 name_len = copy_path_name(pSMB->FileName, toName);
2544 }
2545 params = 6 + name_len;
2546 pSMB->MaxSetupCount = 0;
2547 pSMB->Reserved = 0;
2548 pSMB->Flags = 0;
2549 pSMB->Timeout = 0;
2550 pSMB->Reserved2 = 0;
2551 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2552 InformationLevel) - 4;
2553 offset = param_offset + params;
2554
2555 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
2556 data_offset = (char *)pSMB + offset + 4;
2557 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2558 name_len_target =
2559 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2560 PATH_MAX, nls_codepage, remap);
2561 name_len_target++; /* trailing null */
2562 name_len_target *= 2;
2563 } else {
2564 name_len_target = copy_path_name(data_offset, fromName);
2565 }
2566
2567 pSMB->MaxParameterCount = cpu_to_le16(2);
2568 /* BB find exact max on data count below from sess*/
2569 pSMB->MaxDataCount = cpu_to_le16(1000);
2570 pSMB->SetupCount = 1;
2571 pSMB->Reserved3 = 0;
2572 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2573 byte_count = 3 /* pad */ + params + name_len_target;
2574 pSMB->ParameterCount = cpu_to_le16(params);
2575 pSMB->TotalParameterCount = pSMB->ParameterCount;
2576 pSMB->DataCount = cpu_to_le16(name_len_target);
2577 pSMB->TotalDataCount = pSMB->DataCount;
2578 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2579 pSMB->DataOffset = cpu_to_le16(offset);
2580 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2581 pSMB->Reserved4 = 0;
2582 inc_rfc1001_len(pSMB, byte_count);
2583 pSMB->ByteCount = cpu_to_le16(byte_count);
2584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2585 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2586 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2587 if (rc)
2588 cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2589 rc);
2590
2591 cifs_buf_release(pSMB);
2592 if (rc == -EAGAIN)
2593 goto createHardLinkRetry;
2594
2595 return rc;
2596 }
2597
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)2598 int CIFSCreateHardLink(const unsigned int xid,
2599 struct cifs_tcon *tcon,
2600 struct dentry *source_dentry,
2601 const char *from_name, const char *to_name,
2602 struct cifs_sb_info *cifs_sb)
2603 {
2604 int rc = 0;
2605 NT_RENAME_REQ *pSMB = NULL;
2606 RENAME_RSP *pSMBr = NULL;
2607 int bytes_returned;
2608 int name_len, name_len2;
2609 __u16 count;
2610 int remap = cifs_remap(cifs_sb);
2611
2612 cifs_dbg(FYI, "In CIFSCreateHardLink\n");
2613 winCreateHardLinkRetry:
2614
2615 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2616 (void **) &pSMBr);
2617 if (rc)
2618 return rc;
2619
2620 pSMB->SearchAttributes =
2621 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2622 ATTR_DIRECTORY);
2623 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2624 pSMB->ClusterCount = 0;
2625
2626 pSMB->BufferFormat = 0x04;
2627
2628 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2629 name_len =
2630 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2631 PATH_MAX, cifs_sb->local_nls, remap);
2632 name_len++; /* trailing null */
2633 name_len *= 2;
2634
2635 /* protocol specifies ASCII buffer format (0x04) for unicode */
2636 pSMB->OldFileName[name_len] = 0x04;
2637 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2638 name_len2 =
2639 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2640 to_name, PATH_MAX, cifs_sb->local_nls,
2641 remap);
2642 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2643 name_len2 *= 2; /* convert to bytes */
2644 } else {
2645 name_len = copy_path_name(pSMB->OldFileName, from_name);
2646 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2647 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2648 name_len2++; /* signature byte */
2649 }
2650
2651 count = 1 /* string type byte */ + name_len + name_len2;
2652 inc_rfc1001_len(pSMB, count);
2653 pSMB->ByteCount = cpu_to_le16(count);
2654
2655 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2656 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2657 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2658 if (rc)
2659 cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
2660
2661 cifs_buf_release(pSMB);
2662 if (rc == -EAGAIN)
2663 goto winCreateHardLinkRetry;
2664
2665 return rc;
2666 }
2667
2668 int
CIFSSMBUnixQuerySymLink(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * searchName,char ** symlinkinfo,const struct nls_table * nls_codepage,int remap)2669 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
2670 const unsigned char *searchName, char **symlinkinfo,
2671 const struct nls_table *nls_codepage, int remap)
2672 {
2673 /* SMB_QUERY_FILE_UNIX_LINK */
2674 TRANSACTION2_QPI_REQ *pSMB = NULL;
2675 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2676 int rc = 0;
2677 int bytes_returned;
2678 int name_len;
2679 __u16 params, byte_count;
2680 char *data_start;
2681
2682 cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
2683
2684 querySymLinkRetry:
2685 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2686 (void **) &pSMBr);
2687 if (rc)
2688 return rc;
2689
2690 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2691 name_len =
2692 cifsConvertToUTF16((__le16 *) pSMB->FileName,
2693 searchName, PATH_MAX, nls_codepage,
2694 remap);
2695 name_len++; /* trailing null */
2696 name_len *= 2;
2697 } else {
2698 name_len = copy_path_name(pSMB->FileName, searchName);
2699 }
2700
2701 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2702 pSMB->TotalDataCount = 0;
2703 pSMB->MaxParameterCount = cpu_to_le16(2);
2704 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2705 pSMB->MaxSetupCount = 0;
2706 pSMB->Reserved = 0;
2707 pSMB->Flags = 0;
2708 pSMB->Timeout = 0;
2709 pSMB->Reserved2 = 0;
2710 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2711 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2712 pSMB->DataCount = 0;
2713 pSMB->DataOffset = 0;
2714 pSMB->SetupCount = 1;
2715 pSMB->Reserved3 = 0;
2716 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2717 byte_count = params + 1 /* pad */ ;
2718 pSMB->TotalParameterCount = cpu_to_le16(params);
2719 pSMB->ParameterCount = pSMB->TotalParameterCount;
2720 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2721 pSMB->Reserved4 = 0;
2722 inc_rfc1001_len(pSMB, byte_count);
2723 pSMB->ByteCount = cpu_to_le16(byte_count);
2724
2725 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2726 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2727 if (rc) {
2728 cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
2729 } else {
2730 /* decode response */
2731
2732 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2733 /* BB also check enough total bytes returned */
2734 if (rc || get_bcc(&pSMBr->hdr) < 2)
2735 rc = -EIO;
2736 else {
2737 bool is_unicode;
2738 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2739
2740 data_start = ((char *) &pSMBr->hdr.Protocol) +
2741 le16_to_cpu(pSMBr->t2.DataOffset);
2742
2743 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2744 is_unicode = true;
2745 else
2746 is_unicode = false;
2747
2748 /* BB FIXME investigate remapping reserved chars here */
2749 *symlinkinfo = cifs_strndup_from_utf16(data_start,
2750 count, is_unicode, nls_codepage);
2751 if (!*symlinkinfo)
2752 rc = -ENOMEM;
2753 }
2754 }
2755 cifs_buf_release(pSMB);
2756 if (rc == -EAGAIN)
2757 goto querySymLinkRetry;
2758 return rc;
2759 }
2760
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)2761 int cifs_query_reparse_point(const unsigned int xid,
2762 struct cifs_tcon *tcon,
2763 struct cifs_sb_info *cifs_sb,
2764 const char *full_path,
2765 u32 *tag, struct kvec *rsp,
2766 int *rsp_buftype)
2767 {
2768 struct reparse_data_buffer *buf;
2769 struct cifs_open_parms oparms;
2770 TRANSACT_IOCTL_REQ *io_req = NULL;
2771 TRANSACT_IOCTL_RSP *io_rsp = NULL;
2772 struct cifs_fid fid;
2773 __u32 data_offset, data_count, len;
2774 __u8 *start, *end;
2775 int io_rsp_len;
2776 int oplock = 0;
2777 int rc;
2778
2779 cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
2780
2781 if (cap_unix(tcon->ses))
2782 return -EOPNOTSUPP;
2783
2784 if (!CIFS_REPARSE_SUPPORT(tcon))
2785 return -EOPNOTSUPP;
2786
2787 oparms = (struct cifs_open_parms) {
2788 .tcon = tcon,
2789 .cifs_sb = cifs_sb,
2790 .desired_access = FILE_READ_ATTRIBUTES,
2791 .create_options = cifs_create_options(cifs_sb,
2792 OPEN_REPARSE_POINT),
2793 .disposition = FILE_OPEN,
2794 .path = full_path,
2795 .fid = &fid,
2796 };
2797
2798 rc = CIFS_open(xid, &oparms, &oplock, NULL);
2799 if (rc)
2800 return rc;
2801
2802 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon,
2803 (void **)&io_req, (void **)&io_rsp);
2804 if (rc)
2805 goto error;
2806
2807 io_req->TotalParameterCount = 0;
2808 io_req->TotalDataCount = 0;
2809 io_req->MaxParameterCount = cpu_to_le32(0);
2810 /* BB find exact data count max from sess structure BB */
2811 io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
2812 io_req->MaxSetupCount = 1;
2813 io_req->Reserved = 0;
2814 io_req->ParameterOffset = 0;
2815 io_req->DataCount = 0;
2816 io_req->DataOffset = 0;
2817 io_req->SetupCount = 4;
2818 io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2819 io_req->ParameterCount = io_req->TotalParameterCount;
2820 io_req->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2821 io_req->IsFsctl = 1;
2822 io_req->IsRootFlag = 0;
2823 io_req->Fid = fid.netfid;
2824 io_req->ByteCount = 0;
2825
2826 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)io_req,
2827 (struct smb_hdr *)io_rsp, &io_rsp_len, 0);
2828 if (rc)
2829 goto error;
2830
2831 data_offset = le32_to_cpu(io_rsp->DataOffset);
2832 data_count = le32_to_cpu(io_rsp->DataCount);
2833 if (get_bcc(&io_rsp->hdr) < 2 || data_offset > 512 ||
2834 !data_count || data_count > 2048) {
2835 rc = -EIO;
2836 goto error;
2837 }
2838
2839 /* SetupCount must be 1, otherwise offset to ByteCount is incorrect. */
2840 if (io_rsp->SetupCount != 1) {
2841 rc = -EIO;
2842 goto error;
2843 }
2844
2845 /*
2846 * ReturnedDataLen is output length of executed IOCTL.
2847 * DataCount is output length transferred over network.
2848 * Check that we have full FSCTL_GET_REPARSE_POINT buffer.
2849 */
2850 if (data_count != le16_to_cpu(io_rsp->ReturnedDataLen)) {
2851 rc = -EIO;
2852 goto error;
2853 }
2854
2855 end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
2856 start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
2857 if (start >= end) {
2858 rc = -EIO;
2859 goto error;
2860 }
2861
2862 data_count = le16_to_cpu(io_rsp->ByteCount);
2863 buf = (struct reparse_data_buffer *)start;
2864 len = sizeof(*buf);
2865 if (data_count < len ||
2866 data_count < le16_to_cpu(buf->ReparseDataLength) + len) {
2867 rc = -EIO;
2868 goto error;
2869 }
2870
2871 *tag = le32_to_cpu(buf->ReparseTag);
2872 rsp->iov_base = io_rsp;
2873 rsp->iov_len = io_rsp_len;
2874 *rsp_buftype = CIFS_LARGE_BUFFER;
2875 CIFSSMBClose(xid, tcon, fid.netfid);
2876 return 0;
2877
2878 error:
2879 cifs_buf_release(io_req);
2880 CIFSSMBClose(xid, tcon, fid.netfid);
2881 return rc;
2882 }
2883
cifs_create_reparse_inode(struct cifs_open_info_data * data,struct super_block * sb,const unsigned int xid,struct cifs_tcon * tcon,const char * full_path,bool directory,struct kvec * reparse_iov,struct kvec * xattr_iov)2884 struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data,
2885 struct super_block *sb,
2886 const unsigned int xid,
2887 struct cifs_tcon *tcon,
2888 const char *full_path,
2889 bool directory,
2890 struct kvec *reparse_iov,
2891 struct kvec *xattr_iov)
2892 {
2893 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
2894 struct cifs_open_parms oparms;
2895 TRANSACT_IOCTL_REQ *io_req;
2896 struct inode *new = NULL;
2897 struct kvec in_iov[2];
2898 struct kvec out_iov;
2899 struct cifs_fid fid;
2900 int io_req_len;
2901 int oplock = 0;
2902 int buf_type = 0;
2903 int rc;
2904
2905 cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
2906
2907 /*
2908 * If server filesystem does not support reparse points then do not
2909 * attempt to create reparse point. This will prevent creating unusable
2910 * empty object on the server.
2911 */
2912 if (!CIFS_REPARSE_SUPPORT(tcon))
2913 return ERR_PTR(-EOPNOTSUPP);
2914
2915 #ifndef CONFIG_CIFS_XATTR
2916 if (xattr_iov)
2917 return ERR_PTR(-EOPNOTSUPP);
2918 #endif
2919
2920 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
2921 FILE_READ_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA,
2922 FILE_CREATE,
2923 (directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
2924 ACL_NO_MODE);
2925 oparms.fid = &fid;
2926
2927 rc = CIFS_open(xid, &oparms, &oplock, NULL);
2928 if (rc)
2929 return ERR_PTR(rc);
2930
2931 #ifdef CONFIG_CIFS_XATTR
2932 if (xattr_iov) {
2933 struct smb2_file_full_ea_info *ea;
2934
2935 ea = &((struct smb2_create_ea_ctx *)xattr_iov->iov_base)->ea;
2936 while (1) {
2937 rc = CIFSSMBSetEA(xid,
2938 tcon,
2939 full_path,
2940 &ea->ea_data[0],
2941 &ea->ea_data[ea->ea_name_length+1],
2942 le16_to_cpu(ea->ea_value_length),
2943 cifs_sb->local_nls,
2944 cifs_sb);
2945 if (rc)
2946 goto out_close;
2947 if (le32_to_cpu(ea->next_entry_offset) == 0)
2948 break;
2949 ea = (struct smb2_file_full_ea_info *)((u8 *)ea +
2950 le32_to_cpu(ea->next_entry_offset));
2951 }
2952 }
2953 #endif
2954
2955 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **)&io_req, NULL);
2956 if (rc)
2957 goto out_close;
2958
2959 inc_rfc1001_len(io_req, sizeof(io_req->Pad));
2960
2961 io_req_len = be32_to_cpu(io_req->hdr.smb_buf_length) + sizeof(io_req->hdr.smb_buf_length);
2962
2963 /* NT IOCTL response contains one-word long output setup buffer with size of output data. */
2964 io_req->MaxSetupCount = 1;
2965 /* NT IOCTL response does not contain output parameters. */
2966 io_req->MaxParameterCount = cpu_to_le32(0);
2967 /* FSCTL_SET_REPARSE_POINT response contains empty output data. */
2968 io_req->MaxDataCount = cpu_to_le32(0);
2969
2970 io_req->TotalParameterCount = cpu_to_le32(0);
2971 io_req->TotalDataCount = cpu_to_le32(reparse_iov->iov_len);
2972 io_req->ParameterCount = io_req->TotalParameterCount;
2973 io_req->ParameterOffset = cpu_to_le32(0);
2974 io_req->DataCount = io_req->TotalDataCount;
2975 io_req->DataOffset = cpu_to_le32(offsetof(typeof(*io_req), Data) -
2976 sizeof(io_req->hdr.smb_buf_length));
2977 io_req->SetupCount = 4;
2978 io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2979 io_req->FunctionCode = cpu_to_le32(FSCTL_SET_REPARSE_POINT);
2980 io_req->Fid = fid.netfid;
2981 io_req->IsFsctl = 1;
2982 io_req->IsRootFlag = 0;
2983 io_req->ByteCount = cpu_to_le16(le32_to_cpu(io_req->DataCount) + sizeof(io_req->Pad));
2984
2985 inc_rfc1001_len(io_req, reparse_iov->iov_len);
2986
2987 in_iov[0].iov_base = (char *)io_req;
2988 in_iov[0].iov_len = io_req_len;
2989 in_iov[1] = *reparse_iov;
2990 rc = SendReceive2(xid, tcon->ses, in_iov, ARRAY_SIZE(in_iov), &buf_type,
2991 CIFS_NO_RSP_BUF, &out_iov);
2992
2993 cifs_buf_release(io_req);
2994
2995 if (!rc)
2996 rc = cifs_get_inode_info(&new, full_path, data, sb, xid, NULL);
2997
2998 out_close:
2999 CIFSSMBClose(xid, tcon, fid.netfid);
3000
3001 /*
3002 * If CREATE was successful but FSCTL_SET_REPARSE_POINT failed then
3003 * remove the intermediate object created by CREATE. Otherwise
3004 * empty object stay on the server when reparse call failed.
3005 */
3006 if (rc)
3007 CIFSSMBDelFile(xid, tcon, full_path, cifs_sb, NULL);
3008
3009 return rc ? ERR_PTR(rc) : new;
3010 }
3011
3012 int
CIFSSMB_set_compression(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid)3013 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3014 __u16 fid)
3015 {
3016 int rc = 0;
3017 int bytes_returned;
3018 struct smb_com_transaction_compr_ioctl_req *pSMB;
3019 struct smb_com_transaction_ioctl_rsp *pSMBr;
3020
3021 cifs_dbg(FYI, "Set compression for %u\n", fid);
3022 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3023 (void **) &pSMBr);
3024 if (rc)
3025 return rc;
3026
3027 pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3028
3029 pSMB->TotalParameterCount = 0;
3030 pSMB->TotalDataCount = cpu_to_le32(2);
3031 pSMB->MaxParameterCount = 0;
3032 pSMB->MaxDataCount = 0;
3033 pSMB->MaxSetupCount = 4;
3034 pSMB->Reserved = 0;
3035 pSMB->ParameterOffset = 0;
3036 pSMB->DataCount = cpu_to_le32(2);
3037 pSMB->DataOffset =
3038 cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3039 compression_state) - 4); /* 84 */
3040 pSMB->SetupCount = 4;
3041 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3042 pSMB->ParameterCount = 0;
3043 pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3044 pSMB->IsFsctl = 1; /* FSCTL */
3045 pSMB->IsRootFlag = 0;
3046 pSMB->Fid = fid; /* file handle always le */
3047 /* 3 byte pad, followed by 2 byte compress state */
3048 pSMB->ByteCount = cpu_to_le16(5);
3049 inc_rfc1001_len(pSMB, 5);
3050
3051 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3052 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3053 if (rc)
3054 cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3055
3056 cifs_buf_release(pSMB);
3057
3058 /*
3059 * Note: On -EAGAIN error only caller can retry on handle based calls
3060 * since file handle passed in no longer valid.
3061 */
3062 return rc;
3063 }
3064
3065
3066 #ifdef CONFIG_CIFS_POSIX
3067
3068 #ifdef CONFIG_FS_POSIX_ACL
3069 /**
3070 * cifs_init_posix_acl - convert ACL from cifs to POSIX ACL format
3071 * @ace: POSIX ACL entry to store converted ACL into
3072 * @cifs_ace: ACL in cifs format
3073 *
3074 * Convert an Access Control Entry from wire format to local POSIX xattr
3075 * format.
3076 *
3077 * Note that the @cifs_uid member is used to store both {g,u}id_t.
3078 */
cifs_init_posix_acl(struct posix_acl_entry * ace,struct cifs_posix_ace * cifs_ace)3079 static void cifs_init_posix_acl(struct posix_acl_entry *ace,
3080 struct cifs_posix_ace *cifs_ace)
3081 {
3082 /* u8 cifs fields do not need le conversion */
3083 ace->e_perm = cifs_ace->cifs_e_perm;
3084 ace->e_tag = cifs_ace->cifs_e_tag;
3085
3086 switch (ace->e_tag) {
3087 case ACL_USER:
3088 ace->e_uid = make_kuid(&init_user_ns,
3089 le64_to_cpu(cifs_ace->cifs_uid));
3090 break;
3091 case ACL_GROUP:
3092 ace->e_gid = make_kgid(&init_user_ns,
3093 le64_to_cpu(cifs_ace->cifs_uid));
3094 break;
3095 }
3096 return;
3097 }
3098
3099 /**
3100 * cifs_to_posix_acl - copy cifs ACL format to POSIX ACL format
3101 * @acl: ACLs returned in POSIX ACL format
3102 * @src: ACLs in cifs format
3103 * @acl_type: type of POSIX ACL requested
3104 * @size_of_data_area: size of SMB we got
3105 *
3106 * This function converts ACLs from cifs format to POSIX ACL format.
3107 * If @acl is NULL then the size of the buffer required to store POSIX ACLs in
3108 * their uapi format is returned.
3109 */
cifs_to_posix_acl(struct posix_acl ** acl,char * src,const int acl_type,const int size_of_data_area)3110 static int cifs_to_posix_acl(struct posix_acl **acl, char *src,
3111 const int acl_type, const int size_of_data_area)
3112 {
3113 int size = 0;
3114 __u16 count;
3115 struct cifs_posix_ace *pACE;
3116 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3117 struct posix_acl *kacl = NULL;
3118 struct posix_acl_entry *pa, *pe;
3119
3120 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3121 return -EOPNOTSUPP;
3122
3123 if (acl_type == ACL_TYPE_ACCESS) {
3124 count = le16_to_cpu(cifs_acl->access_entry_count);
3125 pACE = &cifs_acl->ace_array[0];
3126 size = sizeof(struct cifs_posix_acl);
3127 size += sizeof(struct cifs_posix_ace) * count;
3128 /* check if we would go beyond end of SMB */
3129 if (size_of_data_area < size) {
3130 cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3131 size_of_data_area, size);
3132 return -EINVAL;
3133 }
3134 } else if (acl_type == ACL_TYPE_DEFAULT) {
3135 count = le16_to_cpu(cifs_acl->access_entry_count);
3136 size = sizeof(struct cifs_posix_acl);
3137 size += sizeof(struct cifs_posix_ace) * count;
3138 /* skip past access ACEs to get to default ACEs */
3139 pACE = &cifs_acl->ace_array[count];
3140 count = le16_to_cpu(cifs_acl->default_entry_count);
3141 size += sizeof(struct cifs_posix_ace) * count;
3142 /* check if we would go beyond end of SMB */
3143 if (size_of_data_area < size)
3144 return -EINVAL;
3145 } else {
3146 /* illegal type */
3147 return -EINVAL;
3148 }
3149
3150 /* Allocate number of POSIX ACLs to store in VFS format. */
3151 kacl = posix_acl_alloc(count, GFP_NOFS);
3152 if (!kacl)
3153 return -ENOMEM;
3154
3155 FOREACH_ACL_ENTRY(pa, kacl, pe) {
3156 cifs_init_posix_acl(pa, pACE);
3157 pACE++;
3158 }
3159
3160 *acl = kacl;
3161 return 0;
3162 }
3163
3164 /**
3165 * cifs_init_ace - convert ACL entry from POSIX ACL to cifs format
3166 * @cifs_ace: the cifs ACL entry to store into
3167 * @local_ace: the POSIX ACL entry to convert
3168 */
cifs_init_ace(struct cifs_posix_ace * cifs_ace,const struct posix_acl_entry * local_ace)3169 static void cifs_init_ace(struct cifs_posix_ace *cifs_ace,
3170 const struct posix_acl_entry *local_ace)
3171 {
3172 cifs_ace->cifs_e_perm = local_ace->e_perm;
3173 cifs_ace->cifs_e_tag = local_ace->e_tag;
3174
3175 switch (local_ace->e_tag) {
3176 case ACL_USER:
3177 cifs_ace->cifs_uid =
3178 cpu_to_le64(from_kuid(&init_user_ns, local_ace->e_uid));
3179 break;
3180 case ACL_GROUP:
3181 cifs_ace->cifs_uid =
3182 cpu_to_le64(from_kgid(&init_user_ns, local_ace->e_gid));
3183 break;
3184 default:
3185 cifs_ace->cifs_uid = cpu_to_le64(-1);
3186 }
3187 }
3188
3189 /**
3190 * posix_acl_to_cifs - convert ACLs from POSIX ACL to cifs format
3191 * @parm_data: ACLs in cifs format to convert to
3192 * @acl: ACLs in POSIX ACL format to convert from
3193 * @acl_type: the type of POSIX ACLs stored in @acl
3194 *
3195 * Return: the number cifs ACL entries after conversion
3196 */
posix_acl_to_cifs(char * parm_data,const struct posix_acl * acl,const int acl_type)3197 static __u16 posix_acl_to_cifs(char *parm_data, const struct posix_acl *acl,
3198 const int acl_type)
3199 {
3200 __u16 rc = 0;
3201 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3202 const struct posix_acl_entry *pa, *pe;
3203 int count;
3204 int i = 0;
3205
3206 if ((acl == NULL) || (cifs_acl == NULL))
3207 return 0;
3208
3209 count = acl->a_count;
3210 cifs_dbg(FYI, "setting acl with %d entries\n", count);
3211
3212 /*
3213 * Note that the uapi POSIX ACL version is verified by the VFS and is
3214 * independent of the cifs ACL version. Changing the POSIX ACL version
3215 * is a uapi change and if it's changed we will pass down the POSIX ACL
3216 * version in struct posix_acl from the VFS. For now there's really
3217 * only one that all filesystems know how to deal with.
3218 */
3219 cifs_acl->version = cpu_to_le16(1);
3220 if (acl_type == ACL_TYPE_ACCESS) {
3221 cifs_acl->access_entry_count = cpu_to_le16(count);
3222 cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3223 } else if (acl_type == ACL_TYPE_DEFAULT) {
3224 cifs_acl->default_entry_count = cpu_to_le16(count);
3225 cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3226 } else {
3227 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3228 return 0;
3229 }
3230 FOREACH_ACL_ENTRY(pa, acl, pe) {
3231 cifs_init_ace(&cifs_acl->ace_array[i++], pa);
3232 }
3233 if (rc == 0) {
3234 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3235 rc += sizeof(struct cifs_posix_acl);
3236 /* BB add check to make sure ACL does not overflow SMB */
3237 }
3238 return rc;
3239 }
3240
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)3241 int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
3242 const unsigned char *searchName, struct posix_acl **acl,
3243 const int acl_type, const struct nls_table *nls_codepage,
3244 int remap)
3245 {
3246 /* SMB_QUERY_POSIX_ACL */
3247 TRANSACTION2_QPI_REQ *pSMB = NULL;
3248 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3249 int rc = 0;
3250 int bytes_returned;
3251 int name_len;
3252 __u16 params, byte_count;
3253
3254 cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3255
3256 queryAclRetry:
3257 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3258 (void **) &pSMBr);
3259 if (rc)
3260 return rc;
3261
3262 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3263 name_len =
3264 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3265 searchName, PATH_MAX, nls_codepage,
3266 remap);
3267 name_len++; /* trailing null */
3268 name_len *= 2;
3269 pSMB->FileName[name_len] = 0;
3270 pSMB->FileName[name_len+1] = 0;
3271 } else {
3272 name_len = copy_path_name(pSMB->FileName, searchName);
3273 }
3274
3275 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3276 pSMB->TotalDataCount = 0;
3277 pSMB->MaxParameterCount = cpu_to_le16(2);
3278 /* BB find exact max data count below from sess structure BB */
3279 pSMB->MaxDataCount = cpu_to_le16(4000);
3280 pSMB->MaxSetupCount = 0;
3281 pSMB->Reserved = 0;
3282 pSMB->Flags = 0;
3283 pSMB->Timeout = 0;
3284 pSMB->Reserved2 = 0;
3285 pSMB->ParameterOffset = cpu_to_le16(
3286 offsetof(struct smb_com_transaction2_qpi_req,
3287 InformationLevel) - 4);
3288 pSMB->DataCount = 0;
3289 pSMB->DataOffset = 0;
3290 pSMB->SetupCount = 1;
3291 pSMB->Reserved3 = 0;
3292 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3293 byte_count = params + 1 /* pad */ ;
3294 pSMB->TotalParameterCount = cpu_to_le16(params);
3295 pSMB->ParameterCount = pSMB->TotalParameterCount;
3296 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3297 pSMB->Reserved4 = 0;
3298 inc_rfc1001_len(pSMB, byte_count);
3299 pSMB->ByteCount = cpu_to_le16(byte_count);
3300
3301 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3302 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3303 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3304 if (rc) {
3305 cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3306 } else {
3307 /* decode response */
3308
3309 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3310 /* BB also check enough total bytes returned */
3311 if (rc || get_bcc(&pSMBr->hdr) < 2)
3312 rc = -EIO; /* bad smb */
3313 else {
3314 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3315 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3316 rc = cifs_to_posix_acl(acl,
3317 (char *)&pSMBr->hdr.Protocol+data_offset,
3318 acl_type, count);
3319 }
3320 }
3321 cifs_buf_release(pSMB);
3322 /*
3323 * The else branch after SendReceive() doesn't return EAGAIN so if we
3324 * allocated @acl in cifs_to_posix_acl() we are guaranteed to return
3325 * here and don't leak POSIX ACLs.
3326 */
3327 if (rc == -EAGAIN)
3328 goto queryAclRetry;
3329 return rc;
3330 }
3331
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)3332 int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
3333 const unsigned char *fileName, const struct posix_acl *acl,
3334 const int acl_type, const struct nls_table *nls_codepage,
3335 int remap)
3336 {
3337 struct smb_com_transaction2_spi_req *pSMB = NULL;
3338 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3339 char *parm_data;
3340 int name_len;
3341 int rc = 0;
3342 int bytes_returned = 0;
3343 __u16 params, byte_count, data_count, param_offset, offset;
3344
3345 cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3346 setAclRetry:
3347 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3348 (void **) &pSMBr);
3349 if (rc)
3350 return rc;
3351 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3352 name_len =
3353 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3354 PATH_MAX, nls_codepage, remap);
3355 name_len++; /* trailing null */
3356 name_len *= 2;
3357 } else {
3358 name_len = copy_path_name(pSMB->FileName, fileName);
3359 }
3360 params = 6 + name_len;
3361 pSMB->MaxParameterCount = cpu_to_le16(2);
3362 /* BB find max SMB size from sess */
3363 pSMB->MaxDataCount = cpu_to_le16(1000);
3364 pSMB->MaxSetupCount = 0;
3365 pSMB->Reserved = 0;
3366 pSMB->Flags = 0;
3367 pSMB->Timeout = 0;
3368 pSMB->Reserved2 = 0;
3369 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3370 InformationLevel) - 4;
3371 offset = param_offset + params;
3372 parm_data = ((char *)pSMB) + sizeof(pSMB->hdr.smb_buf_length) + offset;
3373 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3374
3375 /* convert to on the wire format for POSIX ACL */
3376 data_count = posix_acl_to_cifs(parm_data, acl, acl_type);
3377
3378 if (data_count == 0) {
3379 rc = -EOPNOTSUPP;
3380 goto setACLerrorExit;
3381 }
3382 pSMB->DataOffset = cpu_to_le16(offset);
3383 pSMB->SetupCount = 1;
3384 pSMB->Reserved3 = 0;
3385 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3386 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3387 byte_count = 3 /* pad */ + params + data_count;
3388 pSMB->DataCount = cpu_to_le16(data_count);
3389 pSMB->TotalDataCount = pSMB->DataCount;
3390 pSMB->ParameterCount = cpu_to_le16(params);
3391 pSMB->TotalParameterCount = pSMB->ParameterCount;
3392 pSMB->Reserved4 = 0;
3393 inc_rfc1001_len(pSMB, byte_count);
3394 pSMB->ByteCount = cpu_to_le16(byte_count);
3395 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3396 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3397 if (rc)
3398 cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3399
3400 setACLerrorExit:
3401 cifs_buf_release(pSMB);
3402 if (rc == -EAGAIN)
3403 goto setAclRetry;
3404 return rc;
3405 }
3406 #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)3407 int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
3408 const unsigned char *searchName, struct posix_acl **acl,
3409 const int acl_type, const struct nls_table *nls_codepage,
3410 int remap)
3411 {
3412 return -EOPNOTSUPP;
3413 }
3414
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)3415 int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
3416 const unsigned char *fileName, const struct posix_acl *acl,
3417 const int acl_type, const struct nls_table *nls_codepage,
3418 int remap)
3419 {
3420 return -EOPNOTSUPP;
3421 }
3422 #endif /* CONFIG_FS_POSIX_ACL */
3423
3424 int
CIFSGetExtAttr(const unsigned int xid,struct cifs_tcon * tcon,const int netfid,__u64 * pExtAttrBits,__u64 * pMask)3425 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3426 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3427 {
3428 int rc = 0;
3429 struct smb_t2_qfi_req *pSMB = NULL;
3430 struct smb_t2_qfi_rsp *pSMBr = NULL;
3431 int bytes_returned;
3432 __u16 params, byte_count;
3433
3434 cifs_dbg(FYI, "In GetExtAttr\n");
3435 if (tcon == NULL)
3436 return -ENODEV;
3437
3438 GetExtAttrRetry:
3439 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3440 (void **) &pSMBr);
3441 if (rc)
3442 return rc;
3443
3444 params = 2 /* level */ + 2 /* fid */;
3445 pSMB->t2.TotalDataCount = 0;
3446 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3447 /* BB find exact max data count below from sess structure BB */
3448 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3449 pSMB->t2.MaxSetupCount = 0;
3450 pSMB->t2.Reserved = 0;
3451 pSMB->t2.Flags = 0;
3452 pSMB->t2.Timeout = 0;
3453 pSMB->t2.Reserved2 = 0;
3454 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3455 Fid) - 4);
3456 pSMB->t2.DataCount = 0;
3457 pSMB->t2.DataOffset = 0;
3458 pSMB->t2.SetupCount = 1;
3459 pSMB->t2.Reserved3 = 0;
3460 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3461 byte_count = params + 1 /* pad */ ;
3462 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3463 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3464 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3465 pSMB->Pad = 0;
3466 pSMB->Fid = netfid;
3467 inc_rfc1001_len(pSMB, byte_count);
3468 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3469
3470 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3471 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3472 if (rc) {
3473 cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3474 } else {
3475 /* decode response */
3476 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3477 /* BB also check enough total bytes returned */
3478 if (rc || get_bcc(&pSMBr->hdr) < 2)
3479 /* If rc should we check for EOPNOSUPP and
3480 disable the srvino flag? or in caller? */
3481 rc = -EIO; /* bad smb */
3482 else {
3483 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3484 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3485 struct file_chattr_info *pfinfo;
3486
3487 if (count != 16) {
3488 cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
3489 rc = -EIO;
3490 goto GetExtAttrOut;
3491 }
3492 pfinfo = (struct file_chattr_info *)
3493 (data_offset + (char *) &pSMBr->hdr.Protocol);
3494 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3495 *pMask = le64_to_cpu(pfinfo->mask);
3496 }
3497 }
3498 GetExtAttrOut:
3499 cifs_buf_release(pSMB);
3500 if (rc == -EAGAIN)
3501 goto GetExtAttrRetry;
3502 return rc;
3503 }
3504
3505 #endif /* CONFIG_POSIX */
3506
3507 /*
3508 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3509 * all NT TRANSACTS that we init here have total parm and data under about 400
3510 * bytes (to fit in small cifs buffer size), which is the case so far, it
3511 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3512 * returned setup area) and MaxParameterCount (returned parms size) must be set
3513 * by caller
3514 */
3515 static int
smb_init_nttransact(const __u16 sub_command,const int setup_count,const int parm_len,struct cifs_tcon * tcon,void ** ret_buf)3516 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3517 const int parm_len, struct cifs_tcon *tcon,
3518 void **ret_buf)
3519 {
3520 int rc;
3521 __u32 temp_offset;
3522 struct smb_com_ntransact_req *pSMB;
3523
3524 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3525 (void **)&pSMB);
3526 if (rc)
3527 return rc;
3528 *ret_buf = (void *)pSMB;
3529 pSMB->Reserved = 0;
3530 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3531 pSMB->TotalDataCount = 0;
3532 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3533 pSMB->ParameterCount = pSMB->TotalParameterCount;
3534 pSMB->DataCount = pSMB->TotalDataCount;
3535 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3536 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3537 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3538 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3539 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3540 pSMB->SubCommand = cpu_to_le16(sub_command);
3541 return 0;
3542 }
3543
3544 static int
validate_ntransact(char * buf,char ** ppparm,char ** ppdata,__u32 * pparmlen,__u32 * pdatalen)3545 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3546 __u32 *pparmlen, __u32 *pdatalen)
3547 {
3548 char *end_of_smb;
3549 __u32 data_count, data_offset, parm_count, parm_offset;
3550 struct smb_com_ntransact_rsp *pSMBr;
3551 u16 bcc;
3552
3553 *pdatalen = 0;
3554 *pparmlen = 0;
3555
3556 if (buf == NULL)
3557 return -EINVAL;
3558
3559 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3560
3561 bcc = get_bcc(&pSMBr->hdr);
3562 end_of_smb = 2 /* sizeof byte count */ + bcc +
3563 (char *)&pSMBr->ByteCount;
3564
3565 data_offset = le32_to_cpu(pSMBr->DataOffset);
3566 data_count = le32_to_cpu(pSMBr->DataCount);
3567 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3568 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3569
3570 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3571 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3572
3573 /* should we also check that parm and data areas do not overlap? */
3574 if (*ppparm > end_of_smb) {
3575 cifs_dbg(FYI, "parms start after end of smb\n");
3576 return -EINVAL;
3577 } else if (parm_count + *ppparm > end_of_smb) {
3578 cifs_dbg(FYI, "parm end after end of smb\n");
3579 return -EINVAL;
3580 } else if (*ppdata > end_of_smb) {
3581 cifs_dbg(FYI, "data starts after end of smb\n");
3582 return -EINVAL;
3583 } else if (data_count + *ppdata > end_of_smb) {
3584 cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3585 *ppdata, data_count, (data_count + *ppdata),
3586 end_of_smb, pSMBr);
3587 return -EINVAL;
3588 } else if (parm_count + data_count > bcc) {
3589 cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3590 return -EINVAL;
3591 }
3592 *pdatalen = data_count;
3593 *pparmlen = parm_count;
3594 return 0;
3595 }
3596
3597 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3598 int
CIFSSMBGetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct smb_ntsd ** acl_inf,__u32 * pbuflen,__u32 info)3599 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3600 struct smb_ntsd **acl_inf, __u32 *pbuflen, __u32 info)
3601 {
3602 int rc = 0;
3603 int buf_type = 0;
3604 QUERY_SEC_DESC_REQ *pSMB;
3605 struct kvec iov[1];
3606 struct kvec rsp_iov;
3607
3608 cifs_dbg(FYI, "GetCifsACL\n");
3609
3610 *pbuflen = 0;
3611 *acl_inf = NULL;
3612
3613 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3614 8 /* parm len */, tcon, (void **) &pSMB);
3615 if (rc)
3616 return rc;
3617
3618 pSMB->MaxParameterCount = cpu_to_le32(4);
3619 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3620 pSMB->MaxSetupCount = 0;
3621 pSMB->Fid = fid; /* file handle always le */
3622 pSMB->AclFlags = cpu_to_le32(info);
3623 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3624 inc_rfc1001_len(pSMB, 11);
3625 iov[0].iov_base = (char *)pSMB;
3626 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3627
3628 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3629 0, &rsp_iov);
3630 cifs_small_buf_release(pSMB);
3631 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3632 if (rc) {
3633 cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3634 } else { /* decode response */
3635 __le32 *parm;
3636 __u32 parm_len;
3637 __u32 acl_len;
3638 struct smb_com_ntransact_rsp *pSMBr;
3639 char *pdata;
3640
3641 /* validate_nttransact */
3642 rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3643 &pdata, &parm_len, pbuflen);
3644 if (rc)
3645 goto qsec_out;
3646 pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3647
3648 cifs_dbg(FYI, "smb %p parm %p data %p\n",
3649 pSMBr, parm, *acl_inf);
3650
3651 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3652 rc = -EIO; /* bad smb */
3653 *pbuflen = 0;
3654 goto qsec_out;
3655 }
3656
3657 /* BB check that data area is minimum length and as big as acl_len */
3658
3659 acl_len = le32_to_cpu(*parm);
3660 if (acl_len != *pbuflen) {
3661 cifs_dbg(VFS, "acl length %d does not match %d\n",
3662 acl_len, *pbuflen);
3663 if (*pbuflen > acl_len)
3664 *pbuflen = acl_len;
3665 }
3666
3667 /* check if buffer is big enough for the acl
3668 header followed by the smallest SID */
3669 if ((*pbuflen < sizeof(struct smb_ntsd) + 8) ||
3670 (*pbuflen >= 64 * 1024)) {
3671 cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3672 rc = -EINVAL;
3673 *pbuflen = 0;
3674 } else {
3675 *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3676 if (*acl_inf == NULL) {
3677 *pbuflen = 0;
3678 rc = -ENOMEM;
3679 }
3680 }
3681 }
3682 qsec_out:
3683 free_rsp_buf(buf_type, rsp_iov.iov_base);
3684 return rc;
3685 }
3686
3687 int
CIFSSMBSetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct smb_ntsd * pntsd,__u32 acllen,int aclflag)3688 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3689 struct smb_ntsd *pntsd, __u32 acllen, int aclflag)
3690 {
3691 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3692 int rc = 0;
3693 int bytes_returned = 0;
3694 SET_SEC_DESC_REQ *pSMB = NULL;
3695 void *pSMBr;
3696
3697 setCifsAclRetry:
3698 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3699 if (rc)
3700 return rc;
3701
3702 pSMB->MaxSetupCount = 0;
3703 pSMB->Reserved = 0;
3704
3705 param_count = 8;
3706 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3707 data_count = acllen;
3708 data_offset = param_offset + param_count;
3709 byte_count = 3 /* pad */ + param_count;
3710
3711 pSMB->DataCount = cpu_to_le32(data_count);
3712 pSMB->TotalDataCount = pSMB->DataCount;
3713 pSMB->MaxParameterCount = cpu_to_le32(4);
3714 pSMB->MaxDataCount = cpu_to_le32(16384);
3715 pSMB->ParameterCount = cpu_to_le32(param_count);
3716 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3717 pSMB->TotalParameterCount = pSMB->ParameterCount;
3718 pSMB->DataOffset = cpu_to_le32(data_offset);
3719 pSMB->SetupCount = 0;
3720 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3721 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3722
3723 pSMB->Fid = fid; /* file handle always le */
3724 pSMB->Reserved2 = 0;
3725 pSMB->AclFlags = cpu_to_le32(aclflag);
3726
3727 if (pntsd && acllen) {
3728 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3729 data_offset, pntsd, acllen);
3730 inc_rfc1001_len(pSMB, byte_count + data_count);
3731 } else
3732 inc_rfc1001_len(pSMB, byte_count);
3733
3734 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3735 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3736
3737 cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3738 bytes_returned, rc);
3739 if (rc)
3740 cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3741 cifs_buf_release(pSMB);
3742
3743 if (rc == -EAGAIN)
3744 goto setCifsAclRetry;
3745
3746 return (rc);
3747 }
3748
3749
3750 /* Legacy Query Path Information call for lookup to old servers such
3751 as Win9x/WinME */
3752 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)3753 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3754 const char *search_name, FILE_ALL_INFO *data,
3755 const struct nls_table *nls_codepage, int remap)
3756 {
3757 QUERY_INFORMATION_REQ *pSMB;
3758 QUERY_INFORMATION_RSP *pSMBr;
3759 int rc = 0;
3760 int bytes_returned;
3761 int name_len;
3762
3763 cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
3764 QInfRetry:
3765 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3766 (void **) &pSMBr);
3767 if (rc)
3768 return rc;
3769
3770 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3771 name_len =
3772 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3773 search_name, PATH_MAX, nls_codepage,
3774 remap);
3775 name_len++; /* trailing null */
3776 name_len *= 2;
3777 } else {
3778 name_len = copy_path_name(pSMB->FileName, search_name);
3779 }
3780 pSMB->BufferFormat = 0x04;
3781 name_len++; /* account for buffer type byte */
3782 inc_rfc1001_len(pSMB, (__u16)name_len);
3783 pSMB->ByteCount = cpu_to_le16(name_len);
3784
3785 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3786 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3787 if (rc) {
3788 cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
3789 } else if (data) {
3790 struct timespec64 ts;
3791 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3792
3793 /* decode response */
3794 /* BB FIXME - add time zone adjustment BB */
3795 memset(data, 0, sizeof(FILE_ALL_INFO));
3796 ts.tv_nsec = 0;
3797 ts.tv_sec = time;
3798 /* decode time fields */
3799 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3800 data->LastWriteTime = data->ChangeTime;
3801 data->LastAccessTime = 0;
3802 data->AllocationSize =
3803 cpu_to_le64(le32_to_cpu(pSMBr->size));
3804 data->EndOfFile = data->AllocationSize;
3805 data->Attributes =
3806 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3807 } else
3808 rc = -EIO; /* bad buffer passed in */
3809
3810 cifs_buf_release(pSMB);
3811
3812 if (rc == -EAGAIN)
3813 goto QInfRetry;
3814
3815 return rc;
3816 }
3817
3818 int
CIFSSMBQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_ALL_INFO * pFindData)3819 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3820 u16 netfid, FILE_ALL_INFO *pFindData)
3821 {
3822 struct smb_t2_qfi_req *pSMB = NULL;
3823 struct smb_t2_qfi_rsp *pSMBr = NULL;
3824 int rc = 0;
3825 int bytes_returned;
3826 __u16 params, byte_count;
3827
3828 QFileInfoRetry:
3829 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3830 (void **) &pSMBr);
3831 if (rc)
3832 return rc;
3833
3834 params = 2 /* level */ + 2 /* fid */;
3835 pSMB->t2.TotalDataCount = 0;
3836 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3837 /* BB find exact max data count below from sess structure BB */
3838 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3839 pSMB->t2.MaxSetupCount = 0;
3840 pSMB->t2.Reserved = 0;
3841 pSMB->t2.Flags = 0;
3842 pSMB->t2.Timeout = 0;
3843 pSMB->t2.Reserved2 = 0;
3844 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3845 Fid) - 4);
3846 pSMB->t2.DataCount = 0;
3847 pSMB->t2.DataOffset = 0;
3848 pSMB->t2.SetupCount = 1;
3849 pSMB->t2.Reserved3 = 0;
3850 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3851 byte_count = params + 1 /* pad */ ;
3852 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3853 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3854 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3855 pSMB->Pad = 0;
3856 pSMB->Fid = netfid;
3857 inc_rfc1001_len(pSMB, byte_count);
3858 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3859
3860 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3861 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3862 if (rc) {
3863 cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
3864 } else { /* decode response */
3865 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3866
3867 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3868 rc = -EIO;
3869 else if (get_bcc(&pSMBr->hdr) < 40)
3870 rc = -EIO; /* bad smb */
3871 else if (pFindData) {
3872 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3873 memcpy((char *) pFindData,
3874 (char *) &pSMBr->hdr.Protocol +
3875 data_offset, sizeof(FILE_ALL_INFO));
3876 } else
3877 rc = -ENOMEM;
3878 }
3879 cifs_buf_release(pSMB);
3880 if (rc == -EAGAIN)
3881 goto QFileInfoRetry;
3882
3883 return rc;
3884 }
3885
3886 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)3887 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3888 const char *search_name, FILE_ALL_INFO *data,
3889 int legacy /* old style infolevel */,
3890 const struct nls_table *nls_codepage, int remap)
3891 {
3892 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3893 TRANSACTION2_QPI_REQ *pSMB = NULL;
3894 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3895 int rc = 0;
3896 int bytes_returned;
3897 int name_len;
3898 __u16 params, byte_count;
3899
3900 /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
3901 QPathInfoRetry:
3902 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3903 (void **) &pSMBr);
3904 if (rc)
3905 return rc;
3906
3907 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3908 name_len =
3909 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
3910 PATH_MAX, nls_codepage, remap);
3911 name_len++; /* trailing null */
3912 name_len *= 2;
3913 } else {
3914 name_len = copy_path_name(pSMB->FileName, search_name);
3915 }
3916
3917 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3918 pSMB->TotalDataCount = 0;
3919 pSMB->MaxParameterCount = cpu_to_le16(2);
3920 /* BB find exact max SMB PDU from sess structure BB */
3921 pSMB->MaxDataCount = cpu_to_le16(4000);
3922 pSMB->MaxSetupCount = 0;
3923 pSMB->Reserved = 0;
3924 pSMB->Flags = 0;
3925 pSMB->Timeout = 0;
3926 pSMB->Reserved2 = 0;
3927 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3928 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3929 pSMB->DataCount = 0;
3930 pSMB->DataOffset = 0;
3931 pSMB->SetupCount = 1;
3932 pSMB->Reserved3 = 0;
3933 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3934 byte_count = params + 1 /* pad */ ;
3935 pSMB->TotalParameterCount = cpu_to_le16(params);
3936 pSMB->ParameterCount = pSMB->TotalParameterCount;
3937 if (legacy)
3938 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3939 else
3940 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3941 pSMB->Reserved4 = 0;
3942 inc_rfc1001_len(pSMB, byte_count);
3943 pSMB->ByteCount = cpu_to_le16(byte_count);
3944
3945 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3946 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3947 if (rc) {
3948 cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
3949 } else { /* decode response */
3950 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3951
3952 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3953 rc = -EIO;
3954 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
3955 rc = -EIO; /* bad smb */
3956 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
3957 rc = -EIO; /* 24 or 26 expected but we do not read
3958 last field */
3959 else if (data) {
3960 int size;
3961 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3962
3963 /*
3964 * On legacy responses we do not read the last field,
3965 * EAsize, fortunately since it varies by subdialect and
3966 * also note it differs on Set vs Get, ie two bytes or 4
3967 * bytes depending but we don't care here.
3968 */
3969 if (legacy)
3970 size = sizeof(FILE_INFO_STANDARD);
3971 else
3972 size = sizeof(FILE_ALL_INFO);
3973 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
3974 data_offset, size);
3975 } else
3976 rc = -ENOMEM;
3977 }
3978 cifs_buf_release(pSMB);
3979 if (rc == -EAGAIN)
3980 goto QPathInfoRetry;
3981
3982 return rc;
3983 }
3984
3985 int
CIFSSMBUnixQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_UNIX_BASIC_INFO * pFindData)3986 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3987 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3988 {
3989 struct smb_t2_qfi_req *pSMB = NULL;
3990 struct smb_t2_qfi_rsp *pSMBr = NULL;
3991 int rc = 0;
3992 int bytes_returned;
3993 __u16 params, byte_count;
3994
3995 UnixQFileInfoRetry:
3996 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3997 (void **) &pSMBr);
3998 if (rc)
3999 return rc;
4000
4001 params = 2 /* level */ + 2 /* fid */;
4002 pSMB->t2.TotalDataCount = 0;
4003 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4004 /* BB find exact max data count below from sess structure BB */
4005 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4006 pSMB->t2.MaxSetupCount = 0;
4007 pSMB->t2.Reserved = 0;
4008 pSMB->t2.Flags = 0;
4009 pSMB->t2.Timeout = 0;
4010 pSMB->t2.Reserved2 = 0;
4011 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4012 Fid) - 4);
4013 pSMB->t2.DataCount = 0;
4014 pSMB->t2.DataOffset = 0;
4015 pSMB->t2.SetupCount = 1;
4016 pSMB->t2.Reserved3 = 0;
4017 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4018 byte_count = params + 1 /* pad */ ;
4019 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4020 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4021 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4022 pSMB->Pad = 0;
4023 pSMB->Fid = netfid;
4024 inc_rfc1001_len(pSMB, byte_count);
4025 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4026
4027 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4028 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4029 if (rc) {
4030 cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
4031 } else { /* decode response */
4032 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4033
4034 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4035 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4036 rc = -EIO; /* bad smb */
4037 } else {
4038 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4039 memcpy((char *) pFindData,
4040 (char *) &pSMBr->hdr.Protocol +
4041 data_offset,
4042 sizeof(FILE_UNIX_BASIC_INFO));
4043 }
4044 }
4045
4046 cifs_buf_release(pSMB);
4047 if (rc == -EAGAIN)
4048 goto UnixQFileInfoRetry;
4049
4050 return rc;
4051 }
4052
4053 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)4054 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4055 const unsigned char *searchName,
4056 FILE_UNIX_BASIC_INFO *pFindData,
4057 const struct nls_table *nls_codepage, int remap)
4058 {
4059 /* SMB_QUERY_FILE_UNIX_BASIC */
4060 TRANSACTION2_QPI_REQ *pSMB = NULL;
4061 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4062 int rc = 0;
4063 int bytes_returned = 0;
4064 int name_len;
4065 __u16 params, byte_count;
4066
4067 cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4068 UnixQPathInfoRetry:
4069 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4070 (void **) &pSMBr);
4071 if (rc)
4072 return rc;
4073
4074 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4075 name_len =
4076 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4077 PATH_MAX, nls_codepage, remap);
4078 name_len++; /* trailing null */
4079 name_len *= 2;
4080 } else {
4081 name_len = copy_path_name(pSMB->FileName, searchName);
4082 }
4083
4084 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4085 pSMB->TotalDataCount = 0;
4086 pSMB->MaxParameterCount = cpu_to_le16(2);
4087 /* BB find exact max SMB PDU from sess structure BB */
4088 pSMB->MaxDataCount = cpu_to_le16(4000);
4089 pSMB->MaxSetupCount = 0;
4090 pSMB->Reserved = 0;
4091 pSMB->Flags = 0;
4092 pSMB->Timeout = 0;
4093 pSMB->Reserved2 = 0;
4094 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4095 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4096 pSMB->DataCount = 0;
4097 pSMB->DataOffset = 0;
4098 pSMB->SetupCount = 1;
4099 pSMB->Reserved3 = 0;
4100 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4101 byte_count = params + 1 /* pad */ ;
4102 pSMB->TotalParameterCount = cpu_to_le16(params);
4103 pSMB->ParameterCount = pSMB->TotalParameterCount;
4104 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4105 pSMB->Reserved4 = 0;
4106 inc_rfc1001_len(pSMB, byte_count);
4107 pSMB->ByteCount = cpu_to_le16(byte_count);
4108
4109 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4110 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4111 if (rc) {
4112 cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
4113 } else { /* decode response */
4114 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4115
4116 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4117 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4118 rc = -EIO; /* bad smb */
4119 } else {
4120 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4121 memcpy((char *) pFindData,
4122 (char *) &pSMBr->hdr.Protocol +
4123 data_offset,
4124 sizeof(FILE_UNIX_BASIC_INFO));
4125 }
4126 }
4127 cifs_buf_release(pSMB);
4128 if (rc == -EAGAIN)
4129 goto UnixQPathInfoRetry;
4130
4131 return rc;
4132 }
4133
4134 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4135 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)4136 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4137 const char *searchName, struct cifs_sb_info *cifs_sb,
4138 __u16 *pnetfid, __u16 search_flags,
4139 struct cifs_search_info *psrch_inf, bool msearch)
4140 {
4141 /* level 257 SMB_ */
4142 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4143 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4144 T2_FFIRST_RSP_PARMS *parms;
4145 struct nls_table *nls_codepage;
4146 unsigned int lnoff;
4147 __u16 params, byte_count;
4148 int bytes_returned = 0;
4149 int name_len, remap;
4150 int rc = 0;
4151
4152 cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4153
4154 findFirstRetry:
4155 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4156 (void **) &pSMBr);
4157 if (rc)
4158 return rc;
4159
4160 nls_codepage = cifs_sb->local_nls;
4161 remap = cifs_remap(cifs_sb);
4162
4163 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4164 name_len =
4165 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4166 PATH_MAX, nls_codepage, remap);
4167 /* We can not add the asterisk earlier in case
4168 it got remapped to 0xF03A as if it were part of the
4169 directory name instead of a wildcard */
4170 name_len *= 2;
4171 if (msearch) {
4172 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4173 pSMB->FileName[name_len+1] = 0;
4174 pSMB->FileName[name_len+2] = '*';
4175 pSMB->FileName[name_len+3] = 0;
4176 name_len += 4; /* now the trailing null */
4177 /* null terminate just in case */
4178 pSMB->FileName[name_len] = 0;
4179 pSMB->FileName[name_len+1] = 0;
4180 name_len += 2;
4181 } else if (!searchName[0]) {
4182 pSMB->FileName[0] = CIFS_DIR_SEP(cifs_sb);
4183 pSMB->FileName[1] = 0;
4184 pSMB->FileName[2] = 0;
4185 pSMB->FileName[3] = 0;
4186 name_len = 4;
4187 }
4188 } else {
4189 name_len = copy_path_name(pSMB->FileName, searchName);
4190 if (msearch) {
4191 if (WARN_ON_ONCE(name_len > PATH_MAX-2))
4192 name_len = PATH_MAX-2;
4193 /* overwrite nul byte */
4194 pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
4195 pSMB->FileName[name_len] = '*';
4196 pSMB->FileName[name_len+1] = 0;
4197 name_len += 2;
4198 } else if (!searchName[0]) {
4199 pSMB->FileName[0] = CIFS_DIR_SEP(cifs_sb);
4200 pSMB->FileName[1] = 0;
4201 name_len = 2;
4202 }
4203 }
4204
4205 params = 12 + name_len /* includes null */ ;
4206 pSMB->TotalDataCount = 0; /* no EAs */
4207 pSMB->MaxParameterCount = cpu_to_le16(10);
4208 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4209 pSMB->MaxSetupCount = 0;
4210 pSMB->Reserved = 0;
4211 pSMB->Flags = 0;
4212 pSMB->Timeout = 0;
4213 pSMB->Reserved2 = 0;
4214 byte_count = params + 1 /* pad */ ;
4215 pSMB->TotalParameterCount = cpu_to_le16(params);
4216 pSMB->ParameterCount = pSMB->TotalParameterCount;
4217 pSMB->ParameterOffset = cpu_to_le16(
4218 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4219 - 4);
4220 pSMB->DataCount = 0;
4221 pSMB->DataOffset = 0;
4222 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4223 pSMB->Reserved3 = 0;
4224 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4225 pSMB->SearchAttributes =
4226 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4227 ATTR_DIRECTORY);
4228 pSMB->SearchCount = cpu_to_le16(msearch ? CIFSMaxBufSize/sizeof(FILE_UNIX_INFO) : 1);
4229 pSMB->SearchFlags = cpu_to_le16(search_flags);
4230 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4231
4232 /* BB what should we set StorageType to? Does it matter? BB */
4233 pSMB->SearchStorageType = 0;
4234 inc_rfc1001_len(pSMB, byte_count);
4235 pSMB->ByteCount = cpu_to_le16(byte_count);
4236
4237 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4238 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4239 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4240
4241 if (rc) {
4242 /*
4243 * BB: add logic to retry regular search if Unix search rejected
4244 * unexpectedly by server.
4245 */
4246 /* BB: add code to handle unsupported level rc */
4247 cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4248 cifs_buf_release(pSMB);
4249 /*
4250 * BB: eventually could optimize out free and realloc of buf for
4251 * this case.
4252 */
4253 if (rc == -EAGAIN)
4254 goto findFirstRetry;
4255 return rc;
4256 }
4257 /* decode response */
4258 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4259 if (rc) {
4260 cifs_buf_release(pSMB);
4261 return rc;
4262 }
4263
4264 psrch_inf->unicode = !!(pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);
4265 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4266 psrch_inf->smallBuf = false;
4267 psrch_inf->srch_entries_start = (char *)&pSMBr->hdr.Protocol +
4268 le16_to_cpu(pSMBr->t2.DataOffset);
4269
4270 parms = (T2_FFIRST_RSP_PARMS *)((char *)&pSMBr->hdr.Protocol +
4271 le16_to_cpu(pSMBr->t2.ParameterOffset));
4272 psrch_inf->endOfSearch = !!parms->EndofSearch;
4273
4274 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
4275 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4276 psrch_inf->entries_in_buffer;
4277 lnoff = le16_to_cpu(parms->LastNameOffset);
4278 if (CIFSMaxBufSize < lnoff) {
4279 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4280 psrch_inf->last_entry = NULL;
4281 } else {
4282 psrch_inf->last_entry = psrch_inf->srch_entries_start + lnoff;
4283 if (pnetfid)
4284 *pnetfid = parms->SearchHandle;
4285 }
4286 return 0;
4287 }
4288
CIFSFindNext(const unsigned int xid,struct cifs_tcon * tcon,__u16 searchHandle,__u16 search_flags,struct cifs_search_info * psrch_inf)4289 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4290 __u16 searchHandle, __u16 search_flags,
4291 struct cifs_search_info *psrch_inf)
4292 {
4293 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4294 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4295 T2_FNEXT_RSP_PARMS *parms;
4296 unsigned int name_len;
4297 unsigned int lnoff;
4298 __u16 params, byte_count;
4299 char *response_data;
4300 int bytes_returned;
4301 int rc = 0;
4302
4303 cifs_dbg(FYI, "In FindNext\n");
4304
4305 if (psrch_inf->endOfSearch)
4306 return -ENOENT;
4307
4308 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4309 (void **) &pSMBr);
4310 if (rc)
4311 return rc;
4312
4313 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4314 byte_count = 0;
4315 pSMB->TotalDataCount = 0; /* no EAs */
4316 pSMB->MaxParameterCount = cpu_to_le16(8);
4317 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4318 pSMB->MaxSetupCount = 0;
4319 pSMB->Reserved = 0;
4320 pSMB->Flags = 0;
4321 pSMB->Timeout = 0;
4322 pSMB->Reserved2 = 0;
4323 pSMB->ParameterOffset = cpu_to_le16(
4324 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4325 pSMB->DataCount = 0;
4326 pSMB->DataOffset = 0;
4327 pSMB->SetupCount = 1;
4328 pSMB->Reserved3 = 0;
4329 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4330 pSMB->SearchHandle = searchHandle; /* always kept as le */
4331 pSMB->SearchCount =
4332 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4333 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4334 pSMB->ResumeKey = psrch_inf->resume_key;
4335 pSMB->SearchFlags = cpu_to_le16(search_flags);
4336
4337 name_len = psrch_inf->resume_name_len;
4338 params += name_len;
4339 if (name_len < PATH_MAX) {
4340 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4341 byte_count += name_len;
4342 /* 14 byte parm len above enough for 2 byte null terminator */
4343 pSMB->ResumeFileName[name_len] = 0;
4344 pSMB->ResumeFileName[name_len+1] = 0;
4345 } else {
4346 cifs_buf_release(pSMB);
4347 return -EINVAL;
4348 }
4349 byte_count = params + 1 /* pad */ ;
4350 pSMB->TotalParameterCount = cpu_to_le16(params);
4351 pSMB->ParameterCount = pSMB->TotalParameterCount;
4352 inc_rfc1001_len(pSMB, byte_count);
4353 pSMB->ByteCount = cpu_to_le16(byte_count);
4354
4355 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4356 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4357 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4358
4359 if (rc) {
4360 cifs_buf_release(pSMB);
4361 if (rc == -EBADF) {
4362 psrch_inf->endOfSearch = true;
4363 rc = 0; /* search probably was closed at end of search*/
4364 } else {
4365 cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4366 }
4367 return rc;
4368 }
4369
4370 /* decode response */
4371 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4372 if (rc) {
4373 cifs_buf_release(pSMB);
4374 return rc;
4375 }
4376 /* BB fixme add lock for file (srch_info) struct here */
4377 psrch_inf->unicode = !!(pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);
4378 response_data = (char *)&pSMBr->hdr.Protocol +
4379 le16_to_cpu(pSMBr->t2.ParameterOffset);
4380 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4381 response_data = (char *)&pSMBr->hdr.Protocol +
4382 le16_to_cpu(pSMBr->t2.DataOffset);
4383
4384 if (psrch_inf->smallBuf)
4385 cifs_small_buf_release(psrch_inf->ntwrk_buf_start);
4386 else
4387 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4388
4389 psrch_inf->srch_entries_start = response_data;
4390 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4391 psrch_inf->smallBuf = false;
4392 psrch_inf->endOfSearch = !!parms->EndofSearch;
4393 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
4394 psrch_inf->index_of_last_entry += psrch_inf->entries_in_buffer;
4395 lnoff = le16_to_cpu(parms->LastNameOffset);
4396 if (CIFSMaxBufSize < lnoff) {
4397 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4398 psrch_inf->last_entry = NULL;
4399 } else {
4400 psrch_inf->last_entry =
4401 psrch_inf->srch_entries_start + lnoff;
4402 }
4403 /* BB fixme add unlock here */
4404
4405 /*
4406 * BB: On error, should we leave previous search buf
4407 * (and count and last entry fields) intact or free the previous one?
4408 *
4409 * Note: On -EAGAIN error only caller can retry on handle based calls
4410 * since file handle passed in no longer valid.
4411 */
4412 return 0;
4413 }
4414
4415 int
CIFSFindClose(const unsigned int xid,struct cifs_tcon * tcon,const __u16 searchHandle)4416 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4417 const __u16 searchHandle)
4418 {
4419 int rc = 0;
4420 FINDCLOSE_REQ *pSMB = NULL;
4421
4422 cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4423 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4424
4425 /* no sense returning error if session restarted
4426 as file handle has been closed */
4427 if (rc == -EAGAIN)
4428 return 0;
4429 if (rc)
4430 return rc;
4431
4432 pSMB->FileID = searchHandle;
4433 pSMB->ByteCount = 0;
4434 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4435 cifs_small_buf_release(pSMB);
4436 if (rc)
4437 cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4438
4439 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4440
4441 /* Since session is dead, search handle closed on server already */
4442 if (rc == -EAGAIN)
4443 rc = 0;
4444
4445 return rc;
4446 }
4447
4448 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)4449 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4450 const char *search_name, __u64 *inode_number,
4451 const struct nls_table *nls_codepage, int remap)
4452 {
4453 int rc = 0;
4454 TRANSACTION2_QPI_REQ *pSMB = NULL;
4455 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4456 int name_len, bytes_returned;
4457 __u16 params, byte_count;
4458
4459 cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4460 if (tcon == NULL)
4461 return -ENODEV;
4462
4463 GetInodeNumberRetry:
4464 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4465 (void **) &pSMBr);
4466 if (rc)
4467 return rc;
4468
4469 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4470 name_len =
4471 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4472 search_name, PATH_MAX, nls_codepage,
4473 remap);
4474 name_len++; /* trailing null */
4475 name_len *= 2;
4476 } else {
4477 name_len = copy_path_name(pSMB->FileName, search_name);
4478 }
4479
4480 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4481 pSMB->TotalDataCount = 0;
4482 pSMB->MaxParameterCount = cpu_to_le16(2);
4483 /* BB find exact max data count below from sess structure BB */
4484 pSMB->MaxDataCount = cpu_to_le16(4000);
4485 pSMB->MaxSetupCount = 0;
4486 pSMB->Reserved = 0;
4487 pSMB->Flags = 0;
4488 pSMB->Timeout = 0;
4489 pSMB->Reserved2 = 0;
4490 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4491 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4492 pSMB->DataCount = 0;
4493 pSMB->DataOffset = 0;
4494 pSMB->SetupCount = 1;
4495 pSMB->Reserved3 = 0;
4496 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4497 byte_count = params + 1 /* pad */ ;
4498 pSMB->TotalParameterCount = cpu_to_le16(params);
4499 pSMB->ParameterCount = pSMB->TotalParameterCount;
4500 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4501 pSMB->Reserved4 = 0;
4502 inc_rfc1001_len(pSMB, byte_count);
4503 pSMB->ByteCount = cpu_to_le16(byte_count);
4504
4505 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4506 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4507 if (rc) {
4508 cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4509 } else {
4510 /* decode response */
4511 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4512 /* BB also check enough total bytes returned */
4513 if (rc || get_bcc(&pSMBr->hdr) < 2)
4514 /* If rc should we check for EOPNOSUPP and
4515 disable the srvino flag? or in caller? */
4516 rc = -EIO; /* bad smb */
4517 else {
4518 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4519 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4520 struct file_internal_info *pfinfo;
4521 /* BB Do we need a cast or hash here ? */
4522 if (count < 8) {
4523 cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
4524 rc = -EIO;
4525 goto GetInodeNumOut;
4526 }
4527 pfinfo = (struct file_internal_info *)
4528 (data_offset + (char *) &pSMBr->hdr.Protocol);
4529 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4530 }
4531 }
4532 GetInodeNumOut:
4533 cifs_buf_release(pSMB);
4534 if (rc == -EAGAIN)
4535 goto GetInodeNumberRetry;
4536 return rc;
4537 }
4538
4539 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)4540 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4541 const char *search_name, struct dfs_info3_param **target_nodes,
4542 unsigned int *num_of_nodes,
4543 const struct nls_table *nls_codepage, int remap)
4544 {
4545 /* TRANS2_GET_DFS_REFERRAL */
4546 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4547 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4548 int rc = 0;
4549 int bytes_returned;
4550 int name_len;
4551 __u16 params, byte_count;
4552 *num_of_nodes = 0;
4553 *target_nodes = NULL;
4554
4555 cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4556 if (ses == NULL || ses->tcon_ipc == NULL)
4557 return -ENODEV;
4558
4559 getDFSRetry:
4560 /*
4561 * Use smb_init_no_reconnect() instead of smb_init() as
4562 * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
4563 * causing an infinite recursion.
4564 */
4565 rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
4566 (void **)&pSMB, (void **)&pSMBr);
4567 if (rc)
4568 return rc;
4569
4570 /* server pointer checked in called function,
4571 but should never be null here anyway */
4572 pSMB->hdr.Mid = get_next_mid(ses->server);
4573 pSMB->hdr.Tid = ses->tcon_ipc->tid;
4574 pSMB->hdr.Uid = ses->Suid;
4575 if (ses->capabilities & CAP_STATUS32)
4576 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4577 if (ses->capabilities & CAP_DFS)
4578 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4579
4580 if (ses->capabilities & CAP_UNICODE) {
4581 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4582 name_len =
4583 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4584 search_name, PATH_MAX, nls_codepage,
4585 remap);
4586 name_len++; /* trailing null */
4587 name_len *= 2;
4588 } else { /* BB improve the check for buffer overruns BB */
4589 name_len = copy_path_name(pSMB->RequestFileName, search_name);
4590 }
4591
4592 if (ses->server->sign)
4593 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4594
4595 pSMB->hdr.Uid = ses->Suid;
4596
4597 params = 2 /* level */ + name_len /*includes null */ ;
4598 pSMB->TotalDataCount = 0;
4599 pSMB->DataCount = 0;
4600 pSMB->DataOffset = 0;
4601 pSMB->MaxParameterCount = 0;
4602 /* BB find exact max SMB PDU from sess structure BB */
4603 pSMB->MaxDataCount = cpu_to_le16(4000);
4604 pSMB->MaxSetupCount = 0;
4605 pSMB->Reserved = 0;
4606 pSMB->Flags = 0;
4607 pSMB->Timeout = 0;
4608 pSMB->Reserved2 = 0;
4609 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4610 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4611 pSMB->SetupCount = 1;
4612 pSMB->Reserved3 = 0;
4613 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4614 byte_count = params + 3 /* pad */ ;
4615 pSMB->ParameterCount = cpu_to_le16(params);
4616 pSMB->TotalParameterCount = pSMB->ParameterCount;
4617 pSMB->MaxReferralLevel = cpu_to_le16(3);
4618 inc_rfc1001_len(pSMB, byte_count);
4619 pSMB->ByteCount = cpu_to_le16(byte_count);
4620
4621 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4622 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4623 if (rc) {
4624 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4625 goto GetDFSRefExit;
4626 }
4627 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4628
4629 /* BB Also check if enough total bytes returned? */
4630 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4631 rc = -EIO; /* bad smb */
4632 goto GetDFSRefExit;
4633 }
4634
4635 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4636 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4637
4638 /* parse returned result into more usable form */
4639 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4640 le16_to_cpu(pSMBr->t2.DataCount),
4641 num_of_nodes, target_nodes, nls_codepage,
4642 remap, search_name,
4643 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4644
4645 GetDFSRefExit:
4646 cifs_buf_release(pSMB);
4647
4648 if (rc == -EAGAIN)
4649 goto getDFSRetry;
4650
4651 return rc;
4652 }
4653
4654 /* Query File System Info such as free space to old servers such as Win 9x */
4655 int
SMBOldQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4656 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4657 struct kstatfs *FSData)
4658 {
4659 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4660 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4661 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4662 FILE_SYSTEM_ALLOC_INFO *response_data;
4663 int rc = 0;
4664 int bytes_returned = 0;
4665 __u16 params, byte_count;
4666
4667 cifs_dbg(FYI, "OldQFSInfo\n");
4668 oldQFSInfoRetry:
4669 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4670 (void **) &pSMBr);
4671 if (rc)
4672 return rc;
4673
4674 params = 2; /* level */
4675 pSMB->TotalDataCount = 0;
4676 pSMB->MaxParameterCount = cpu_to_le16(2);
4677 pSMB->MaxDataCount = cpu_to_le16(1000);
4678 pSMB->MaxSetupCount = 0;
4679 pSMB->Reserved = 0;
4680 pSMB->Flags = 0;
4681 pSMB->Timeout = 0;
4682 pSMB->Reserved2 = 0;
4683 byte_count = params + 1 /* pad */ ;
4684 pSMB->TotalParameterCount = cpu_to_le16(params);
4685 pSMB->ParameterCount = pSMB->TotalParameterCount;
4686 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4687 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4688 pSMB->DataCount = 0;
4689 pSMB->DataOffset = 0;
4690 pSMB->SetupCount = 1;
4691 pSMB->Reserved3 = 0;
4692 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4693 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4694 inc_rfc1001_len(pSMB, byte_count);
4695 pSMB->ByteCount = cpu_to_le16(byte_count);
4696
4697 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4698 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4699 if (rc) {
4700 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4701 } else { /* decode response */
4702 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4703
4704 if (rc || get_bcc(&pSMBr->hdr) < 18)
4705 rc = -EIO; /* bad smb */
4706 else {
4707 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4708 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
4709 get_bcc(&pSMBr->hdr), data_offset);
4710
4711 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4712 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4713 FSData->f_bsize =
4714 le16_to_cpu(response_data->BytesPerSector) *
4715 le32_to_cpu(response_data->
4716 SectorsPerAllocationUnit);
4717 /*
4718 * much prefer larger but if server doesn't report
4719 * a valid size than 4K is a reasonable minimum
4720 */
4721 if (FSData->f_bsize < 512)
4722 FSData->f_bsize = 4096;
4723
4724 FSData->f_blocks =
4725 le32_to_cpu(response_data->TotalAllocationUnits);
4726 FSData->f_bfree = FSData->f_bavail =
4727 le32_to_cpu(response_data->FreeAllocationUnits);
4728 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
4729 (unsigned long long)FSData->f_blocks,
4730 (unsigned long long)FSData->f_bfree,
4731 FSData->f_bsize);
4732 }
4733 }
4734 cifs_buf_release(pSMB);
4735
4736 if (rc == -EAGAIN)
4737 goto oldQFSInfoRetry;
4738
4739 return rc;
4740 }
4741
4742 int
CIFSSMBQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4743 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4744 struct kstatfs *FSData)
4745 {
4746 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4747 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4748 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4749 FILE_SYSTEM_INFO *response_data;
4750 int rc = 0;
4751 int bytes_returned = 0;
4752 __u16 params, byte_count;
4753
4754 cifs_dbg(FYI, "In QFSInfo\n");
4755 QFSInfoRetry:
4756 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4757 (void **) &pSMBr);
4758 if (rc)
4759 return rc;
4760
4761 params = 2; /* level */
4762 pSMB->TotalDataCount = 0;
4763 pSMB->MaxParameterCount = cpu_to_le16(2);
4764 pSMB->MaxDataCount = cpu_to_le16(1000);
4765 pSMB->MaxSetupCount = 0;
4766 pSMB->Reserved = 0;
4767 pSMB->Flags = 0;
4768 pSMB->Timeout = 0;
4769 pSMB->Reserved2 = 0;
4770 byte_count = params + 1 /* pad */ ;
4771 pSMB->TotalParameterCount = cpu_to_le16(params);
4772 pSMB->ParameterCount = pSMB->TotalParameterCount;
4773 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4774 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4775 pSMB->DataCount = 0;
4776 pSMB->DataOffset = 0;
4777 pSMB->SetupCount = 1;
4778 pSMB->Reserved3 = 0;
4779 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4780 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4781 inc_rfc1001_len(pSMB, byte_count);
4782 pSMB->ByteCount = cpu_to_le16(byte_count);
4783
4784 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4785 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4786 if (rc) {
4787 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4788 } else { /* decode response */
4789 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4790
4791 if (rc || get_bcc(&pSMBr->hdr) < 24)
4792 rc = -EIO; /* bad smb */
4793 else {
4794 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4795
4796 response_data =
4797 (FILE_SYSTEM_INFO
4798 *) (((char *) &pSMBr->hdr.Protocol) +
4799 data_offset);
4800 FSData->f_bsize =
4801 le32_to_cpu(response_data->BytesPerSector) *
4802 le32_to_cpu(response_data->
4803 SectorsPerAllocationUnit);
4804 /*
4805 * much prefer larger but if server doesn't report
4806 * a valid size than 4K is a reasonable minimum
4807 */
4808 if (FSData->f_bsize < 512)
4809 FSData->f_bsize = 4096;
4810
4811 FSData->f_blocks =
4812 le64_to_cpu(response_data->TotalAllocationUnits);
4813 FSData->f_bfree = FSData->f_bavail =
4814 le64_to_cpu(response_data->FreeAllocationUnits);
4815 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
4816 (unsigned long long)FSData->f_blocks,
4817 (unsigned long long)FSData->f_bfree,
4818 FSData->f_bsize);
4819 }
4820 }
4821 cifs_buf_release(pSMB);
4822
4823 if (rc == -EAGAIN)
4824 goto QFSInfoRetry;
4825
4826 return rc;
4827 }
4828
4829 int
CIFSSMBQFSAttributeInfo(const unsigned int xid,struct cifs_tcon * tcon)4830 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
4831 {
4832 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4833 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4834 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4835 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4836 int rc = 0;
4837 int bytes_returned = 0;
4838 __u16 params, byte_count;
4839
4840 cifs_dbg(FYI, "In QFSAttributeInfo\n");
4841 QFSAttributeRetry:
4842 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4843 (void **) &pSMBr);
4844 if (rc)
4845 return rc;
4846
4847 params = 2; /* level */
4848 pSMB->TotalDataCount = 0;
4849 pSMB->MaxParameterCount = cpu_to_le16(2);
4850 /* BB find exact max SMB PDU from sess structure BB */
4851 pSMB->MaxDataCount = cpu_to_le16(1000);
4852 pSMB->MaxSetupCount = 0;
4853 pSMB->Reserved = 0;
4854 pSMB->Flags = 0;
4855 pSMB->Timeout = 0;
4856 pSMB->Reserved2 = 0;
4857 byte_count = params + 1 /* pad */ ;
4858 pSMB->TotalParameterCount = cpu_to_le16(params);
4859 pSMB->ParameterCount = pSMB->TotalParameterCount;
4860 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4861 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4862 pSMB->DataCount = 0;
4863 pSMB->DataOffset = 0;
4864 pSMB->SetupCount = 1;
4865 pSMB->Reserved3 = 0;
4866 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4867 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4868 inc_rfc1001_len(pSMB, byte_count);
4869 pSMB->ByteCount = cpu_to_le16(byte_count);
4870
4871 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4872 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4873 if (rc) {
4874 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
4875 } else { /* decode response */
4876 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4877
4878 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4879 /* BB also check if enough bytes returned */
4880 rc = -EIO; /* bad smb */
4881 } else {
4882 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4883 response_data =
4884 (FILE_SYSTEM_ATTRIBUTE_INFO
4885 *) (((char *) &pSMBr->hdr.Protocol) +
4886 data_offset);
4887 memcpy(&tcon->fsAttrInfo, response_data,
4888 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4889 }
4890 }
4891 cifs_buf_release(pSMB);
4892
4893 if (rc == -EAGAIN)
4894 goto QFSAttributeRetry;
4895
4896 return rc;
4897 }
4898
4899 int
CIFSSMBQFSDeviceInfo(const unsigned int xid,struct cifs_tcon * tcon)4900 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
4901 {
4902 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4903 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4904 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4905 FILE_SYSTEM_DEVICE_INFO *response_data;
4906 int rc = 0;
4907 int bytes_returned = 0;
4908 __u16 params, byte_count;
4909
4910 cifs_dbg(FYI, "In QFSDeviceInfo\n");
4911 QFSDeviceRetry:
4912 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4913 (void **) &pSMBr);
4914 if (rc)
4915 return rc;
4916
4917 params = 2; /* level */
4918 pSMB->TotalDataCount = 0;
4919 pSMB->MaxParameterCount = cpu_to_le16(2);
4920 /* BB find exact max SMB PDU from sess structure BB */
4921 pSMB->MaxDataCount = cpu_to_le16(1000);
4922 pSMB->MaxSetupCount = 0;
4923 pSMB->Reserved = 0;
4924 pSMB->Flags = 0;
4925 pSMB->Timeout = 0;
4926 pSMB->Reserved2 = 0;
4927 byte_count = params + 1 /* pad */ ;
4928 pSMB->TotalParameterCount = cpu_to_le16(params);
4929 pSMB->ParameterCount = pSMB->TotalParameterCount;
4930 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4931 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4932
4933 pSMB->DataCount = 0;
4934 pSMB->DataOffset = 0;
4935 pSMB->SetupCount = 1;
4936 pSMB->Reserved3 = 0;
4937 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4938 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4939 inc_rfc1001_len(pSMB, byte_count);
4940 pSMB->ByteCount = cpu_to_le16(byte_count);
4941
4942 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4943 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4944 if (rc) {
4945 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
4946 } else { /* decode response */
4947 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4948
4949 if (rc || get_bcc(&pSMBr->hdr) <
4950 sizeof(FILE_SYSTEM_DEVICE_INFO))
4951 rc = -EIO; /* bad smb */
4952 else {
4953 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4954 response_data =
4955 (FILE_SYSTEM_DEVICE_INFO *)
4956 (((char *) &pSMBr->hdr.Protocol) +
4957 data_offset);
4958 memcpy(&tcon->fsDevInfo, response_data,
4959 sizeof(FILE_SYSTEM_DEVICE_INFO));
4960 }
4961 }
4962 cifs_buf_release(pSMB);
4963
4964 if (rc == -EAGAIN)
4965 goto QFSDeviceRetry;
4966
4967 return rc;
4968 }
4969
4970 int
CIFSSMBQFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon)4971 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
4972 {
4973 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4974 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4975 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4976 FILE_SYSTEM_UNIX_INFO *response_data;
4977 int rc = 0;
4978 int bytes_returned = 0;
4979 __u16 params, byte_count;
4980
4981 cifs_dbg(FYI, "In QFSUnixInfo\n");
4982 QFSUnixRetry:
4983 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4984 (void **) &pSMB, (void **) &pSMBr);
4985 if (rc)
4986 return rc;
4987
4988 params = 2; /* level */
4989 pSMB->TotalDataCount = 0;
4990 pSMB->DataCount = 0;
4991 pSMB->DataOffset = 0;
4992 pSMB->MaxParameterCount = cpu_to_le16(2);
4993 /* BB find exact max SMB PDU from sess structure BB */
4994 pSMB->MaxDataCount = cpu_to_le16(100);
4995 pSMB->MaxSetupCount = 0;
4996 pSMB->Reserved = 0;
4997 pSMB->Flags = 0;
4998 pSMB->Timeout = 0;
4999 pSMB->Reserved2 = 0;
5000 byte_count = params + 1 /* pad */ ;
5001 pSMB->ParameterCount = cpu_to_le16(params);
5002 pSMB->TotalParameterCount = pSMB->ParameterCount;
5003 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5004 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5005 pSMB->SetupCount = 1;
5006 pSMB->Reserved3 = 0;
5007 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5008 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5009 inc_rfc1001_len(pSMB, byte_count);
5010 pSMB->ByteCount = cpu_to_le16(byte_count);
5011
5012 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5013 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5014 if (rc) {
5015 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5016 } else { /* decode response */
5017 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5018
5019 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5020 rc = -EIO; /* bad smb */
5021 } else {
5022 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5023 response_data =
5024 (FILE_SYSTEM_UNIX_INFO
5025 *) (((char *) &pSMBr->hdr.Protocol) +
5026 data_offset);
5027 memcpy(&tcon->fsUnixInfo, response_data,
5028 sizeof(FILE_SYSTEM_UNIX_INFO));
5029 }
5030 }
5031 cifs_buf_release(pSMB);
5032
5033 if (rc == -EAGAIN)
5034 goto QFSUnixRetry;
5035
5036
5037 return rc;
5038 }
5039
5040 int
CIFSSMBSetFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon,__u64 cap)5041 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5042 {
5043 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5044 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5045 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5046 int rc = 0;
5047 int bytes_returned = 0;
5048 __u16 params, param_offset, offset, byte_count;
5049
5050 cifs_dbg(FYI, "In SETFSUnixInfo\n");
5051 SETFSUnixRetry:
5052 /* BB switch to small buf init to save memory */
5053 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5054 (void **) &pSMB, (void **) &pSMBr);
5055 if (rc)
5056 return rc;
5057
5058 params = 4; /* 2 bytes zero followed by info level. */
5059 pSMB->MaxSetupCount = 0;
5060 pSMB->Reserved = 0;
5061 pSMB->Flags = 0;
5062 pSMB->Timeout = 0;
5063 pSMB->Reserved2 = 0;
5064 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5065 - 4;
5066 offset = param_offset + params;
5067
5068 pSMB->MaxParameterCount = cpu_to_le16(4);
5069 /* BB find exact max SMB PDU from sess structure BB */
5070 pSMB->MaxDataCount = cpu_to_le16(100);
5071 pSMB->SetupCount = 1;
5072 pSMB->Reserved3 = 0;
5073 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5074 byte_count = 1 /* pad */ + params + 12;
5075
5076 pSMB->DataCount = cpu_to_le16(12);
5077 pSMB->ParameterCount = cpu_to_le16(params);
5078 pSMB->TotalDataCount = pSMB->DataCount;
5079 pSMB->TotalParameterCount = pSMB->ParameterCount;
5080 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5081 pSMB->DataOffset = cpu_to_le16(offset);
5082
5083 /* Params. */
5084 pSMB->FileNum = 0;
5085 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5086
5087 /* Data. */
5088 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5089 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5090 pSMB->ClientUnixCap = cpu_to_le64(cap);
5091
5092 inc_rfc1001_len(pSMB, byte_count);
5093 pSMB->ByteCount = cpu_to_le16(byte_count);
5094
5095 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5096 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5097 if (rc) {
5098 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5099 } else { /* decode response */
5100 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5101 if (rc)
5102 rc = -EIO; /* bad smb */
5103 }
5104 cifs_buf_release(pSMB);
5105
5106 if (rc == -EAGAIN)
5107 goto SETFSUnixRetry;
5108
5109 return rc;
5110 }
5111
5112
5113
5114 int
CIFSSMBQFSPosixInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5115 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5116 struct kstatfs *FSData)
5117 {
5118 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5119 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5120 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5121 FILE_SYSTEM_POSIX_INFO *response_data;
5122 int rc = 0;
5123 int bytes_returned = 0;
5124 __u16 params, byte_count;
5125
5126 cifs_dbg(FYI, "In QFSPosixInfo\n");
5127 QFSPosixRetry:
5128 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5129 (void **) &pSMBr);
5130 if (rc)
5131 return rc;
5132
5133 params = 2; /* level */
5134 pSMB->TotalDataCount = 0;
5135 pSMB->DataCount = 0;
5136 pSMB->DataOffset = 0;
5137 pSMB->MaxParameterCount = cpu_to_le16(2);
5138 /* BB find exact max SMB PDU from sess structure BB */
5139 pSMB->MaxDataCount = cpu_to_le16(100);
5140 pSMB->MaxSetupCount = 0;
5141 pSMB->Reserved = 0;
5142 pSMB->Flags = 0;
5143 pSMB->Timeout = 0;
5144 pSMB->Reserved2 = 0;
5145 byte_count = params + 1 /* pad */ ;
5146 pSMB->ParameterCount = cpu_to_le16(params);
5147 pSMB->TotalParameterCount = pSMB->ParameterCount;
5148 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5149 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5150 pSMB->SetupCount = 1;
5151 pSMB->Reserved3 = 0;
5152 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5153 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5154 inc_rfc1001_len(pSMB, byte_count);
5155 pSMB->ByteCount = cpu_to_le16(byte_count);
5156
5157 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5158 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5159 if (rc) {
5160 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5161 } else { /* decode response */
5162 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5163
5164 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5165 rc = -EIO; /* bad smb */
5166 } else {
5167 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5168 response_data =
5169 (FILE_SYSTEM_POSIX_INFO
5170 *) (((char *) &pSMBr->hdr.Protocol) +
5171 data_offset);
5172 FSData->f_bsize =
5173 le32_to_cpu(response_data->BlockSize);
5174 /*
5175 * much prefer larger but if server doesn't report
5176 * a valid size than 4K is a reasonable minimum
5177 */
5178 if (FSData->f_bsize < 512)
5179 FSData->f_bsize = 4096;
5180
5181 FSData->f_blocks =
5182 le64_to_cpu(response_data->TotalBlocks);
5183 FSData->f_bfree =
5184 le64_to_cpu(response_data->BlocksAvail);
5185 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5186 FSData->f_bavail = FSData->f_bfree;
5187 } else {
5188 FSData->f_bavail =
5189 le64_to_cpu(response_data->UserBlocksAvail);
5190 }
5191 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5192 FSData->f_files =
5193 le64_to_cpu(response_data->TotalFileNodes);
5194 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5195 FSData->f_ffree =
5196 le64_to_cpu(response_data->FreeFileNodes);
5197 }
5198 }
5199 cifs_buf_release(pSMB);
5200
5201 if (rc == -EAGAIN)
5202 goto QFSPosixRetry;
5203
5204 return rc;
5205 }
5206
5207
5208 /*
5209 * We can not use write of zero bytes trick to set file size due to need for
5210 * large file support. Also note that this SetPathInfo is preferred to
5211 * SetFileInfo based method in next routine which is only needed to work around
5212 * a sharing violation bugin Samba which this routine can run into.
5213 */
5214 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)5215 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5216 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5217 bool set_allocation, struct dentry *dentry)
5218 {
5219 struct smb_com_transaction2_spi_req *pSMB = NULL;
5220 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5221 struct file_end_of_file_info *parm_data;
5222 int name_len;
5223 int rc = 0;
5224 int bytes_returned = 0;
5225 int remap = cifs_remap(cifs_sb);
5226
5227 __u16 params, byte_count, data_count, param_offset, offset;
5228
5229 cifs_dbg(FYI, "In SetEOF\n");
5230 SetEOFRetry:
5231 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5232 (void **) &pSMBr);
5233 if (rc)
5234 return rc;
5235
5236 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5237 name_len =
5238 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5239 PATH_MAX, cifs_sb->local_nls, remap);
5240 name_len++; /* trailing null */
5241 name_len *= 2;
5242 } else {
5243 name_len = copy_path_name(pSMB->FileName, file_name);
5244 }
5245 params = 6 + name_len;
5246 data_count = sizeof(struct file_end_of_file_info);
5247 pSMB->MaxParameterCount = cpu_to_le16(2);
5248 pSMB->MaxDataCount = cpu_to_le16(4100);
5249 pSMB->MaxSetupCount = 0;
5250 pSMB->Reserved = 0;
5251 pSMB->Flags = 0;
5252 pSMB->Timeout = 0;
5253 pSMB->Reserved2 = 0;
5254 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5255 InformationLevel) - 4;
5256 offset = param_offset + params;
5257 if (set_allocation) {
5258 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5259 pSMB->InformationLevel =
5260 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5261 else
5262 pSMB->InformationLevel =
5263 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5264 } else /* Set File Size */ {
5265 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5266 pSMB->InformationLevel =
5267 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5268 else
5269 pSMB->InformationLevel =
5270 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5271 }
5272
5273 parm_data =
5274 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5275 offset);
5276 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5277 pSMB->DataOffset = cpu_to_le16(offset);
5278 pSMB->SetupCount = 1;
5279 pSMB->Reserved3 = 0;
5280 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5281 byte_count = 3 /* pad */ + params + data_count;
5282 pSMB->DataCount = cpu_to_le16(data_count);
5283 pSMB->TotalDataCount = pSMB->DataCount;
5284 pSMB->ParameterCount = cpu_to_le16(params);
5285 pSMB->TotalParameterCount = pSMB->ParameterCount;
5286 pSMB->Reserved4 = 0;
5287 inc_rfc1001_len(pSMB, byte_count);
5288 parm_data->FileSize = cpu_to_le64(size);
5289 pSMB->ByteCount = cpu_to_le16(byte_count);
5290 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5291 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5292 if (rc)
5293 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5294
5295 cifs_buf_release(pSMB);
5296
5297 if (rc == -EAGAIN)
5298 goto SetEOFRetry;
5299
5300 return rc;
5301 }
5302
5303 int
CIFSSMBSetFileSize(const unsigned int xid,struct cifs_tcon * tcon,struct cifsFileInfo * cfile,__u64 size,bool set_allocation)5304 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5305 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5306 {
5307 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5308 struct file_end_of_file_info *parm_data;
5309 int rc = 0;
5310 __u16 params, param_offset, offset, byte_count, count;
5311
5312 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5313 (long long)size);
5314 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5315
5316 if (rc)
5317 return rc;
5318
5319 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5320 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5321
5322 params = 6;
5323 pSMB->MaxSetupCount = 0;
5324 pSMB->Reserved = 0;
5325 pSMB->Flags = 0;
5326 pSMB->Timeout = 0;
5327 pSMB->Reserved2 = 0;
5328 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5329 offset = param_offset + params;
5330
5331 count = sizeof(struct file_end_of_file_info);
5332 pSMB->MaxParameterCount = cpu_to_le16(2);
5333 /* BB find exact max SMB PDU from sess structure BB */
5334 pSMB->MaxDataCount = cpu_to_le16(1000);
5335 pSMB->SetupCount = 1;
5336 pSMB->Reserved3 = 0;
5337 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5338 byte_count = 3 /* pad */ + params + count;
5339 pSMB->DataCount = cpu_to_le16(count);
5340 pSMB->ParameterCount = cpu_to_le16(params);
5341 pSMB->TotalDataCount = pSMB->DataCount;
5342 pSMB->TotalParameterCount = pSMB->ParameterCount;
5343 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5344 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5345 parm_data =
5346 (struct file_end_of_file_info *)(((char *)pSMB) + offset + 4);
5347 pSMB->DataOffset = cpu_to_le16(offset);
5348 parm_data->FileSize = cpu_to_le64(size);
5349 pSMB->Fid = cfile->fid.netfid;
5350 if (set_allocation) {
5351 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5352 pSMB->InformationLevel =
5353 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5354 else
5355 pSMB->InformationLevel =
5356 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5357 } else /* Set File Size */ {
5358 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5359 pSMB->InformationLevel =
5360 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5361 else
5362 pSMB->InformationLevel =
5363 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5364 }
5365 pSMB->Reserved4 = 0;
5366 inc_rfc1001_len(pSMB, byte_count);
5367 pSMB->ByteCount = cpu_to_le16(byte_count);
5368 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5369 cifs_small_buf_release(pSMB);
5370 if (rc) {
5371 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5372 rc);
5373 }
5374
5375 /* Note: On -EAGAIN error only caller can retry on handle based calls
5376 since file handle passed in no longer valid */
5377
5378 return rc;
5379 }
5380
5381 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)5382 SMBSetInformation(const unsigned int xid, struct cifs_tcon *tcon,
5383 const char *fileName, __le32 attributes, __le64 write_time,
5384 const struct nls_table *nls_codepage,
5385 struct cifs_sb_info *cifs_sb)
5386 {
5387 SETATTR_REQ *pSMB;
5388 SETATTR_RSP *pSMBr;
5389 struct timespec64 ts;
5390 int bytes_returned;
5391 int name_len;
5392 int rc;
5393
5394 cifs_dbg(FYI, "In %s path %s\n", __func__, fileName);
5395
5396 retry:
5397 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5398 (void **) &pSMBr);
5399 if (rc)
5400 return rc;
5401
5402 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5403 name_len =
5404 cifsConvertToUTF16((__le16 *) pSMB->fileName,
5405 fileName, PATH_MAX, nls_codepage,
5406 cifs_remap(cifs_sb));
5407 name_len++; /* trailing null */
5408 name_len *= 2;
5409 } else {
5410 name_len = copy_path_name(pSMB->fileName, fileName);
5411 }
5412 /* Only few attributes can be set by this command, others are not accepted by Win9x. */
5413 pSMB->attr = cpu_to_le16(le32_to_cpu(attributes) &
5414 (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE));
5415 /* Zero write time value (in both NT and SETATTR formats) means to not change it. */
5416 if (le64_to_cpu(write_time) != 0) {
5417 ts = cifs_NTtimeToUnix(write_time);
5418 pSMB->last_write_time = cpu_to_le32(ts.tv_sec);
5419 }
5420 pSMB->BufferFormat = 0x04;
5421 name_len++; /* account for buffer type byte */
5422 inc_rfc1001_len(pSMB, (__u16)name_len);
5423 pSMB->ByteCount = cpu_to_le16(name_len);
5424
5425 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5426 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5427 if (rc)
5428 cifs_dbg(FYI, "Send error in %s = %d\n", __func__, rc);
5429
5430 cifs_buf_release(pSMB);
5431
5432 if (rc == -EAGAIN)
5433 goto retry;
5434
5435 return rc;
5436 }
5437
5438 /* Some legacy servers such as NT4 require that the file times be set on
5439 an open handle, rather than by pathname - this is awkward due to
5440 potential access conflicts on the open, but it is unavoidable for these
5441 old servers since the only other choice is to go from 100 nanosecond DCE
5442 time and resort to the original setpathinfo level which takes the ancient
5443 DOS time format with 2 second granularity */
5444 int
CIFSSMBSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const FILE_BASIC_INFO * data,__u16 fid,__u32 pid_of_opener)5445 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5446 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5447 {
5448 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5449 char *data_offset;
5450 int rc = 0;
5451 __u16 params, param_offset, offset, byte_count, count;
5452
5453 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5454 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5455
5456 if (rc)
5457 return rc;
5458
5459 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5460 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5461
5462 params = 6;
5463 pSMB->MaxSetupCount = 0;
5464 pSMB->Reserved = 0;
5465 pSMB->Flags = 0;
5466 pSMB->Timeout = 0;
5467 pSMB->Reserved2 = 0;
5468 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5469 offset = param_offset + params;
5470
5471 data_offset = (char *)pSMB +
5472 offsetof(struct smb_hdr, Protocol) + offset;
5473
5474 count = sizeof(FILE_BASIC_INFO);
5475 pSMB->MaxParameterCount = cpu_to_le16(2);
5476 /* BB find max SMB PDU from sess */
5477 pSMB->MaxDataCount = cpu_to_le16(1000);
5478 pSMB->SetupCount = 1;
5479 pSMB->Reserved3 = 0;
5480 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5481 byte_count = 3 /* pad */ + params + count;
5482 pSMB->DataCount = cpu_to_le16(count);
5483 pSMB->ParameterCount = cpu_to_le16(params);
5484 pSMB->TotalDataCount = pSMB->DataCount;
5485 pSMB->TotalParameterCount = pSMB->ParameterCount;
5486 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5487 pSMB->DataOffset = cpu_to_le16(offset);
5488 pSMB->Fid = fid;
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 pSMB->ByteCount = cpu_to_le16(byte_count);
5496 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5497 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5498 cifs_small_buf_release(pSMB);
5499 if (rc)
5500 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5501 rc);
5502
5503 /* Note: On -EAGAIN error only caller can retry on handle based calls
5504 since file handle passed in no longer valid */
5505
5506 return rc;
5507 }
5508
5509 int
CIFSSMBSetFileDisposition(const unsigned int xid,struct cifs_tcon * tcon,bool delete_file,__u16 fid,__u32 pid_of_opener)5510 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5511 bool delete_file, __u16 fid, __u32 pid_of_opener)
5512 {
5513 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5514 char *data_offset;
5515 int rc = 0;
5516 __u16 params, param_offset, offset, byte_count, count;
5517
5518 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5519 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5520
5521 if (rc)
5522 return rc;
5523
5524 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5525 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5526
5527 params = 6;
5528 pSMB->MaxSetupCount = 0;
5529 pSMB->Reserved = 0;
5530 pSMB->Flags = 0;
5531 pSMB->Timeout = 0;
5532 pSMB->Reserved2 = 0;
5533 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5534 offset = param_offset + params;
5535
5536 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5537 data_offset = (char *)(pSMB) + offset + 4;
5538
5539 count = 1;
5540 pSMB->MaxParameterCount = cpu_to_le16(2);
5541 /* BB find max SMB PDU from sess */
5542 pSMB->MaxDataCount = cpu_to_le16(1000);
5543 pSMB->SetupCount = 1;
5544 pSMB->Reserved3 = 0;
5545 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5546 byte_count = 3 /* pad */ + params + count;
5547 pSMB->DataCount = cpu_to_le16(count);
5548 pSMB->ParameterCount = cpu_to_le16(params);
5549 pSMB->TotalDataCount = pSMB->DataCount;
5550 pSMB->TotalParameterCount = pSMB->ParameterCount;
5551 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5552 pSMB->DataOffset = cpu_to_le16(offset);
5553 pSMB->Fid = fid;
5554 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5555 pSMB->Reserved4 = 0;
5556 inc_rfc1001_len(pSMB, byte_count);
5557 pSMB->ByteCount = cpu_to_le16(byte_count);
5558 *data_offset = delete_file ? 1 : 0;
5559 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5560 cifs_small_buf_release(pSMB);
5561 if (rc)
5562 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5563
5564 return rc;
5565 }
5566
5567 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)5568 CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
5569 const char *fileName, const FILE_BASIC_INFO *data,
5570 const struct nls_table *nls_codepage,
5571 struct cifs_sb_info *cifs_sb)
5572 {
5573 int oplock = 0;
5574 struct cifs_open_parms oparms;
5575 struct cifs_fid fid;
5576 int rc;
5577
5578 oparms = (struct cifs_open_parms) {
5579 .tcon = tcon,
5580 .cifs_sb = cifs_sb,
5581 .desired_access = GENERIC_WRITE,
5582 .create_options = cifs_create_options(cifs_sb, 0),
5583 .disposition = FILE_OPEN,
5584 .path = fileName,
5585 .fid = &fid,
5586 };
5587
5588 rc = CIFS_open(xid, &oparms, &oplock, NULL);
5589 if (rc)
5590 goto out;
5591
5592 rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
5593 CIFSSMBClose(xid, tcon, fid.netfid);
5594 out:
5595
5596 return rc;
5597 }
5598
5599 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)5600 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5601 const char *fileName, const FILE_BASIC_INFO *data,
5602 const struct nls_table *nls_codepage,
5603 struct cifs_sb_info *cifs_sb)
5604 {
5605 TRANSACTION2_SPI_REQ *pSMB = NULL;
5606 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5607 int name_len;
5608 int rc = 0;
5609 int bytes_returned = 0;
5610 char *data_offset;
5611 __u16 params, param_offset, offset, byte_count, count;
5612 int remap = cifs_remap(cifs_sb);
5613
5614 cifs_dbg(FYI, "In SetTimes\n");
5615
5616 SetTimesRetry:
5617 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5618 (void **) &pSMBr);
5619 if (rc)
5620 return rc;
5621
5622 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5623 name_len =
5624 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5625 PATH_MAX, nls_codepage, remap);
5626 name_len++; /* trailing null */
5627 name_len *= 2;
5628 } else {
5629 name_len = copy_path_name(pSMB->FileName, fileName);
5630 }
5631
5632 params = 6 + name_len;
5633 count = sizeof(FILE_BASIC_INFO);
5634 pSMB->MaxParameterCount = cpu_to_le16(2);
5635 /* BB find max SMB PDU from sess structure BB */
5636 pSMB->MaxDataCount = cpu_to_le16(1000);
5637 pSMB->MaxSetupCount = 0;
5638 pSMB->Reserved = 0;
5639 pSMB->Flags = 0;
5640 pSMB->Timeout = 0;
5641 pSMB->Reserved2 = 0;
5642 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5643 InformationLevel) - 4;
5644 offset = param_offset + params;
5645 data_offset = (char *)pSMB + offsetof(typeof(*pSMB), hdr.Protocol) + offset;
5646 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5647 pSMB->DataOffset = cpu_to_le16(offset);
5648 pSMB->SetupCount = 1;
5649 pSMB->Reserved3 = 0;
5650 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5651 byte_count = 3 /* pad */ + params + count;
5652
5653 pSMB->DataCount = cpu_to_le16(count);
5654 pSMB->ParameterCount = cpu_to_le16(params);
5655 pSMB->TotalDataCount = pSMB->DataCount;
5656 pSMB->TotalParameterCount = pSMB->ParameterCount;
5657 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5658 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5659 else
5660 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5661 pSMB->Reserved4 = 0;
5662 inc_rfc1001_len(pSMB, byte_count);
5663 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5664 pSMB->ByteCount = cpu_to_le16(byte_count);
5665 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5666 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5667 if (rc)
5668 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5669
5670 cifs_buf_release(pSMB);
5671
5672 if (rc == -EAGAIN)
5673 goto SetTimesRetry;
5674
5675 if (rc == -EOPNOTSUPP)
5676 return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
5677 nls_codepage, cifs_sb);
5678
5679 return rc;
5680 }
5681
5682 static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO * data_offset,const struct cifs_unix_set_info_args * args)5683 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5684 const struct cifs_unix_set_info_args *args)
5685 {
5686 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5687 u64 mode = args->mode;
5688
5689 if (uid_valid(args->uid))
5690 uid = from_kuid(&init_user_ns, args->uid);
5691 if (gid_valid(args->gid))
5692 gid = from_kgid(&init_user_ns, args->gid);
5693
5694 /*
5695 * Samba server ignores set of file size to zero due to bugs in some
5696 * older clients, but we should be precise - we use SetFileSize to
5697 * set file size and do not want to truncate file size to zero
5698 * accidentally as happened on one Samba server beta by putting
5699 * zero instead of -1 here
5700 */
5701 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5702 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5703 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5704 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5705 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5706 data_offset->Uid = cpu_to_le64(uid);
5707 data_offset->Gid = cpu_to_le64(gid);
5708 /* better to leave device as zero when it is */
5709 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5710 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5711 data_offset->Permissions = cpu_to_le64(mode);
5712
5713 if (S_ISREG(mode))
5714 data_offset->Type = cpu_to_le32(UNIX_FILE);
5715 else if (S_ISDIR(mode))
5716 data_offset->Type = cpu_to_le32(UNIX_DIR);
5717 else if (S_ISLNK(mode))
5718 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5719 else if (S_ISCHR(mode))
5720 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5721 else if (S_ISBLK(mode))
5722 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5723 else if (S_ISFIFO(mode))
5724 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5725 else if (S_ISSOCK(mode))
5726 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5727 }
5728
5729 int
CIFSSMBUnixSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const struct cifs_unix_set_info_args * args,u16 fid,u32 pid_of_opener)5730 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5731 const struct cifs_unix_set_info_args *args,
5732 u16 fid, u32 pid_of_opener)
5733 {
5734 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5735 char *data_offset;
5736 int rc = 0;
5737 u16 params, param_offset, offset, byte_count, count;
5738
5739 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5740 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5741
5742 if (rc)
5743 return rc;
5744
5745 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5746 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5747
5748 params = 6;
5749 pSMB->MaxSetupCount = 0;
5750 pSMB->Reserved = 0;
5751 pSMB->Flags = 0;
5752 pSMB->Timeout = 0;
5753 pSMB->Reserved2 = 0;
5754 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5755 offset = param_offset + params;
5756
5757 data_offset = (char *)pSMB +
5758 offsetof(struct smb_hdr, Protocol) + offset;
5759
5760 count = sizeof(FILE_UNIX_BASIC_INFO);
5761
5762 pSMB->MaxParameterCount = cpu_to_le16(2);
5763 /* BB find max SMB PDU from sess */
5764 pSMB->MaxDataCount = cpu_to_le16(1000);
5765 pSMB->SetupCount = 1;
5766 pSMB->Reserved3 = 0;
5767 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5768 byte_count = 3 /* pad */ + params + count;
5769 pSMB->DataCount = cpu_to_le16(count);
5770 pSMB->ParameterCount = cpu_to_le16(params);
5771 pSMB->TotalDataCount = pSMB->DataCount;
5772 pSMB->TotalParameterCount = pSMB->ParameterCount;
5773 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5774 pSMB->DataOffset = cpu_to_le16(offset);
5775 pSMB->Fid = fid;
5776 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5777 pSMB->Reserved4 = 0;
5778 inc_rfc1001_len(pSMB, byte_count);
5779 pSMB->ByteCount = cpu_to_le16(byte_count);
5780
5781 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5782
5783 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5784 cifs_small_buf_release(pSMB);
5785 if (rc)
5786 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5787 rc);
5788
5789 /* Note: On -EAGAIN error only caller can retry on handle based calls
5790 since file handle passed in no longer valid */
5791
5792 return rc;
5793 }
5794
5795 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)5796 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5797 const char *file_name,
5798 const struct cifs_unix_set_info_args *args,
5799 const struct nls_table *nls_codepage, int remap)
5800 {
5801 TRANSACTION2_SPI_REQ *pSMB = NULL;
5802 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5803 int name_len;
5804 int rc = 0;
5805 int bytes_returned = 0;
5806 FILE_UNIX_BASIC_INFO *data_offset;
5807 __u16 params, param_offset, offset, count, byte_count;
5808
5809 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
5810 setPermsRetry:
5811 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5812 (void **) &pSMBr);
5813 if (rc)
5814 return rc;
5815
5816 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5817 name_len =
5818 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5819 PATH_MAX, nls_codepage, remap);
5820 name_len++; /* trailing null */
5821 name_len *= 2;
5822 } else {
5823 name_len = copy_path_name(pSMB->FileName, file_name);
5824 }
5825
5826 params = 6 + name_len;
5827 count = sizeof(FILE_UNIX_BASIC_INFO);
5828 pSMB->MaxParameterCount = cpu_to_le16(2);
5829 /* BB find max SMB PDU from sess structure BB */
5830 pSMB->MaxDataCount = cpu_to_le16(1000);
5831 pSMB->MaxSetupCount = 0;
5832 pSMB->Reserved = 0;
5833 pSMB->Flags = 0;
5834 pSMB->Timeout = 0;
5835 pSMB->Reserved2 = 0;
5836 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5837 InformationLevel) - 4;
5838 offset = param_offset + params;
5839 /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5840 data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4);
5841 memset(data_offset, 0, count);
5842 pSMB->DataOffset = cpu_to_le16(offset);
5843 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5844 pSMB->SetupCount = 1;
5845 pSMB->Reserved3 = 0;
5846 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5847 byte_count = 3 /* pad */ + params + count;
5848 pSMB->ParameterCount = cpu_to_le16(params);
5849 pSMB->DataCount = cpu_to_le16(count);
5850 pSMB->TotalParameterCount = pSMB->ParameterCount;
5851 pSMB->TotalDataCount = pSMB->DataCount;
5852 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5853 pSMB->Reserved4 = 0;
5854 inc_rfc1001_len(pSMB, byte_count);
5855
5856 cifs_fill_unix_set_info(data_offset, args);
5857
5858 pSMB->ByteCount = cpu_to_le16(byte_count);
5859 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5860 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5861 if (rc)
5862 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
5863
5864 cifs_buf_release(pSMB);
5865 if (rc == -EAGAIN)
5866 goto setPermsRetry;
5867 return rc;
5868 }
5869
5870 #ifdef CONFIG_CIFS_XATTR
5871 /*
5872 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5873 * function used by listxattr and getxattr type calls. When ea_name is set,
5874 * it looks for that attribute name and stuffs that value into the EAData
5875 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5876 * buffer. In both cases, the return value is either the length of the
5877 * resulting data or a negative error code. If EAData is a NULL pointer then
5878 * the data isn't copied to it, but the length is returned.
5879 */
5880 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)5881 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
5882 const unsigned char *searchName, const unsigned char *ea_name,
5883 char *EAData, size_t buf_size,
5884 struct cifs_sb_info *cifs_sb)
5885 {
5886 /* BB assumes one setup word */
5887 TRANSACTION2_QPI_REQ *pSMB = NULL;
5888 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5889 int remap = cifs_remap(cifs_sb);
5890 struct nls_table *nls_codepage = cifs_sb->local_nls;
5891 int rc = 0;
5892 int bytes_returned;
5893 int list_len;
5894 struct fealist *ea_response_data;
5895 struct fea *temp_fea;
5896 char *temp_ptr;
5897 char *end_of_smb;
5898 __u16 params, byte_count, data_offset;
5899 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
5900
5901 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
5902 QAllEAsRetry:
5903 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5904 (void **) &pSMBr);
5905 if (rc)
5906 return rc;
5907
5908 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5909 list_len =
5910 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
5911 PATH_MAX, nls_codepage, remap);
5912 list_len++; /* trailing null */
5913 list_len *= 2;
5914 } else {
5915 list_len = copy_path_name(pSMB->FileName, searchName);
5916 }
5917
5918 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5919 pSMB->TotalDataCount = 0;
5920 pSMB->MaxParameterCount = cpu_to_le16(2);
5921 /* BB find exact max SMB PDU from sess structure BB */
5922 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5923 pSMB->MaxSetupCount = 0;
5924 pSMB->Reserved = 0;
5925 pSMB->Flags = 0;
5926 pSMB->Timeout = 0;
5927 pSMB->Reserved2 = 0;
5928 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5929 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5930 pSMB->DataCount = 0;
5931 pSMB->DataOffset = 0;
5932 pSMB->SetupCount = 1;
5933 pSMB->Reserved3 = 0;
5934 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5935 byte_count = params + 1 /* pad */ ;
5936 pSMB->TotalParameterCount = cpu_to_le16(params);
5937 pSMB->ParameterCount = pSMB->TotalParameterCount;
5938 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5939 pSMB->Reserved4 = 0;
5940 inc_rfc1001_len(pSMB, byte_count);
5941 pSMB->ByteCount = cpu_to_le16(byte_count);
5942
5943 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5944 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5945 if (rc) {
5946 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
5947 goto QAllEAsOut;
5948 }
5949
5950
5951 /* BB also check enough total bytes returned */
5952 /* BB we need to improve the validity checking
5953 of these trans2 responses */
5954
5955 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5956 if (rc || get_bcc(&pSMBr->hdr) < 4) {
5957 rc = -EIO; /* bad smb */
5958 goto QAllEAsOut;
5959 }
5960
5961 /* check that length of list is not more than bcc */
5962 /* check that each entry does not go beyond length
5963 of list */
5964 /* check that each element of each entry does not
5965 go beyond end of list */
5966 /* validate_trans2_offsets() */
5967 /* BB check if start of smb + data_offset > &bcc+ bcc */
5968
5969 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5970 ea_response_data = (struct fealist *)
5971 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5972
5973 list_len = le32_to_cpu(ea_response_data->list_len);
5974 cifs_dbg(FYI, "ea length %d\n", list_len);
5975 if (list_len <= 8) {
5976 cifs_dbg(FYI, "empty EA list returned from server\n");
5977 /* didn't find the named attribute */
5978 if (ea_name)
5979 rc = -ENODATA;
5980 goto QAllEAsOut;
5981 }
5982
5983 /* make sure list_len doesn't go past end of SMB */
5984 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5985 if ((char *)ea_response_data + list_len > end_of_smb) {
5986 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
5987 rc = -EIO;
5988 goto QAllEAsOut;
5989 }
5990
5991 /* account for ea list len */
5992 list_len -= 4;
5993 temp_fea = &ea_response_data->list;
5994 temp_ptr = (char *)temp_fea;
5995 while (list_len > 0) {
5996 unsigned int name_len;
5997 __u16 value_len;
5998
5999 list_len -= 4;
6000 temp_ptr += 4;
6001 /* make sure we can read name_len and value_len */
6002 if (list_len < 0) {
6003 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6004 rc = -EIO;
6005 goto QAllEAsOut;
6006 }
6007
6008 name_len = temp_fea->name_len;
6009 value_len = le16_to_cpu(temp_fea->value_len);
6010 list_len -= name_len + 1 + value_len;
6011 if (list_len < 0) {
6012 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6013 rc = -EIO;
6014 goto QAllEAsOut;
6015 }
6016
6017 if (ea_name) {
6018 if (ea_name_len == name_len &&
6019 memcmp(ea_name, temp_ptr, name_len) == 0) {
6020 temp_ptr += name_len + 1;
6021 rc = value_len;
6022 if (buf_size == 0)
6023 goto QAllEAsOut;
6024 if ((size_t)value_len > buf_size) {
6025 rc = -ERANGE;
6026 goto QAllEAsOut;
6027 }
6028 memcpy(EAData, temp_ptr, value_len);
6029 goto QAllEAsOut;
6030 }
6031 } else {
6032 /* account for prefix user. and trailing null */
6033 rc += (5 + 1 + name_len);
6034 if (rc < (int) buf_size) {
6035 memcpy(EAData, "user.", 5);
6036 EAData += 5;
6037 memcpy(EAData, temp_ptr, name_len);
6038 EAData += name_len;
6039 /* null terminate name */
6040 *EAData = 0;
6041 ++EAData;
6042 } else if (buf_size == 0) {
6043 /* skip copy - calc size only */
6044 } else {
6045 /* stop before overrun buffer */
6046 rc = -ERANGE;
6047 break;
6048 }
6049 }
6050 temp_ptr += name_len + 1 + value_len;
6051 temp_fea = (struct fea *)temp_ptr;
6052 }
6053
6054 /* didn't find the named attribute */
6055 if (ea_name)
6056 rc = -ENODATA;
6057
6058 QAllEAsOut:
6059 cifs_buf_release(pSMB);
6060 if (rc == -EAGAIN)
6061 goto QAllEAsRetry;
6062
6063 return (ssize_t)rc;
6064 }
6065
6066 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)6067 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6068 const char *fileName, const char *ea_name, const void *ea_value,
6069 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6070 struct cifs_sb_info *cifs_sb)
6071 {
6072 struct smb_com_transaction2_spi_req *pSMB = NULL;
6073 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6074 struct fealist *parm_data;
6075 int name_len;
6076 int rc = 0;
6077 int bytes_returned = 0;
6078 __u16 params, param_offset, byte_count, offset, count;
6079 int remap = cifs_remap(cifs_sb);
6080
6081 cifs_dbg(FYI, "In SetEA\n");
6082 SetEARetry:
6083 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6084 (void **) &pSMBr);
6085 if (rc)
6086 return rc;
6087
6088 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6089 name_len =
6090 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6091 PATH_MAX, nls_codepage, remap);
6092 name_len++; /* trailing null */
6093 name_len *= 2;
6094 } else {
6095 name_len = copy_path_name(pSMB->FileName, fileName);
6096 }
6097
6098 params = 6 + name_len;
6099
6100 /* done calculating parms using name_len of file name,
6101 now use name_len to calculate length of ea name
6102 we are going to create in the inode xattrs */
6103 if (ea_name == NULL)
6104 name_len = 0;
6105 else
6106 name_len = strnlen(ea_name, 255);
6107
6108 count = sizeof(*parm_data) + 1 + ea_value_len + name_len;
6109 pSMB->MaxParameterCount = cpu_to_le16(2);
6110 /* BB find max SMB PDU from sess */
6111 pSMB->MaxDataCount = cpu_to_le16(1000);
6112 pSMB->MaxSetupCount = 0;
6113 pSMB->Reserved = 0;
6114 pSMB->Flags = 0;
6115 pSMB->Timeout = 0;
6116 pSMB->Reserved2 = 0;
6117 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6118 InformationLevel) - 4;
6119 offset = param_offset + params;
6120 pSMB->InformationLevel =
6121 cpu_to_le16(SMB_SET_FILE_EA);
6122
6123 parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
6124 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6125 pSMB->DataOffset = cpu_to_le16(offset);
6126 pSMB->SetupCount = 1;
6127 pSMB->Reserved3 = 0;
6128 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6129 byte_count = 3 /* pad */ + params + count;
6130 pSMB->DataCount = cpu_to_le16(count);
6131 parm_data->list_len = cpu_to_le32(count);
6132 parm_data->list.EA_flags = 0;
6133 /* we checked above that name len is less than 255 */
6134 parm_data->list.name_len = (__u8)name_len;
6135 /* EA names are always ASCII and NUL-terminated */
6136 strscpy(parm_data->list.name, ea_name ?: "", name_len + 1);
6137 parm_data->list.value_len = cpu_to_le16(ea_value_len);
6138 /* caller ensures that ea_value_len is less than 64K but
6139 we need to ensure that it fits within the smb */
6140
6141 /*BB add length check to see if it would fit in
6142 negotiated SMB buffer size BB */
6143 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6144 if (ea_value_len)
6145 memcpy(parm_data->list.name + name_len + 1,
6146 ea_value, ea_value_len);
6147
6148 pSMB->TotalDataCount = pSMB->DataCount;
6149 pSMB->ParameterCount = cpu_to_le16(params);
6150 pSMB->TotalParameterCount = pSMB->ParameterCount;
6151 pSMB->Reserved4 = 0;
6152 inc_rfc1001_len(pSMB, byte_count);
6153 pSMB->ByteCount = cpu_to_le16(byte_count);
6154 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6155 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6156 if (rc)
6157 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6158
6159 cifs_buf_release(pSMB);
6160
6161 if (rc == -EAGAIN)
6162 goto SetEARetry;
6163
6164 return rc;
6165 }
6166 #endif
6167