aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorSteve French <smfrench@austin.rr.com>2005-04-29 01:41:08 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-29 01:41:08 -0400
commit09d1db5c6131232f764046160c29118cd4e5e646 (patch)
tree198d0b03c0afa7974cd6dcea4e711351f4e056eb /fs/cifs/connect.c
parent966ca9234754ece58870075972ef103e354de075 (diff)
[PATCH] cifs: improve check for search entry going beyond end of SMB transact
Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c62
1 files changed, 39 insertions, 23 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 8a8aa785e7b7..d5d49b584db4 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -157,9 +157,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
157 qhead); 157 qhead);
158 if(mid_entry) { 158 if(mid_entry) {
159 if(mid_entry->midState == MID_REQUEST_SUBMITTED) { 159 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
160 /* Mark other intransit requests as needing retry so 160 /* Mark other intransit requests as needing
161 we do not immediately mark the session bad again 161 retry so we do not immediately mark the
162 (ie after we reconnect below) as they timeout too */ 162 session bad again (ie after we reconnect
163 below) as they timeout too */
163 mid_entry->midState = MID_RETRY_NEEDED; 164 mid_entry->midState = MID_RETRY_NEEDED;
164 } 165 }
165 } 166 }
@@ -278,9 +279,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
278 } else if (length <= 0) { 279 } else if (length <= 0) {
279 if(server->tcpStatus == CifsNew) { 280 if(server->tcpStatus == CifsNew) {
280 cFYI(1,("tcp session abended prematurely (after SMBnegprot)")); 281 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
281 /* some servers kill tcp session rather than returning 282 /* some servers kill the TCP session rather than
282 smb negprot error in which case reconnecting here is 283 returning an SMB negprot error, in which
283 not going to help - return error to mount */ 284 case reconnecting here is not going to help,
285 and so simply return error to mount */
284 break; 286 break;
285 } 287 }
286 if(length == -EINTR) { 288 if(length == -EINTR) {
@@ -296,15 +298,19 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
296 pdu_length = ntohl(smb_buffer->smb_buf_length); 298 pdu_length = ntohl(smb_buffer->smb_buf_length);
297 /* Only read pdu_length after below checks for too short (due 299 /* Only read pdu_length after below checks for too short (due
298 to e.g. int overflow) and too long ie beyond end of buf */ 300 to e.g. int overflow) and too long ie beyond end of buf */
299 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); 301 cFYI(1,("rfc1002 length(big endian)0x%x)",
302 pdu_length+4));
300 303
301 temp = (char *) smb_buffer; 304 temp = (char *) smb_buffer;
302 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { 305 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
303 cFYI(0,("Received 4 byte keep alive packet")); 306 cFYI(0,("Received 4 byte keep alive packet"));
304 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) { 307 } else if (temp[0] ==
308 (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
305 cFYI(1,("Good RFC 1002 session rsp")); 309 cFYI(1,("Good RFC 1002 session rsp"));
306 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { 310 } else if (temp[0] ==
307 /* we get this from Windows 98 instead of error on SMB negprot response */ 311 (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
312 /* we get this from Windows 98 instead of
313 an error on SMB negprot response */
308 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); 314 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
309 if(server->tcpStatus == CifsNew) { 315 if(server->tcpStatus == CifsNew) {
310 /* if nack on negprot (rather than 316 /* if nack on negprot (rather than
@@ -320,7 +326,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
320 connected to port 139 (the NACK is 326 connected to port 139 (the NACK is
321 since we do not begin with RFC1001 327 since we do not begin with RFC1001
322 session initialize frame) */ 328 session initialize frame) */
323 server->addr.sockAddr.sin_port = htons(CIFS_PORT); 329 server->addr.sockAddr.sin_port =
330 htons(CIFS_PORT);
324 cifs_reconnect(server); 331 cifs_reconnect(server);
325 csocket = server->ssocket; 332 csocket = server->ssocket;
326 wake_up(&server->response_q); 333 wake_up(&server->response_q);
@@ -333,8 +340,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
333 csocket = server->ssocket; 340 csocket = server->ssocket;
334 continue; 341 continue;
335 } else { 342 } else {
336 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) 343 if((pdu_length > CIFSMaxBufSize +
337 || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { 344 MAX_CIFS_HDR_SIZE - 4) ||
345 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
338 cERROR(1, 346 cERROR(1,
339 ("Invalid size SMB length %d and pdu_length %d", 347 ("Invalid size SMB length %d and pdu_length %d",
340 length, pdu_length+4)); 348 length, pdu_length+4));
@@ -377,6 +385,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
377 continue; 385 continue;
378 } 386 }
379 387
388 /* BB FIXME - add checkTrans2SMBSecondary() */
389
380 task_to_wake = NULL; 390 task_to_wake = NULL;
381 spin_lock(&GlobalMid_Lock); 391 spin_lock(&GlobalMid_Lock);
382 list_for_each(tmp, &server->pending_mid_q) { 392 list_for_each(tmp, &server->pending_mid_q) {
@@ -408,7 +418,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
408 bigbuf = NULL; 418 bigbuf = NULL;
409 else 419 else
410 smallbuf = NULL; 420 smallbuf = NULL;
411 smb_buffer = NULL; /* will be freed by users thread after he is done */ 421 smb_buffer = NULL; /* will be freed by users thread after he is done */
412 wake_up_process(task_to_wake); 422 wake_up_process(task_to_wake);
413 } else if (is_valid_oplock_break(smb_buffer) == FALSE) { 423 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
414 cERROR(1, ("No task to wake, unknown frame rcvd!")); 424 cERROR(1, ("No task to wake, unknown frame rcvd!"));
@@ -432,7 +442,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
432 spin_unlock(&GlobalMid_Lock); 442 spin_unlock(&GlobalMid_Lock);
433 /* Although there should not be any requests blocked on 443 /* Although there should not be any requests blocked on
434 this queue it can not hurt to be paranoid and try to wake up requests 444 this queue it can not hurt to be paranoid and try to wake up requests
435 that may haven been blocked when more than 50 at time were on the wire 445 that may haven been blocked when more than 50 at time were on the wire
436 to the same server - they now will see the session is in exit state 446 to the same server - they now will see the session is in exit state
437 and get out of SendReceive. */ 447 and get out of SendReceive. */
438 wake_up_all(&server->request_q); 448 wake_up_all(&server->request_q);
@@ -451,7 +461,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
451 461
452 read_lock(&GlobalSMBSeslock); 462 read_lock(&GlobalSMBSeslock);
453 if (list_empty(&server->pending_mid_q)) { 463 if (list_empty(&server->pending_mid_q)) {
454 /* loop through server session structures attached to this and mark them dead */ 464 /* loop through server session structures attached to this and
465 mark them dead */
455 list_for_each(tmp, &GlobalSMBSessionList) { 466 list_for_each(tmp, &GlobalSMBSessionList) {
456 ses = 467 ses =
457 list_entry(tmp, struct cifsSesInfo, 468 list_entry(tmp, struct cifsSesInfo,
@@ -468,7 +479,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
468 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 479 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
469 if (mid_entry->midState == MID_REQUEST_SUBMITTED) { 480 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
470 cFYI(1, 481 cFYI(1,
471 (" Clearing Mid 0x%x - waking up ",mid_entry->mid)); 482 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
472 task_to_wake = mid_entry->tsk; 483 task_to_wake = mid_entry->tsk;
473 if(task_to_wake) { 484 if(task_to_wake) {
474 wake_up_process(task_to_wake); 485 wake_up_process(task_to_wake);
@@ -521,7 +532,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
521 /* does not have to be a perfect mapping since the field is 532 /* does not have to be a perfect mapping since the field is
522 informational, only used for servers that do not support 533 informational, only used for servers that do not support
523 port 445 and it can be overridden at mount time */ 534 port 445 and it can be overridden at mount time */
524 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]); 535 vol->source_rfc1001_name[i] =
536 toupper(system_utsname.nodename[i]);
525 } 537 }
526 vol->source_rfc1001_name[15] = 0; 538 vol->source_rfc1001_name[15] = 0;
527 539
@@ -596,14 +608,17 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
596 /* NB: password legally can have multiple commas and 608 /* NB: password legally can have multiple commas and
597 the only illegal character in a password is null */ 609 the only illegal character in a password is null */
598 610
599 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) { 611 if ((value[temp_len] == 0) &&
612 (value[temp_len+1] == separator[0])) {
600 /* reinsert comma */ 613 /* reinsert comma */
601 value[temp_len] = separator[0]; 614 value[temp_len] = separator[0];
602 temp_len+=2; /* move after the second comma */ 615 temp_len+=2; /* move after the second comma */
603 while(value[temp_len] != 0) { 616 while(value[temp_len] != 0) {
604 if (value[temp_len] == separator[0]) { 617 if (value[temp_len] == separator[0]) {
605 if (value[temp_len+1] == separator[0]) { 618 if (value[temp_len+1] ==
606 temp_len++; /* skip second comma */ 619 separator[0]) {
620 /* skip second comma */
621 temp_len++;
607 } else { 622 } else {
608 /* single comma indicating start 623 /* single comma indicating start
609 of next parm */ 624 of next parm */
@@ -629,14 +644,15 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
629 } 644 }
630 for(i=0,j=0;i<temp_len;i++,j++) { 645 for(i=0,j=0;i<temp_len;i++,j++) {
631 vol->password[j] = value[i]; 646 vol->password[j] = value[i];
632 if(value[i] == separator[0] && value[i+1] == separator[0]) { 647 if(value[i] == separator[0]
648 && value[i+1] == separator[0]) {
633 /* skip second comma */ 649 /* skip second comma */
634 i++; 650 i++;
635 } 651 }
636 } 652 }
637 vol->password[j] = 0; 653 vol->password[j] = 0;
638 } else { 654 } else {
639 vol->password = kcalloc(1, temp_len + 1, GFP_KERNEL); 655 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
640 if(vol->password == NULL) { 656 if(vol->password == NULL) {
641 printk("CIFS: no memory for pass\n"); 657 printk("CIFS: no memory for pass\n");
642 return 1; 658 return 1;