diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 15:00:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 15:00:58 -0400 |
commit | 2843483d2eb02ad104edbe8b2429fb6a39d25063 (patch) | |
tree | 7a63d1fa408ab50277666b2d73d2553ea4cfc7a7 /fs/cifs/connect.c | |
parent | 26790656d7dc34206f78eeca0f4be5caede788ce (diff) | |
parent | a761ac579b89bc1f00212a42401398108deba65c (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (51 commits)
[CIFS] log better errors on failed mounts
[CIFS] Return better error when server requires signing but client forbids
[CIFS] fix typo
[CIFS] acl support part 4
[CIFS] Fix minor problems noticed by scan
[CIFS] fix bad handling of EAGAIN error on kernel_recvmsg in cifs_demultiplex_thread
[CIFS] build break
[CIFS] endian fixes
[CIFS] endian fixes in new acl code
[CIFS] Fix some endianness problems in new acl code
[CIFS] missing #endif from a previous patch
[CIFS] formatting fixes
[CIFS] Break up unicode_sessetup string functions
[CIFS] parse server_GUID in SPNEGO negProt response
[CIFS]
[CIFS] Fix endian conversion problem in posix mkdir
[CIFS] fix build break when lanman not enabled
[CIFS] remove two sparse warnings
[CIFS] remove compile warnings when debug disabled
[CIFS] CIFS ACL support part 3
...
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 262 |
1 files changed, 139 insertions, 123 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 370866cb3d48..19ee11f7f35a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -124,7 +124,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
124 | struct mid_q_entry *mid_entry; | 124 | struct mid_q_entry *mid_entry; |
125 | 125 | ||
126 | spin_lock(&GlobalMid_Lock); | 126 | spin_lock(&GlobalMid_Lock); |
127 | if ( kthread_should_stop() ) { | 127 | if (kthread_should_stop()) { |
128 | /* the demux thread will exit normally | 128 | /* the demux thread will exit normally |
129 | next time through the loop */ | 129 | next time through the loop */ |
130 | spin_unlock(&GlobalMid_Lock); | 130 | spin_unlock(&GlobalMid_Lock); |
@@ -151,9 +151,8 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
151 | } | 151 | } |
152 | list_for_each(tmp, &GlobalTreeConnectionList) { | 152 | list_for_each(tmp, &GlobalTreeConnectionList) { |
153 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | 153 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); |
154 | if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) { | 154 | if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) |
155 | tcon->tidStatus = CifsNeedReconnect; | 155 | tcon->tidStatus = CifsNeedReconnect; |
156 | } | ||
157 | } | 156 | } |
158 | read_unlock(&GlobalSMBSeslock); | 157 | read_unlock(&GlobalSMBSeslock); |
159 | /* do not want to be sending data on a socket we are freeing */ | 158 | /* do not want to be sending data on a socket we are freeing */ |
@@ -187,7 +186,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
187 | spin_unlock(&GlobalMid_Lock); | 186 | spin_unlock(&GlobalMid_Lock); |
188 | up(&server->tcpSem); | 187 | up(&server->tcpSem); |
189 | 188 | ||
190 | while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { | 189 | while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { |
191 | try_to_freeze(); | 190 | try_to_freeze(); |
192 | if (server->protocolType == IPV6) { | 191 | if (server->protocolType == IPV6) { |
193 | rc = ipv6_connect(&server->addr.sockAddr6, | 192 | rc = ipv6_connect(&server->addr.sockAddr6, |
@@ -204,7 +203,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
204 | } else { | 203 | } else { |
205 | atomic_inc(&tcpSesReconnectCount); | 204 | atomic_inc(&tcpSesReconnectCount); |
206 | spin_lock(&GlobalMid_Lock); | 205 | spin_lock(&GlobalMid_Lock); |
207 | if ( !kthread_should_stop() ) | 206 | if (!kthread_should_stop()) |
208 | server->tcpStatus = CifsGood; | 207 | server->tcpStatus = CifsGood; |
209 | server->sequence_number = 0; | 208 | server->sequence_number = 0; |
210 | spin_unlock(&GlobalMid_Lock); | 209 | spin_unlock(&GlobalMid_Lock); |
@@ -358,11 +357,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
358 | length = tcpSesAllocCount.counter; | 357 | length = tcpSesAllocCount.counter; |
359 | write_unlock(&GlobalSMBSeslock); | 358 | write_unlock(&GlobalSMBSeslock); |
360 | complete(&cifsd_complete); | 359 | complete(&cifsd_complete); |
361 | if (length > 1) { | 360 | if (length > 1) |
362 | mempool_resize(cifs_req_poolp, | 361 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
363 | length + cifs_min_rcv, | 362 | GFP_KERNEL); |
364 | GFP_KERNEL); | ||
365 | } | ||
366 | 363 | ||
367 | set_freezable(); | 364 | set_freezable(); |
368 | while (!kthread_should_stop()) { | 365 | while (!kthread_should_stop()) { |
@@ -378,7 +375,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
378 | } | 375 | } |
379 | } else if (isLargeBuf) { | 376 | } else if (isLargeBuf) { |
380 | /* we are reusing a dirty large buf, clear its start */ | 377 | /* we are reusing a dirty large buf, clear its start */ |
381 | memset(bigbuf, 0, sizeof (struct smb_hdr)); | 378 | memset(bigbuf, 0, sizeof(struct smb_hdr)); |
382 | } | 379 | } |
383 | 380 | ||
384 | if (smallbuf == NULL) { | 381 | if (smallbuf == NULL) { |
@@ -391,7 +388,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
391 | } | 388 | } |
392 | /* beginning of smb buffer is cleared in our buf_get */ | 389 | /* beginning of smb buffer is cleared in our buf_get */ |
393 | } else /* if existing small buf clear beginning */ | 390 | } else /* if existing small buf clear beginning */ |
394 | memset(smallbuf, 0, sizeof (struct smb_hdr)); | 391 | memset(smallbuf, 0, sizeof(struct smb_hdr)); |
395 | 392 | ||
396 | isLargeBuf = FALSE; | 393 | isLargeBuf = FALSE; |
397 | isMultiRsp = FALSE; | 394 | isMultiRsp = FALSE; |
@@ -400,11 +397,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
400 | iov.iov_len = 4; | 397 | iov.iov_len = 4; |
401 | smb_msg.msg_control = NULL; | 398 | smb_msg.msg_control = NULL; |
402 | smb_msg.msg_controllen = 0; | 399 | smb_msg.msg_controllen = 0; |
400 | pdu_length = 4; /* enough to get RFC1001 header */ | ||
401 | incomplete_rcv: | ||
403 | length = | 402 | length = |
404 | kernel_recvmsg(csocket, &smb_msg, | 403 | kernel_recvmsg(csocket, &smb_msg, |
405 | &iov, 1, 4, 0 /* BB see socket.h flags */); | 404 | &iov, 1, pdu_length, 0 /* BB other flags? */); |
406 | 405 | ||
407 | if ( kthread_should_stop() ) { | 406 | if (kthread_should_stop()) { |
408 | break; | 407 | break; |
409 | } else if (server->tcpStatus == CifsNeedReconnect) { | 408 | } else if (server->tcpStatus == CifsNeedReconnect) { |
410 | cFYI(1, ("Reconnect after server stopped responding")); | 409 | cFYI(1, ("Reconnect after server stopped responding")); |
@@ -416,7 +415,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
416 | msleep(1); /* minimum sleep to prevent looping | 415 | msleep(1); /* minimum sleep to prevent looping |
417 | allowing socket to clear and app threads to set | 416 | allowing socket to clear and app threads to set |
418 | tcpStatus CifsNeedReconnect if server hung */ | 417 | tcpStatus CifsNeedReconnect if server hung */ |
419 | continue; | 418 | if (pdu_length < 4) |
419 | goto incomplete_rcv; | ||
420 | else | ||
421 | continue; | ||
420 | } else if (length <= 0) { | 422 | } else if (length <= 0) { |
421 | if (server->tcpStatus == CifsNew) { | 423 | if (server->tcpStatus == CifsNew) { |
422 | cFYI(1, ("tcp session abend after SMBnegprot")); | 424 | cFYI(1, ("tcp session abend after SMBnegprot")); |
@@ -437,13 +439,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
437 | wake_up(&server->response_q); | 439 | wake_up(&server->response_q); |
438 | continue; | 440 | continue; |
439 | } else if (length < 4) { | 441 | } else if (length < 4) { |
440 | cFYI(1, | 442 | cFYI(1, ("less than four bytes received (%d bytes)", |
441 | ("Frame under four bytes received (%d bytes long)", | ||
442 | length)); | 443 | length)); |
443 | cifs_reconnect(server); | 444 | pdu_length -= length; |
444 | csocket = server->ssocket; | 445 | msleep(1); |
445 | wake_up(&server->response_q); | 446 | goto incomplete_rcv; |
446 | continue; | ||
447 | } | 447 | } |
448 | 448 | ||
449 | /* The right amount was read from socket - 4 bytes */ | 449 | /* The right amount was read from socket - 4 bytes */ |
@@ -504,7 +504,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
504 | 504 | ||
505 | /* else we have an SMB response */ | 505 | /* else we have an SMB response */ |
506 | if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || | 506 | if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || |
507 | (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { | 507 | (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) { |
508 | cERROR(1, ("Invalid size SMB length %d pdu_length %d", | 508 | cERROR(1, ("Invalid size SMB length %d pdu_length %d", |
509 | length, pdu_length+4)); | 509 | length, pdu_length+4)); |
510 | cifs_reconnect(server); | 510 | cifs_reconnect(server); |
@@ -528,7 +528,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
528 | total_read += length) { | 528 | total_read += length) { |
529 | length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, | 529 | length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, |
530 | pdu_length - total_read, 0); | 530 | pdu_length - total_read, 0); |
531 | if ( kthread_should_stop() || | 531 | if (kthread_should_stop() || |
532 | (length == -EINTR)) { | 532 | (length == -EINTR)) { |
533 | /* then will exit */ | 533 | /* then will exit */ |
534 | reconnect = 2; | 534 | reconnect = 2; |
@@ -546,6 +546,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
546 | allowing socket to clear and app | 546 | allowing socket to clear and app |
547 | threads to set tcpStatus | 547 | threads to set tcpStatus |
548 | CifsNeedReconnect if server hung*/ | 548 | CifsNeedReconnect if server hung*/ |
549 | length = 0; | ||
549 | continue; | 550 | continue; |
550 | } else if (length <= 0) { | 551 | } else if (length <= 0) { |
551 | cERROR(1, ("Received no data, expecting %d", | 552 | cERROR(1, ("Received no data, expecting %d", |
@@ -631,9 +632,9 @@ multi_t2_fnd: | |||
631 | /* Was previous buf put in mpx struct for multi-rsp? */ | 632 | /* Was previous buf put in mpx struct for multi-rsp? */ |
632 | if (!isMultiRsp) { | 633 | if (!isMultiRsp) { |
633 | /* smb buffer will be freed by user thread */ | 634 | /* smb buffer will be freed by user thread */ |
634 | if (isLargeBuf) { | 635 | if (isLargeBuf) |
635 | bigbuf = NULL; | 636 | bigbuf = NULL; |
636 | } else | 637 | else |
637 | smallbuf = NULL; | 638 | smallbuf = NULL; |
638 | } | 639 | } |
639 | wake_up_process(task_to_wake); | 640 | wake_up_process(task_to_wake); |
@@ -676,9 +677,8 @@ multi_t2_fnd: | |||
676 | server->ssocket = NULL; | 677 | server->ssocket = NULL; |
677 | } | 678 | } |
678 | /* buffer usuallly freed in free_mid - need to free it here on exit */ | 679 | /* buffer usuallly freed in free_mid - need to free it here on exit */ |
679 | if (bigbuf != NULL) | 680 | cifs_buf_release(bigbuf); |
680 | cifs_buf_release(bigbuf); | 681 | if (smallbuf) /* no sense logging a debug message if NULL */ |
681 | if (smallbuf != NULL) | ||
682 | cifs_small_buf_release(smallbuf); | 682 | cifs_small_buf_release(smallbuf); |
683 | 683 | ||
684 | read_lock(&GlobalSMBSeslock); | 684 | read_lock(&GlobalSMBSeslock); |
@@ -702,9 +702,8 @@ multi_t2_fnd: | |||
702 | list_for_each(tmp, &GlobalSMBSessionList) { | 702 | list_for_each(tmp, &GlobalSMBSessionList) { |
703 | ses = list_entry(tmp, struct cifsSesInfo, | 703 | ses = list_entry(tmp, struct cifsSesInfo, |
704 | cifsSessionList); | 704 | cifsSessionList); |
705 | if (ses->server == server) { | 705 | if (ses->server == server) |
706 | ses->status = CifsExiting; | 706 | ses->status = CifsExiting; |
707 | } | ||
708 | } | 707 | } |
709 | 708 | ||
710 | spin_lock(&GlobalMid_Lock); | 709 | spin_lock(&GlobalMid_Lock); |
@@ -714,9 +713,8 @@ multi_t2_fnd: | |||
714 | cFYI(1, ("Clearing Mid 0x%x - waking up ", | 713 | cFYI(1, ("Clearing Mid 0x%x - waking up ", |
715 | mid_entry->mid)); | 714 | mid_entry->mid)); |
716 | task_to_wake = mid_entry->tsk; | 715 | task_to_wake = mid_entry->tsk; |
717 | if (task_to_wake) { | 716 | if (task_to_wake) |
718 | wake_up_process(task_to_wake); | 717 | wake_up_process(task_to_wake); |
719 | } | ||
720 | } | 718 | } |
721 | } | 719 | } |
722 | spin_unlock(&GlobalMid_Lock); | 720 | spin_unlock(&GlobalMid_Lock); |
@@ -749,18 +747,15 @@ multi_t2_fnd: | |||
749 | list_for_each(tmp, &GlobalSMBSessionList) { | 747 | list_for_each(tmp, &GlobalSMBSessionList) { |
750 | ses = list_entry(tmp, struct cifsSesInfo, | 748 | ses = list_entry(tmp, struct cifsSesInfo, |
751 | cifsSessionList); | 749 | cifsSessionList); |
752 | if (ses->server == server) { | 750 | if (ses->server == server) |
753 | ses->server = NULL; | 751 | ses->server = NULL; |
754 | } | ||
755 | } | 752 | } |
756 | write_unlock(&GlobalSMBSeslock); | 753 | write_unlock(&GlobalSMBSeslock); |
757 | 754 | ||
758 | kfree(server); | 755 | kfree(server); |
759 | if (length > 0) { | 756 | if (length > 0) |
760 | mempool_resize(cifs_req_poolp, | 757 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
761 | length + cifs_min_rcv, | 758 | GFP_KERNEL); |
762 | GFP_KERNEL); | ||
763 | } | ||
764 | 759 | ||
765 | return 0; | 760 | return 0; |
766 | } | 761 | } |
@@ -1477,7 +1472,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1477 | if (psin_server->sin_port) { /* user overrode default port */ | 1472 | if (psin_server->sin_port) { /* user overrode default port */ |
1478 | rc = (*csocket)->ops->connect(*csocket, | 1473 | rc = (*csocket)->ops->connect(*csocket, |
1479 | (struct sockaddr *) psin_server, | 1474 | (struct sockaddr *) psin_server, |
1480 | sizeof (struct sockaddr_in), 0); | 1475 | sizeof(struct sockaddr_in), 0); |
1481 | if (rc >= 0) | 1476 | if (rc >= 0) |
1482 | connected = 1; | 1477 | connected = 1; |
1483 | } | 1478 | } |
@@ -1493,7 +1488,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1493 | 1488 | ||
1494 | rc = (*csocket)->ops->connect(*csocket, | 1489 | rc = (*csocket)->ops->connect(*csocket, |
1495 | (struct sockaddr *) psin_server, | 1490 | (struct sockaddr *) psin_server, |
1496 | sizeof (struct sockaddr_in), 0); | 1491 | sizeof(struct sockaddr_in), 0); |
1497 | if (rc >= 0) | 1492 | if (rc >= 0) |
1498 | connected = 1; | 1493 | connected = 1; |
1499 | } | 1494 | } |
@@ -1502,7 +1497,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1502 | psin_server->sin_port = htons(RFC1001_PORT); | 1497 | psin_server->sin_port = htons(RFC1001_PORT); |
1503 | rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) | 1498 | rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) |
1504 | psin_server, | 1499 | psin_server, |
1505 | sizeof (struct sockaddr_in), 0); | 1500 | sizeof(struct sockaddr_in), 0); |
1506 | if (rc >= 0) | 1501 | if (rc >= 0) |
1507 | connected = 1; | 1502 | connected = 1; |
1508 | } | 1503 | } |
@@ -1610,7 +1605,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
1610 | if (psin_server->sin6_port) { /* user overrode default port */ | 1605 | if (psin_server->sin6_port) { /* user overrode default port */ |
1611 | rc = (*csocket)->ops->connect(*csocket, | 1606 | rc = (*csocket)->ops->connect(*csocket, |
1612 | (struct sockaddr *) psin_server, | 1607 | (struct sockaddr *) psin_server, |
1613 | sizeof (struct sockaddr_in6), 0); | 1608 | sizeof(struct sockaddr_in6), 0); |
1614 | if (rc >= 0) | 1609 | if (rc >= 0) |
1615 | connected = 1; | 1610 | connected = 1; |
1616 | } | 1611 | } |
@@ -1626,7 +1621,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
1626 | 1621 | ||
1627 | rc = (*csocket)->ops->connect(*csocket, | 1622 | rc = (*csocket)->ops->connect(*csocket, |
1628 | (struct sockaddr *) psin_server, | 1623 | (struct sockaddr *) psin_server, |
1629 | sizeof (struct sockaddr_in6), 0); | 1624 | sizeof(struct sockaddr_in6), 0); |
1630 | if (rc >= 0) | 1625 | if (rc >= 0) |
1631 | connected = 1; | 1626 | connected = 1; |
1632 | } | 1627 | } |
@@ -1634,7 +1629,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
1634 | if (!connected) { | 1629 | if (!connected) { |
1635 | psin_server->sin6_port = htons(RFC1001_PORT); | 1630 | psin_server->sin6_port = htons(RFC1001_PORT); |
1636 | rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) | 1631 | rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) |
1637 | psin_server, sizeof (struct sockaddr_in6), 0); | 1632 | psin_server, sizeof(struct sockaddr_in6), 0); |
1638 | if (rc >= 0) | 1633 | if (rc >= 0) |
1639 | connected = 1; | 1634 | connected = 1; |
1640 | } | 1635 | } |
@@ -1750,7 +1745,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, | |||
1750 | cFYI(1, ("very large write cap")); | 1745 | cFYI(1, ("very large write cap")); |
1751 | #endif /* CIFS_DEBUG2 */ | 1746 | #endif /* CIFS_DEBUG2 */ |
1752 | if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { | 1747 | if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { |
1753 | cFYI(1, ("setting capabilities failed")); | 1748 | if (vol_info == NULL) { |
1749 | cFYI(1, ("resetting capabilities failed")); | ||
1750 | } else | ||
1751 | cERROR(1, ("Negotiating Unix capabilities " | ||
1752 | "with the server failed. Consider " | ||
1753 | "mounting with the Unix Extensions\n" | ||
1754 | "disabled, if problems are found, " | ||
1755 | "by specifying the nounix mount " | ||
1756 | "option.")); | ||
1757 | |||
1754 | } | 1758 | } |
1755 | } | 1759 | } |
1756 | } | 1760 | } |
@@ -1909,8 +1913,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1909 | return rc; | 1913 | return rc; |
1910 | } | 1914 | } |
1911 | 1915 | ||
1912 | srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL); | 1916 | srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL); |
1913 | if (srvTcp == NULL) { | 1917 | if (!srvTcp) { |
1914 | rc = -ENOMEM; | 1918 | rc = -ENOMEM; |
1915 | sock_release(csocket); | 1919 | sock_release(csocket); |
1916 | kfree(volume_info.UNC); | 1920 | kfree(volume_info.UNC); |
@@ -1919,9 +1923,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1919 | FreeXid(xid); | 1923 | FreeXid(xid); |
1920 | return rc; | 1924 | return rc; |
1921 | } else { | 1925 | } else { |
1922 | memset(srvTcp, 0, sizeof (struct TCP_Server_Info)); | ||
1923 | memcpy(&srvTcp->addr.sockAddr, &sin_server, | 1926 | memcpy(&srvTcp->addr.sockAddr, &sin_server, |
1924 | sizeof (struct sockaddr_in)); | 1927 | sizeof(struct sockaddr_in)); |
1925 | atomic_set(&srvTcp->inFlight, 0); | 1928 | atomic_set(&srvTcp->inFlight, 0); |
1926 | /* BB Add code for ipv6 case too */ | 1929 | /* BB Add code for ipv6 case too */ |
1927 | srvTcp->ssocket = csocket; | 1930 | srvTcp->ssocket = csocket; |
@@ -2173,8 +2176,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2173 | if (tsk) | 2176 | if (tsk) |
2174 | kthread_stop(tsk); | 2177 | kthread_stop(tsk); |
2175 | } | 2178 | } |
2176 | } else | 2179 | } else { |
2177 | cFYI(1, ("No session or bad tcon")); | 2180 | cFYI(1, ("No session or bad tcon")); |
2181 | if ((pSesInfo->server) && | ||
2182 | (pSesInfo->server->tsk)) { | ||
2183 | struct task_struct *tsk; | ||
2184 | force_sig(SIGKILL, | ||
2185 | pSesInfo->server->tsk); | ||
2186 | tsk = pSesInfo->server->tsk; | ||
2187 | if (tsk) | ||
2188 | kthread_stop(tsk); | ||
2189 | } | ||
2190 | } | ||
2178 | sesInfoFree(pSesInfo); | 2191 | sesInfoFree(pSesInfo); |
2179 | /* pSesInfo = NULL; */ | 2192 | /* pSesInfo = NULL; */ |
2180 | } | 2193 | } |
@@ -2185,8 +2198,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2185 | tcon->ses = pSesInfo; | 2198 | tcon->ses = pSesInfo; |
2186 | 2199 | ||
2187 | /* do not care if following two calls succeed - informational */ | 2200 | /* do not care if following two calls succeed - informational */ |
2188 | CIFSSMBQFSDeviceInfo(xid, tcon); | 2201 | if (!tcon->ipc) { |
2189 | CIFSSMBQFSAttributeInfo(xid, tcon); | 2202 | CIFSSMBQFSDeviceInfo(xid, tcon); |
2203 | CIFSSMBQFSAttributeInfo(xid, tcon); | ||
2204 | } | ||
2190 | 2205 | ||
2191 | /* tell server which Unix caps we support */ | 2206 | /* tell server which Unix caps we support */ |
2192 | if (tcon->ses->capabilities & CAP_UNIX) | 2207 | if (tcon->ses->capabilities & CAP_UNIX) |
@@ -2526,8 +2541,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2526 | sesssetup_nomem: /* do not return an error on nomem for the info strings, | 2541 | sesssetup_nomem: /* do not return an error on nomem for the info strings, |
2527 | since that could make reconnection harder, and | 2542 | since that could make reconnection harder, and |
2528 | reconnection might be needed to free memory */ | 2543 | reconnection might be needed to free memory */ |
2529 | if (smb_buffer) | 2544 | cifs_buf_release(smb_buffer); |
2530 | cifs_buf_release(smb_buffer); | ||
2531 | 2545 | ||
2532 | return rc; | 2546 | return rc; |
2533 | } | 2547 | } |
@@ -2547,7 +2561,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2547 | int remaining_words = 0; | 2561 | int remaining_words = 0; |
2548 | int bytes_returned = 0; | 2562 | int bytes_returned = 0; |
2549 | int len; | 2563 | int len; |
2550 | int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE); | 2564 | int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE); |
2551 | PNEGOTIATE_MESSAGE SecurityBlob; | 2565 | PNEGOTIATE_MESSAGE SecurityBlob; |
2552 | PCHALLENGE_MESSAGE SecurityBlob2; | 2566 | PCHALLENGE_MESSAGE SecurityBlob2; |
2553 | __u32 negotiate_flags, capabilities; | 2567 | __u32 negotiate_flags, capabilities; |
@@ -2865,15 +2879,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2865 | rc = -EIO; | 2879 | rc = -EIO; |
2866 | } | 2880 | } |
2867 | 2881 | ||
2868 | if (smb_buffer) | 2882 | cifs_buf_release(smb_buffer); |
2869 | cifs_buf_release(smb_buffer); | ||
2870 | 2883 | ||
2871 | return rc; | 2884 | return rc; |
2872 | } | 2885 | } |
2873 | static int | 2886 | static int |
2874 | CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | 2887 | CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, |
2875 | char *ntlm_session_key, int ntlmv2_flag, | 2888 | char *ntlm_session_key, int ntlmv2_flag, |
2876 | const struct nls_table *nls_codepage) | 2889 | const struct nls_table *nls_codepage) |
2877 | { | 2890 | { |
2878 | struct smb_hdr *smb_buffer; | 2891 | struct smb_hdr *smb_buffer; |
2879 | struct smb_hdr *smb_buffer_response; | 2892 | struct smb_hdr *smb_buffer_response; |
@@ -2886,7 +2899,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2886 | int remaining_words = 0; | 2899 | int remaining_words = 0; |
2887 | int bytes_returned = 0; | 2900 | int bytes_returned = 0; |
2888 | int len; | 2901 | int len; |
2889 | int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE); | 2902 | int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE); |
2890 | PAUTHENTICATE_MESSAGE SecurityBlob; | 2903 | PAUTHENTICATE_MESSAGE SecurityBlob; |
2891 | __u32 negotiate_flags, capabilities; | 2904 | __u32 negotiate_flags, capabilities; |
2892 | __u16 count; | 2905 | __u16 count; |
@@ -2901,8 +2914,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2901 | return -ENOMEM; | 2914 | return -ENOMEM; |
2902 | } | 2915 | } |
2903 | smb_buffer_response = smb_buffer; | 2916 | smb_buffer_response = smb_buffer; |
2904 | pSMB = (SESSION_SETUP_ANDX *) smb_buffer; | 2917 | pSMB = (SESSION_SETUP_ANDX *)smb_buffer; |
2905 | pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; | 2918 | pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response; |
2906 | 2919 | ||
2907 | /* send SMBsessionSetup here */ | 2920 | /* send SMBsessionSetup here */ |
2908 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2921 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
@@ -2921,7 +2934,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2921 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 2934 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
2922 | 2935 | ||
2923 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | | 2936 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | |
2924 | CAP_EXTENDED_SECURITY; | 2937 | CAP_EXTENDED_SECURITY; |
2925 | if (ses->capabilities & CAP_UNICODE) { | 2938 | if (ses->capabilities & CAP_UNICODE) { |
2926 | smb_buffer->Flags2 |= SMBFLG2_UNICODE; | 2939 | smb_buffer->Flags2 |= SMBFLG2_UNICODE; |
2927 | capabilities |= CAP_UNICODE; | 2940 | capabilities |= CAP_UNICODE; |
@@ -2936,15 +2949,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2936 | } | 2949 | } |
2937 | pSMB->req.Capabilities = cpu_to_le32(capabilities); | 2950 | pSMB->req.Capabilities = cpu_to_le32(capabilities); |
2938 | 2951 | ||
2939 | bcc_ptr = (char *) &pSMB->req.SecurityBlob; | 2952 | bcc_ptr = (char *)&pSMB->req.SecurityBlob; |
2940 | SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr; | 2953 | SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr; |
2941 | strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); | 2954 | strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); |
2942 | SecurityBlob->MessageType = NtLmAuthenticate; | 2955 | SecurityBlob->MessageType = NtLmAuthenticate; |
2943 | bcc_ptr += SecurityBlobLength; | 2956 | bcc_ptr += SecurityBlobLength; |
2944 | negotiate_flags = | 2957 | negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | |
2945 | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | | 2958 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | |
2946 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | | 2959 | 0x80000000 | NTLMSSP_NEGOTIATE_128; |
2947 | 0x80000000 | NTLMSSP_NEGOTIATE_128; | ||
2948 | if (sign_CIFS_PDUs) | 2960 | if (sign_CIFS_PDUs) |
2949 | negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; | 2961 | negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; |
2950 | if (ntlmv2_flag) | 2962 | if (ntlmv2_flag) |
@@ -2979,36 +2991,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2979 | SecurityBlob->DomainName.Length = 0; | 2991 | SecurityBlob->DomainName.Length = 0; |
2980 | SecurityBlob->DomainName.MaximumLength = 0; | 2992 | SecurityBlob->DomainName.MaximumLength = 0; |
2981 | } else { | 2993 | } else { |
2982 | __u16 len = | 2994 | __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, |
2983 | cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, | ||
2984 | nls_codepage); | 2995 | nls_codepage); |
2985 | len *= 2; | 2996 | ln *= 2; |
2986 | SecurityBlob->DomainName.MaximumLength = | 2997 | SecurityBlob->DomainName.MaximumLength = |
2987 | cpu_to_le16(len); | 2998 | cpu_to_le16(ln); |
2988 | SecurityBlob->DomainName.Buffer = | 2999 | SecurityBlob->DomainName.Buffer = |
2989 | cpu_to_le32(SecurityBlobLength); | 3000 | cpu_to_le32(SecurityBlobLength); |
2990 | bcc_ptr += len; | 3001 | bcc_ptr += ln; |
2991 | SecurityBlobLength += len; | 3002 | SecurityBlobLength += ln; |
2992 | SecurityBlob->DomainName.Length = | 3003 | SecurityBlob->DomainName.Length = cpu_to_le16(ln); |
2993 | cpu_to_le16(len); | ||
2994 | } | 3004 | } |
2995 | if (user == NULL) { | 3005 | if (user == NULL) { |
2996 | SecurityBlob->UserName.Buffer = 0; | 3006 | SecurityBlob->UserName.Buffer = 0; |
2997 | SecurityBlob->UserName.Length = 0; | 3007 | SecurityBlob->UserName.Length = 0; |
2998 | SecurityBlob->UserName.MaximumLength = 0; | 3008 | SecurityBlob->UserName.MaximumLength = 0; |
2999 | } else { | 3009 | } else { |
3000 | __u16 len = | 3010 | __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64, |
3001 | cifs_strtoUCS((__le16 *) bcc_ptr, user, 64, | ||
3002 | nls_codepage); | 3011 | nls_codepage); |
3003 | len *= 2; | 3012 | ln *= 2; |
3004 | SecurityBlob->UserName.MaximumLength = | 3013 | SecurityBlob->UserName.MaximumLength = |
3005 | cpu_to_le16(len); | 3014 | cpu_to_le16(ln); |
3006 | SecurityBlob->UserName.Buffer = | 3015 | SecurityBlob->UserName.Buffer = |
3007 | cpu_to_le32(SecurityBlobLength); | 3016 | cpu_to_le32(SecurityBlobLength); |
3008 | bcc_ptr += len; | 3017 | bcc_ptr += ln; |
3009 | SecurityBlobLength += len; | 3018 | SecurityBlobLength += ln; |
3010 | SecurityBlob->UserName.Length = | 3019 | SecurityBlob->UserName.Length = cpu_to_le16(ln); |
3011 | cpu_to_le16(len); | ||
3012 | } | 3020 | } |
3013 | 3021 | ||
3014 | /* SecurityBlob->WorkstationName.Length = | 3022 | /* SecurityBlob->WorkstationName.Length = |
@@ -3052,33 +3060,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3052 | SecurityBlob->DomainName.Length = 0; | 3060 | SecurityBlob->DomainName.Length = 0; |
3053 | SecurityBlob->DomainName.MaximumLength = 0; | 3061 | SecurityBlob->DomainName.MaximumLength = 0; |
3054 | } else { | 3062 | } else { |
3055 | __u16 len; | 3063 | __u16 ln; |
3056 | negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; | 3064 | negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; |
3057 | strncpy(bcc_ptr, domain, 63); | 3065 | strncpy(bcc_ptr, domain, 63); |
3058 | len = strnlen(domain, 64); | 3066 | ln = strnlen(domain, 64); |
3059 | SecurityBlob->DomainName.MaximumLength = | 3067 | SecurityBlob->DomainName.MaximumLength = |
3060 | cpu_to_le16(len); | 3068 | cpu_to_le16(ln); |
3061 | SecurityBlob->DomainName.Buffer = | 3069 | SecurityBlob->DomainName.Buffer = |
3062 | cpu_to_le32(SecurityBlobLength); | 3070 | cpu_to_le32(SecurityBlobLength); |
3063 | bcc_ptr += len; | 3071 | bcc_ptr += ln; |
3064 | SecurityBlobLength += len; | 3072 | SecurityBlobLength += ln; |
3065 | SecurityBlob->DomainName.Length = cpu_to_le16(len); | 3073 | SecurityBlob->DomainName.Length = cpu_to_le16(ln); |
3066 | } | 3074 | } |
3067 | if (user == NULL) { | 3075 | if (user == NULL) { |
3068 | SecurityBlob->UserName.Buffer = 0; | 3076 | SecurityBlob->UserName.Buffer = 0; |
3069 | SecurityBlob->UserName.Length = 0; | 3077 | SecurityBlob->UserName.Length = 0; |
3070 | SecurityBlob->UserName.MaximumLength = 0; | 3078 | SecurityBlob->UserName.MaximumLength = 0; |
3071 | } else { | 3079 | } else { |
3072 | __u16 len; | 3080 | __u16 ln; |
3073 | strncpy(bcc_ptr, user, 63); | 3081 | strncpy(bcc_ptr, user, 63); |
3074 | len = strnlen(user, 64); | 3082 | ln = strnlen(user, 64); |
3075 | SecurityBlob->UserName.MaximumLength = | 3083 | SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln); |
3076 | cpu_to_le16(len); | ||
3077 | SecurityBlob->UserName.Buffer = | 3084 | SecurityBlob->UserName.Buffer = |
3078 | cpu_to_le32(SecurityBlobLength); | 3085 | cpu_to_le32(SecurityBlobLength); |
3079 | bcc_ptr += len; | 3086 | bcc_ptr += ln; |
3080 | SecurityBlobLength += len; | 3087 | SecurityBlobLength += ln; |
3081 | SecurityBlob->UserName.Length = cpu_to_le16(len); | 3088 | SecurityBlob->UserName.Length = cpu_to_le16(ln); |
3082 | } | 3089 | } |
3083 | /* BB fill in our workstation name if known BB */ | 3090 | /* BB fill in our workstation name if known BB */ |
3084 | 3091 | ||
@@ -3100,12 +3107,11 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3100 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | 3107 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, |
3101 | &bytes_returned, 1); | 3108 | &bytes_returned, 1); |
3102 | if (rc) { | 3109 | if (rc) { |
3103 | /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ | 3110 | /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ |
3104 | } else if ((smb_buffer_response->WordCount == 3) | 3111 | } else if ((smb_buffer_response->WordCount == 3) || |
3105 | || (smb_buffer_response->WordCount == 4)) { | 3112 | (smb_buffer_response->WordCount == 4)) { |
3106 | __u16 action = le16_to_cpu(pSMBr->resp.Action); | 3113 | __u16 action = le16_to_cpu(pSMBr->resp.Action); |
3107 | __u16 blob_len = | 3114 | __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); |
3108 | le16_to_cpu(pSMBr->resp.SecurityBlobLength); | ||
3109 | if (action & GUEST_LOGIN) | 3115 | if (action & GUEST_LOGIN) |
3110 | cFYI(1, (" Guest login")); /* BB Should we set anything | 3116 | cFYI(1, (" Guest login")); /* BB Should we set anything |
3111 | in SesInfo struct ? */ | 3117 | in SesInfo struct ? */ |
@@ -3145,8 +3151,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3145 | } else { | 3151 | } else { |
3146 | remaining_words = BCC(smb_buffer_response) / 2; | 3152 | remaining_words = BCC(smb_buffer_response) / 2; |
3147 | } | 3153 | } |
3148 | len = | 3154 | len = UniStrnlen((wchar_t *) bcc_ptr, |
3149 | UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1); | 3155 | remaining_words - 1); |
3150 | /* We look for obvious messed up bcc or strings in response so we do not go off | 3156 | /* We look for obvious messed up bcc or strings in response so we do not go off |
3151 | the end since (at least) WIN2K and Windows XP have a major bug in not null | 3157 | the end since (at least) WIN2K and Windows XP have a major bug in not null |
3152 | terminating last Unicode string in response */ | 3158 | terminating last Unicode string in response */ |
@@ -3230,7 +3236,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3230 | <= BCC(smb_buffer_response)) { | 3236 | <= BCC(smb_buffer_response)) { |
3231 | if (ses->serverOS) | 3237 | if (ses->serverOS) |
3232 | kfree(ses->serverOS); | 3238 | kfree(ses->serverOS); |
3233 | ses->serverOS = kzalloc(len + 1,GFP_KERNEL); | 3239 | ses->serverOS = kzalloc(len + 1, GFP_KERNEL); |
3234 | strncpy(ses->serverOS,bcc_ptr, len); | 3240 | strncpy(ses->serverOS,bcc_ptr, len); |
3235 | 3241 | ||
3236 | bcc_ptr += len; | 3242 | bcc_ptr += len; |
@@ -3259,28 +3265,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3259 | bcc_ptr[0] = 0; | 3265 | bcc_ptr[0] = 0; |
3260 | bcc_ptr++; | 3266 | bcc_ptr++; |
3261 | } else | 3267 | } else |
3262 | cFYI(1, | 3268 | cFYI(1, ("field of length %d " |
3263 | ("field of length %d " | ||
3264 | "extends beyond end of smb ", | 3269 | "extends beyond end of smb ", |
3265 | len)); | 3270 | len)); |
3266 | } | 3271 | } |
3267 | } else { | 3272 | } else { |
3268 | cERROR(1, | 3273 | cERROR(1, ("Security Blob extends beyond end " |
3269 | (" Security Blob extends beyond end " | ||
3270 | "of SMB")); | 3274 | "of SMB")); |
3271 | } | 3275 | } |
3272 | } else { | 3276 | } else { |
3273 | cERROR(1, ("No session structure passed in.")); | 3277 | cERROR(1, ("No session structure passed in.")); |
3274 | } | 3278 | } |
3275 | } else { | 3279 | } else { |
3276 | cERROR(1, | 3280 | cERROR(1, ("Invalid Word count %d: ", |
3277 | (" Invalid Word count %d: ", | ||
3278 | smb_buffer_response->WordCount)); | 3281 | smb_buffer_response->WordCount)); |
3279 | rc = -EIO; | 3282 | rc = -EIO; |
3280 | } | 3283 | } |
3281 | 3284 | ||
3282 | if (smb_buffer) | 3285 | cifs_buf_release(smb_buffer); |
3283 | cifs_buf_release(smb_buffer); | ||
3284 | 3286 | ||
3285 | return rc; | 3287 | return rc; |
3286 | } | 3288 | } |
@@ -3389,6 +3391,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3389 | bcc_ptr = pByteArea(smb_buffer_response); | 3391 | bcc_ptr = pByteArea(smb_buffer_response); |
3390 | length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); | 3392 | length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); |
3391 | /* skip service field (NB: this field is always ASCII) */ | 3393 | /* skip service field (NB: this field is always ASCII) */ |
3394 | if (length == 3) { | ||
3395 | if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && | ||
3396 | (bcc_ptr[2] == 'C')) { | ||
3397 | cFYI(1, ("IPC connection")); | ||
3398 | tcon->ipc = 1; | ||
3399 | } | ||
3400 | } else if (length == 2) { | ||
3401 | if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) { | ||
3402 | /* the most common case */ | ||
3403 | cFYI(1, ("disk share connection")); | ||
3404 | } | ||
3405 | } | ||
3392 | bcc_ptr += length + 1; | 3406 | bcc_ptr += length + 1; |
3393 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); | 3407 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); |
3394 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { | 3408 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { |
@@ -3399,9 +3413,11 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3399 | kfree(tcon->nativeFileSystem); | 3413 | kfree(tcon->nativeFileSystem); |
3400 | tcon->nativeFileSystem = | 3414 | tcon->nativeFileSystem = |
3401 | kzalloc(length + 2, GFP_KERNEL); | 3415 | kzalloc(length + 2, GFP_KERNEL); |
3402 | cifs_strfromUCS_le(tcon->nativeFileSystem, | 3416 | if (tcon->nativeFileSystem) |
3403 | (__le16 *) bcc_ptr, | 3417 | cifs_strfromUCS_le( |
3404 | length, nls_codepage); | 3418 | tcon->nativeFileSystem, |
3419 | (__le16 *) bcc_ptr, | ||
3420 | length, nls_codepage); | ||
3405 | bcc_ptr += 2 * length; | 3421 | bcc_ptr += 2 * length; |
3406 | bcc_ptr[0] = 0; /* null terminate the string */ | 3422 | bcc_ptr[0] = 0; /* null terminate the string */ |
3407 | bcc_ptr[1] = 0; | 3423 | bcc_ptr[1] = 0; |
@@ -3416,8 +3432,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3416 | kfree(tcon->nativeFileSystem); | 3432 | kfree(tcon->nativeFileSystem); |
3417 | tcon->nativeFileSystem = | 3433 | tcon->nativeFileSystem = |
3418 | kzalloc(length + 1, GFP_KERNEL); | 3434 | kzalloc(length + 1, GFP_KERNEL); |
3419 | strncpy(tcon->nativeFileSystem, bcc_ptr, | 3435 | if (tcon->nativeFileSystem) |
3420 | length); | 3436 | strncpy(tcon->nativeFileSystem, bcc_ptr, |
3437 | length); | ||
3421 | } | 3438 | } |
3422 | /* else do not bother copying these information fields*/ | 3439 | /* else do not bother copying these information fields*/ |
3423 | } | 3440 | } |
@@ -3433,8 +3450,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3433 | ses->ipc_tid = smb_buffer_response->Tid; | 3450 | ses->ipc_tid = smb_buffer_response->Tid; |
3434 | } | 3451 | } |
3435 | 3452 | ||
3436 | if (smb_buffer) | 3453 | cifs_buf_release(smb_buffer); |
3437 | cifs_buf_release(smb_buffer); | ||
3438 | return rc; | 3454 | return rc; |
3439 | } | 3455 | } |
3440 | 3456 | ||