aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/misc.c')
-rw-r--r--fs/cifs/misc.c189
1 files changed, 66 insertions, 123 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 43f10281bc19..2a930a752a78 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -236,10 +236,7 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
236{ 236{
237 __u16 mid = 0; 237 __u16 mid = 0;
238 __u16 last_mid; 238 __u16 last_mid;
239 int collision; 239 bool collision;
240
241 if (server == NULL)
242 return mid;
243 240
244 spin_lock(&GlobalMid_Lock); 241 spin_lock(&GlobalMid_Lock);
245 last_mid = server->CurrentMid; /* we do not want to loop forever */ 242 last_mid = server->CurrentMid; /* we do not want to loop forever */
@@ -252,24 +249,38 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
252 (and it would also have to have been a request that 249 (and it would also have to have been a request that
253 did not time out) */ 250 did not time out) */
254 while (server->CurrentMid != last_mid) { 251 while (server->CurrentMid != last_mid) {
255 struct list_head *tmp;
256 struct mid_q_entry *mid_entry; 252 struct mid_q_entry *mid_entry;
253 unsigned int num_mids;
257 254
258 collision = 0; 255 collision = false;
259 if (server->CurrentMid == 0) 256 if (server->CurrentMid == 0)
260 server->CurrentMid++; 257 server->CurrentMid++;
261 258
262 list_for_each(tmp, &server->pending_mid_q) { 259 num_mids = 0;
263 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 260 list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
264 261 ++num_mids;
265 if ((mid_entry->mid == server->CurrentMid) && 262 if (mid_entry->mid == server->CurrentMid &&
266 (mid_entry->midState == MID_REQUEST_SUBMITTED)) { 263 mid_entry->midState == MID_REQUEST_SUBMITTED) {
267 /* This mid is in use, try a different one */ 264 /* This mid is in use, try a different one */
268 collision = 1; 265 collision = true;
269 break; 266 break;
270 } 267 }
271 } 268 }
272 if (collision == 0) { 269
270 /*
271 * if we have more than 32k mids in the list, then something
272 * is very wrong. Possibly a local user is trying to DoS the
273 * box by issuing long-running calls and SIGKILL'ing them. If
274 * we get to 2^16 mids then we're in big trouble as this
275 * function could loop forever.
276 *
277 * Go ahead and assign out the mid in this situation, but force
278 * an eventual reconnect to clean out the pending_mid_q.
279 */
280 if (num_mids > 32768)
281 server->tcpStatus = CifsNeedReconnect;
282
283 if (!collision) {
273 mid = server->CurrentMid; 284 mid = server->CurrentMid;
274 break; 285 break;
275 } 286 }
@@ -381,29 +392,31 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
381} 392}
382 393
383static int 394static int
384checkSMBhdr(struct smb_hdr *smb, __u16 mid) 395check_smb_hdr(struct smb_hdr *smb, __u16 mid)
385{ 396{
386 /* Make sure that this really is an SMB, that it is a response, 397 /* does it have the right SMB "signature" ? */
387 and that the message ids match */ 398 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) {
388 if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) && 399 cERROR(1, "Bad protocol string signature header 0x%x",
389 (mid == smb->Mid)) { 400 *(unsigned int *)smb->Protocol);
390 if (smb->Flags & SMBFLG_RESPONSE) 401 return 1;
391 return 0;
392 else {
393 /* only one valid case where server sends us request */
394 if (smb->Command == SMB_COM_LOCKING_ANDX)
395 return 0;
396 else
397 cERROR(1, "Received Request not response");
398 }
399 } else { /* bad signature or mid */
400 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
401 cERROR(1, "Bad protocol string signature header %x",
402 *(unsigned int *) smb->Protocol);
403 if (mid != smb->Mid)
404 cERROR(1, "Mids do not match");
405 } 402 }
406 cERROR(1, "bad smb detected. The Mid=%d", smb->Mid); 403
404 /* Make sure that message ids match */
405 if (mid != smb->Mid) {
406 cERROR(1, "Mids do not match. received=%u expected=%u",
407 smb->Mid, mid);
408 return 1;
409 }
410
411 /* if it's a response then accept */
412 if (smb->Flags & SMBFLG_RESPONSE)
413 return 0;
414
415 /* only one valid case where server sends us request */
416 if (smb->Command == SMB_COM_LOCKING_ANDX)
417 return 0;
418
419 cERROR(1, "Server sent request, not response. mid=%u", smb->Mid);
407 return 1; 420 return 1;
408} 421}
409 422
@@ -448,7 +461,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
448 return 1; 461 return 1;
449 } 462 }
450 463
451 if (checkSMBhdr(smb, mid)) 464 if (check_smb_hdr(smb, mid))
452 return 1; 465 return 1;
453 clc_len = smbCalcSize_LE(smb); 466 clc_len = smbCalcSize_LE(smb);
454 467
@@ -465,25 +478,26 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
465 if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) 478 if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
466 return 0; /* bcc wrapped */ 479 return 0; /* bcc wrapped */
467 } 480 }
468 cFYI(1, "Calculated size %d vs length %d mismatch for mid %d", 481 cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u",
469 clc_len, 4 + len, smb->Mid); 482 clc_len, 4 + len, smb->Mid);
470 /* Windows XP can return a few bytes too much, presumably 483
471 an illegal pad, at the end of byte range lock responses 484 if (4 + len < clc_len) {
472 so we allow for that three byte pad, as long as actual 485 cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u",
473 received length is as long or longer than calculated length */
474 /* We have now had to extend this more, since there is a
475 case in which it needs to be bigger still to handle a
476 malformed response to transact2 findfirst from WinXP when
477 access denied is returned and thus bcc and wct are zero
478 but server says length is 0x21 bytes too long as if the server
479 forget to reset the smb rfc1001 length when it reset the
480 wct and bcc to minimum size and drop the t2 parms and data */
481 if ((4+len > clc_len) && (len <= clc_len + 512))
482 return 0;
483 else {
484 cERROR(1, "RFC1001 size %d bigger than SMB for Mid=%d",
485 len, smb->Mid); 486 len, smb->Mid);
486 return 1; 487 return 1;
488 } else if (len > clc_len + 512) {
489 /*
490 * Some servers (Windows XP in particular) send more
491 * data than the lengths in the SMB packet would
492 * indicate on certain calls (byte range locks and
493 * trans2 find first calls in particular). While the
494 * client can handle such a frame by ignoring the
495 * trailing data, we choose limit the amount of extra
496 * data to 512 bytes.
497 */
498 cERROR(1, "RFC1001 size %u more than 512 bytes larger "
499 "than SMB for mid=%u", len, smb->Mid);
500 return 1;
487 } 501 }
488 } 502 }
489 return 0; 503 return 0;
@@ -571,7 +585,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
571 pCifsInode = CIFS_I(netfile->dentry->d_inode); 585 pCifsInode = CIFS_I(netfile->dentry->d_inode);
572 586
573 cifs_set_oplock_level(pCifsInode, 587 cifs_set_oplock_level(pCifsInode,
574 pSMB->OplockLevel); 588 pSMB->OplockLevel ? OPLOCK_READ : 0);
575 /* 589 /*
576 * cifs_oplock_break_put() can't be called 590 * cifs_oplock_break_put() can't be called
577 * from here. Get reference after queueing 591 * from here. Get reference after queueing
@@ -637,77 +651,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
637 return; 651 return;
638} 652}
639 653
640/* Convert 16 bit Unicode pathname to wire format from string in current code
641 page. Conversion may involve remapping up the seven characters that are
642 only legal in POSIX-like OS (if they are present in the string). Path
643 names are little endian 16 bit Unicode on the wire */
644int
645cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
646 const struct nls_table *cp, int mapChars)
647{
648 int i, j, charlen;
649 int len_remaining = maxlen;
650 char src_char;
651 __u16 temp;
652
653 if (!mapChars)
654 return cifs_strtoUCS(target, source, PATH_MAX, cp);
655
656 for (i = 0, j = 0; i < maxlen; j++) {
657 src_char = source[i];
658 switch (src_char) {
659 case 0:
660 target[j] = 0;
661 goto ctoUCS_out;
662 case ':':
663 target[j] = cpu_to_le16(UNI_COLON);
664 break;
665 case '*':
666 target[j] = cpu_to_le16(UNI_ASTERIK);
667 break;
668 case '?':
669 target[j] = cpu_to_le16(UNI_QUESTION);
670 break;
671 case '<':
672 target[j] = cpu_to_le16(UNI_LESSTHAN);
673 break;
674 case '>':
675 target[j] = cpu_to_le16(UNI_GRTRTHAN);
676 break;
677 case '|':
678 target[j] = cpu_to_le16(UNI_PIPE);
679 break;
680 /* BB We can not handle remapping slash until
681 all the calls to build_path_from_dentry
682 are modified, as they use slash as separator BB */
683 /* case '\\':
684 target[j] = cpu_to_le16(UNI_SLASH);
685 break;*/
686 default:
687 charlen = cp->char2uni(source+i,
688 len_remaining, &temp);
689 /* if no match, use question mark, which
690 at least in some cases servers as wild card */
691 if (charlen < 1) {
692 target[j] = cpu_to_le16(0x003f);
693 charlen = 1;
694 } else
695 target[j] = cpu_to_le16(temp);
696 len_remaining -= charlen;
697 /* character may take more than one byte in the
698 the source string, but will take exactly two
699 bytes in the target string */
700 i += charlen;
701 continue;
702 }
703 i++; /* move to next char in source string */
704 len_remaining--;
705 }
706
707ctoUCS_out:
708 return i;
709}
710
711void 654void
712cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) 655cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
713{ 656{