diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 70 |
1 files changed, 52 insertions, 18 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 18d3c7724d6e..8d6c17ab593d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -55,9 +55,6 @@ | |||
55 | /* SMB echo "timeout" -- FIXME: tunable? */ | 55 | /* SMB echo "timeout" -- FIXME: tunable? */ |
56 | #define SMB_ECHO_INTERVAL (60 * HZ) | 56 | #define SMB_ECHO_INTERVAL (60 * HZ) |
57 | 57 | ||
58 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | ||
59 | unsigned char *p24); | ||
60 | |||
61 | extern mempool_t *cifs_req_poolp; | 58 | extern mempool_t *cifs_req_poolp; |
62 | 59 | ||
63 | struct smb_vol { | 60 | struct smb_vol { |
@@ -87,6 +84,7 @@ struct smb_vol { | |||
87 | bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ | 84 | bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ |
88 | bool server_ino:1; /* use inode numbers from server ie UniqueId */ | 85 | bool server_ino:1; /* use inode numbers from server ie UniqueId */ |
89 | bool direct_io:1; | 86 | bool direct_io:1; |
87 | bool strict_io:1; /* strict cache behavior */ | ||
90 | bool remap:1; /* set to remap seven reserved chars in filenames */ | 88 | bool remap:1; /* set to remap seven reserved chars in filenames */ |
91 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ | 89 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ |
92 | bool no_linux_ext:1; | 90 | bool no_linux_ext:1; |
@@ -339,8 +337,13 @@ cifs_echo_request(struct work_struct *work) | |||
339 | struct TCP_Server_Info *server = container_of(work, | 337 | struct TCP_Server_Info *server = container_of(work, |
340 | struct TCP_Server_Info, echo.work); | 338 | struct TCP_Server_Info, echo.work); |
341 | 339 | ||
342 | /* no need to ping if we got a response recently */ | 340 | /* |
343 | if (time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) | 341 | * We cannot send an echo until the NEGOTIATE_PROTOCOL request is |
342 | * done, which is indicated by maxBuf != 0. Also, no need to ping if | ||
343 | * we got a response recently | ||
344 | */ | ||
345 | if (server->maxBuf == 0 || | ||
346 | time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) | ||
344 | goto requeue_echo; | 347 | goto requeue_echo; |
345 | 348 | ||
346 | rc = CIFSSMBEcho(server); | 349 | rc = CIFSSMBEcho(server); |
@@ -580,14 +583,23 @@ incomplete_rcv: | |||
580 | else if (reconnect == 1) | 583 | else if (reconnect == 1) |
581 | continue; | 584 | continue; |
582 | 585 | ||
583 | length += 4; /* account for rfc1002 hdr */ | 586 | total_read += 4; /* account for rfc1002 hdr */ |
584 | 587 | ||
588 | dump_smb(smb_buffer, total_read); | ||
585 | 589 | ||
586 | dump_smb(smb_buffer, length); | 590 | /* |
587 | if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) { | 591 | * We know that we received enough to get to the MID as we |
588 | cifs_dump_mem("Bad SMB: ", smb_buffer, 48); | 592 | * checked the pdu_length earlier. Now check to see |
589 | continue; | 593 | * if the rest of the header is OK. We borrow the length |
590 | } | 594 | * var for the rest of the loop to avoid a new stack var. |
595 | * | ||
596 | * 48 bytes is enough to display the header and a little bit | ||
597 | * into the payload for debugging purposes. | ||
598 | */ | ||
599 | length = checkSMB(smb_buffer, smb_buffer->Mid, total_read); | ||
600 | if (length != 0) | ||
601 | cifs_dump_mem("Bad SMB: ", smb_buffer, | ||
602 | min_t(unsigned int, total_read, 48)); | ||
591 | 603 | ||
592 | mid_entry = NULL; | 604 | mid_entry = NULL; |
593 | server->lstrp = jiffies; | 605 | server->lstrp = jiffies; |
@@ -599,7 +611,8 @@ incomplete_rcv: | |||
599 | if ((mid_entry->mid == smb_buffer->Mid) && | 611 | if ((mid_entry->mid == smb_buffer->Mid) && |
600 | (mid_entry->midState == MID_REQUEST_SUBMITTED) && | 612 | (mid_entry->midState == MID_REQUEST_SUBMITTED) && |
601 | (mid_entry->command == smb_buffer->Command)) { | 613 | (mid_entry->command == smb_buffer->Command)) { |
602 | if (check2ndT2(smb_buffer,server->maxBuf) > 0) { | 614 | if (length == 0 && |
615 | check2ndT2(smb_buffer, server->maxBuf) > 0) { | ||
603 | /* We have a multipart transact2 resp */ | 616 | /* We have a multipart transact2 resp */ |
604 | isMultiRsp = true; | 617 | isMultiRsp = true; |
605 | if (mid_entry->resp_buf) { | 618 | if (mid_entry->resp_buf) { |
@@ -634,12 +647,17 @@ incomplete_rcv: | |||
634 | mid_entry->resp_buf = smb_buffer; | 647 | mid_entry->resp_buf = smb_buffer; |
635 | mid_entry->largeBuf = isLargeBuf; | 648 | mid_entry->largeBuf = isLargeBuf; |
636 | multi_t2_fnd: | 649 | multi_t2_fnd: |
637 | mid_entry->midState = MID_RESPONSE_RECEIVED; | 650 | if (length == 0) |
638 | list_del_init(&mid_entry->qhead); | 651 | mid_entry->midState = |
639 | mid_entry->callback(mid_entry); | 652 | MID_RESPONSE_RECEIVED; |
653 | else | ||
654 | mid_entry->midState = | ||
655 | MID_RESPONSE_MALFORMED; | ||
640 | #ifdef CONFIG_CIFS_STATS2 | 656 | #ifdef CONFIG_CIFS_STATS2 |
641 | mid_entry->when_received = jiffies; | 657 | mid_entry->when_received = jiffies; |
642 | #endif | 658 | #endif |
659 | list_del_init(&mid_entry->qhead); | ||
660 | mid_entry->callback(mid_entry); | ||
643 | break; | 661 | break; |
644 | } | 662 | } |
645 | mid_entry = NULL; | 663 | mid_entry = NULL; |
@@ -655,6 +673,9 @@ multi_t2_fnd: | |||
655 | else | 673 | else |
656 | smallbuf = NULL; | 674 | smallbuf = NULL; |
657 | } | 675 | } |
676 | } else if (length != 0) { | ||
677 | /* response sanity checks failed */ | ||
678 | continue; | ||
658 | } else if (!is_valid_oplock_break(smb_buffer, server) && | 679 | } else if (!is_valid_oplock_break(smb_buffer, server) && |
659 | !isMultiRsp) { | 680 | !isMultiRsp) { |
660 | cERROR(1, "No task to wake, unknown frame received! " | 681 | cERROR(1, "No task to wake, unknown frame received! " |
@@ -1344,6 +1365,8 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1344 | vol->direct_io = 1; | 1365 | vol->direct_io = 1; |
1345 | } else if (strnicmp(data, "forcedirectio", 13) == 0) { | 1366 | } else if (strnicmp(data, "forcedirectio", 13) == 0) { |
1346 | vol->direct_io = 1; | 1367 | vol->direct_io = 1; |
1368 | } else if (strnicmp(data, "strictcache", 11) == 0) { | ||
1369 | vol->strict_io = 1; | ||
1347 | } else if (strnicmp(data, "noac", 4) == 0) { | 1370 | } else if (strnicmp(data, "noac", 4) == 0) { |
1348 | printk(KERN_WARNING "CIFS: Mount option noac not " | 1371 | printk(KERN_WARNING "CIFS: Mount option noac not " |
1349 | "supported. Instead set " | 1372 | "supported. Instead set " |
@@ -1568,6 +1591,9 @@ cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol) | |||
1568 | 1591 | ||
1569 | spin_lock(&cifs_tcp_ses_lock); | 1592 | spin_lock(&cifs_tcp_ses_lock); |
1570 | list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { | 1593 | list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { |
1594 | if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns)) | ||
1595 | continue; | ||
1596 | |||
1571 | if (!match_address(server, addr, | 1597 | if (!match_address(server, addr, |
1572 | (struct sockaddr *)&vol->srcaddr)) | 1598 | (struct sockaddr *)&vol->srcaddr)) |
1573 | continue; | 1599 | continue; |
@@ -1598,6 +1624,8 @@ cifs_put_tcp_session(struct TCP_Server_Info *server) | |||
1598 | return; | 1624 | return; |
1599 | } | 1625 | } |
1600 | 1626 | ||
1627 | put_net(cifs_net_ns(server)); | ||
1628 | |||
1601 | list_del_init(&server->tcp_ses_list); | 1629 | list_del_init(&server->tcp_ses_list); |
1602 | spin_unlock(&cifs_tcp_ses_lock); | 1630 | spin_unlock(&cifs_tcp_ses_lock); |
1603 | 1631 | ||
@@ -1672,6 +1700,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1672 | goto out_err; | 1700 | goto out_err; |
1673 | } | 1701 | } |
1674 | 1702 | ||
1703 | cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); | ||
1675 | tcp_ses->hostname = extract_hostname(volume_info->UNC); | 1704 | tcp_ses->hostname = extract_hostname(volume_info->UNC); |
1676 | if (IS_ERR(tcp_ses->hostname)) { | 1705 | if (IS_ERR(tcp_ses->hostname)) { |
1677 | rc = PTR_ERR(tcp_ses->hostname); | 1706 | rc = PTR_ERR(tcp_ses->hostname); |
@@ -1752,6 +1781,8 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1752 | out_err_crypto_release: | 1781 | out_err_crypto_release: |
1753 | cifs_crypto_shash_release(tcp_ses); | 1782 | cifs_crypto_shash_release(tcp_ses); |
1754 | 1783 | ||
1784 | put_net(cifs_net_ns(tcp_ses)); | ||
1785 | |||
1755 | out_err: | 1786 | out_err: |
1756 | if (tcp_ses) { | 1787 | if (tcp_ses) { |
1757 | if (!IS_ERR(tcp_ses->hostname)) | 1788 | if (!IS_ERR(tcp_ses->hostname)) |
@@ -2263,8 +2294,8 @@ generic_ip_connect(struct TCP_Server_Info *server) | |||
2263 | } | 2294 | } |
2264 | 2295 | ||
2265 | if (socket == NULL) { | 2296 | if (socket == NULL) { |
2266 | rc = sock_create_kern(sfamily, SOCK_STREAM, | 2297 | rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM, |
2267 | IPPROTO_TCP, &socket); | 2298 | IPPROTO_TCP, &socket, 1); |
2268 | if (rc < 0) { | 2299 | if (rc < 0) { |
2269 | cERROR(1, "Error %d creating socket", rc); | 2300 | cERROR(1, "Error %d creating socket", rc); |
2270 | server->ssocket = NULL; | 2301 | server->ssocket = NULL; |
@@ -2576,6 +2607,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, | |||
2576 | if (pvolume_info->multiuser) | 2607 | if (pvolume_info->multiuser) |
2577 | cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER | | 2608 | cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER | |
2578 | CIFS_MOUNT_NO_PERM); | 2609 | CIFS_MOUNT_NO_PERM); |
2610 | if (pvolume_info->strict_io) | ||
2611 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO; | ||
2579 | if (pvolume_info->direct_io) { | 2612 | if (pvolume_info->direct_io) { |
2580 | cFYI(1, "mounting share using direct i/o"); | 2613 | cFYI(1, "mounting share using direct i/o"); |
2581 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | 2614 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
@@ -2977,7 +3010,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
2977 | bcc_ptr); | 3010 | bcc_ptr); |
2978 | else | 3011 | else |
2979 | #endif /* CIFS_WEAK_PW_HASH */ | 3012 | #endif /* CIFS_WEAK_PW_HASH */ |
2980 | SMBNTencrypt(tcon->password, ses->server->cryptkey, bcc_ptr); | 3013 | rc = SMBNTencrypt(tcon->password, ses->server->cryptkey, |
3014 | bcc_ptr); | ||
2981 | 3015 | ||
2982 | bcc_ptr += CIFS_AUTH_RESP_SIZE; | 3016 | bcc_ptr += CIFS_AUTH_RESP_SIZE; |
2983 | if (ses->capabilities & CAP_UNICODE) { | 3017 | if (ses->capabilities & CAP_UNICODE) { |