diff options
Diffstat (limited to 'fs/cifs/connect.c')
| -rw-r--r-- | fs/cifs/connect.c | 210 |
1 files changed, 117 insertions, 93 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e8fa46c7cff2..0711db65afe8 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -151,7 +151,7 @@ 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->ses) && (tcon->ses->server == server)) |
| 155 | tcon->tidStatus = CifsNeedReconnect; | 155 | tcon->tidStatus = CifsNeedReconnect; |
| 156 | } | 156 | } |
| 157 | read_unlock(&GlobalSMBSeslock); | 157 | read_unlock(&GlobalSMBSeslock); |
| @@ -173,14 +173,12 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 173 | mid_entry = list_entry(tmp, struct | 173 | mid_entry = list_entry(tmp, struct |
| 174 | mid_q_entry, | 174 | mid_q_entry, |
| 175 | qhead); | 175 | qhead); |
| 176 | if (mid_entry) { | 176 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) { |
| 177 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) { | ||
| 178 | /* Mark other intransit requests as needing | 177 | /* Mark other intransit requests as needing |
| 179 | retry so we do not immediately mark the | 178 | retry so we do not immediately mark the |
| 180 | session bad again (ie after we reconnect | 179 | session bad again (ie after we reconnect |
| 181 | below) as they timeout too */ | 180 | below) as they timeout too */ |
| 182 | mid_entry->midState = MID_RETRY_NEEDED; | 181 | mid_entry->midState = MID_RETRY_NEEDED; |
| 183 | } | ||
| 184 | } | 182 | } |
| 185 | } | 183 | } |
| 186 | spin_unlock(&GlobalMid_Lock); | 184 | spin_unlock(&GlobalMid_Lock); |
| @@ -351,11 +349,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
| 351 | 349 | ||
| 352 | current->flags |= PF_MEMALLOC; | 350 | current->flags |= PF_MEMALLOC; |
| 353 | cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); | 351 | cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); |
| 354 | write_lock(&GlobalSMBSeslock); | 352 | |
| 355 | atomic_inc(&tcpSesAllocCount); | 353 | length = atomic_inc_return(&tcpSesAllocCount); |
| 356 | length = tcpSesAllocCount.counter; | 354 | if (length > 1) |
| 357 | write_unlock(&GlobalSMBSeslock); | ||
| 358 | if (length > 1) | ||
| 359 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, | 355 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
| 360 | GFP_KERNEL); | 356 | GFP_KERNEL); |
| 361 | 357 | ||
| @@ -455,7 +451,7 @@ incomplete_rcv: | |||
| 455 | /* Note that FC 1001 length is big endian on the wire, | 451 | /* Note that FC 1001 length is big endian on the wire, |
| 456 | but we convert it here so it is always manipulated | 452 | but we convert it here so it is always manipulated |
| 457 | as host byte order */ | 453 | as host byte order */ |
| 458 | pdu_length = ntohl(smb_buffer->smb_buf_length); | 454 | pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length); |
| 459 | smb_buffer->smb_buf_length = pdu_length; | 455 | smb_buffer->smb_buf_length = pdu_length; |
| 460 | 456 | ||
| 461 | cFYI(1, ("rfc1002 length 0x%x", pdu_length+4)); | 457 | cFYI(1, ("rfc1002 length 0x%x", pdu_length+4)); |
| @@ -745,14 +741,11 @@ multi_t2_fnd: | |||
| 745 | coming home not much else we can do but free the memory */ | 741 | coming home not much else we can do but free the memory */ |
| 746 | } | 742 | } |
| 747 | 743 | ||
| 748 | write_lock(&GlobalSMBSeslock); | ||
| 749 | atomic_dec(&tcpSesAllocCount); | ||
| 750 | length = tcpSesAllocCount.counter; | ||
| 751 | |||
| 752 | /* last chance to mark ses pointers invalid | 744 | /* last chance to mark ses pointers invalid |
| 753 | if there are any pointing to this (e.g | 745 | if there are any pointing to this (e.g |
| 754 | if a crazy root user tried to kill cifsd | 746 | if a crazy root user tried to kill cifsd |
| 755 | kernel thread explicitly this might happen) */ | 747 | kernel thread explicitly this might happen) */ |
| 748 | write_lock(&GlobalSMBSeslock); | ||
| 756 | list_for_each(tmp, &GlobalSMBSessionList) { | 749 | list_for_each(tmp, &GlobalSMBSessionList) { |
| 757 | ses = list_entry(tmp, struct cifsSesInfo, | 750 | ses = list_entry(tmp, struct cifsSesInfo, |
| 758 | cifsSessionList); | 751 | cifsSessionList); |
| @@ -763,6 +756,8 @@ multi_t2_fnd: | |||
| 763 | 756 | ||
| 764 | kfree(server->hostname); | 757 | kfree(server->hostname); |
| 765 | kfree(server); | 758 | kfree(server); |
| 759 | |||
| 760 | length = atomic_dec_return(&tcpSesAllocCount); | ||
| 766 | if (length > 0) | 761 | if (length > 0) |
| 767 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, | 762 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
| 768 | GFP_KERNEL); | 763 | GFP_KERNEL); |
| @@ -1461,6 +1456,39 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, | |||
| 1461 | return rc; | 1456 | return rc; |
| 1462 | } | 1457 | } |
| 1463 | 1458 | ||
| 1459 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 1460 | static struct lock_class_key cifs_key[2]; | ||
| 1461 | static struct lock_class_key cifs_slock_key[2]; | ||
| 1462 | |||
| 1463 | static inline void | ||
| 1464 | cifs_reclassify_socket4(struct socket *sock) | ||
| 1465 | { | ||
| 1466 | struct sock *sk = sock->sk; | ||
| 1467 | BUG_ON(sock_owned_by_user(sk)); | ||
| 1468 | sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS", | ||
| 1469 | &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]); | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | static inline void | ||
| 1473 | cifs_reclassify_socket6(struct socket *sock) | ||
| 1474 | { | ||
| 1475 | struct sock *sk = sock->sk; | ||
| 1476 | BUG_ON(sock_owned_by_user(sk)); | ||
| 1477 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS", | ||
| 1478 | &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]); | ||
| 1479 | } | ||
| 1480 | #else | ||
| 1481 | static inline void | ||
| 1482 | cifs_reclassify_socket4(struct socket *sock) | ||
| 1483 | { | ||
| 1484 | } | ||
| 1485 | |||
| 1486 | static inline void | ||
| 1487 | cifs_reclassify_socket6(struct socket *sock) | ||
| 1488 | { | ||
| 1489 | } | ||
| 1490 | #endif | ||
| 1491 | |||
| 1464 | /* See RFC1001 section 14 on representation of Netbios names */ | 1492 | /* See RFC1001 section 14 on representation of Netbios names */ |
| 1465 | static void rfc1002mangle(char *target, char *source, unsigned int length) | 1493 | static void rfc1002mangle(char *target, char *source, unsigned int length) |
| 1466 | { | 1494 | { |
| @@ -1495,6 +1523,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1495 | /* BB other socket options to set KEEPALIVE, NODELAY? */ | 1523 | /* BB other socket options to set KEEPALIVE, NODELAY? */ |
| 1496 | cFYI(1, ("Socket created")); | 1524 | cFYI(1, ("Socket created")); |
| 1497 | (*csocket)->sk->sk_allocation = GFP_NOFS; | 1525 | (*csocket)->sk->sk_allocation = GFP_NOFS; |
| 1526 | cifs_reclassify_socket4(*csocket); | ||
| 1498 | } | 1527 | } |
| 1499 | } | 1528 | } |
| 1500 | 1529 | ||
| @@ -1627,6 +1656,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
| 1627 | /* BB other socket options to set KEEPALIVE, NODELAY? */ | 1656 | /* BB other socket options to set KEEPALIVE, NODELAY? */ |
| 1628 | cFYI(1, ("ipv6 Socket created")); | 1657 | cFYI(1, ("ipv6 Socket created")); |
| 1629 | (*csocket)->sk->sk_allocation = GFP_NOFS; | 1658 | (*csocket)->sk->sk_allocation = GFP_NOFS; |
| 1659 | cifs_reclassify_socket6(*csocket); | ||
| 1630 | } | 1660 | } |
| 1631 | } | 1661 | } |
| 1632 | 1662 | ||
| @@ -3588,97 +3618,91 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
| 3588 | } | 3618 | } |
| 3589 | first_time = 1; | 3619 | first_time = 1; |
| 3590 | } | 3620 | } |
| 3591 | if (!rc) { | 3621 | |
| 3592 | pSesInfo->flags = 0; | 3622 | if (rc) |
| 3593 | pSesInfo->capabilities = pSesInfo->server->capabilities; | 3623 | goto ss_err_exit; |
| 3594 | if (linuxExtEnabled == 0) | 3624 | |
| 3595 | pSesInfo->capabilities &= (~CAP_UNIX); | 3625 | pSesInfo->flags = 0; |
| 3626 | pSesInfo->capabilities = pSesInfo->server->capabilities; | ||
| 3627 | if (linuxExtEnabled == 0) | ||
| 3628 | pSesInfo->capabilities &= (~CAP_UNIX); | ||
| 3596 | /* pSesInfo->sequence_number = 0;*/ | 3629 | /* pSesInfo->sequence_number = 0;*/ |
| 3597 | cFYI(1, | 3630 | cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", |
| 3598 | ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", | 3631 | pSesInfo->server->secMode, |
| 3599 | pSesInfo->server->secMode, | 3632 | pSesInfo->server->capabilities, |
| 3600 | pSesInfo->server->capabilities, | 3633 | pSesInfo->server->timeAdj)); |
| 3601 | pSesInfo->server->timeAdj)); | 3634 | if (experimEnabled < 2) |
| 3602 | if (experimEnabled < 2) | 3635 | rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); |
| 3603 | rc = CIFS_SessSetup(xid, pSesInfo, | 3636 | else if (extended_security |
| 3604 | first_time, nls_info); | 3637 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) |
| 3605 | else if (extended_security | 3638 | && (pSesInfo->server->secType == NTLMSSP)) { |
| 3606 | && (pSesInfo->capabilities | 3639 | rc = -EOPNOTSUPP; |
| 3607 | & CAP_EXTENDED_SECURITY) | 3640 | } else if (extended_security |
| 3608 | && (pSesInfo->server->secType == NTLMSSP)) { | 3641 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) |
| 3609 | rc = -EOPNOTSUPP; | 3642 | && (pSesInfo->server->secType == RawNTLMSSP)) { |
| 3610 | } else if (extended_security | 3643 | cFYI(1, ("NTLMSSP sesssetup")); |
| 3611 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) | 3644 | rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, |
| 3612 | && (pSesInfo->server->secType == RawNTLMSSP)) { | 3645 | nls_info); |
| 3613 | cFYI(1, ("NTLMSSP sesssetup")); | 3646 | if (!rc) { |
| 3614 | rc = CIFSNTLMSSPNegotiateSessSetup(xid, | 3647 | if (ntlmv2_flag) { |
| 3615 | pSesInfo, | 3648 | char *v2_response; |
| 3616 | &ntlmv2_flag, | 3649 | cFYI(1, ("more secure NTLM ver2 hash")); |
| 3617 | nls_info); | 3650 | if (CalcNTLMv2_partial_mac_key(pSesInfo, |
| 3618 | if (!rc) { | 3651 | nls_info)) { |
| 3619 | if (ntlmv2_flag) { | 3652 | rc = -ENOMEM; |
| 3620 | char *v2_response; | 3653 | goto ss_err_exit; |
| 3621 | cFYI(1, ("more secure NTLM ver2 hash")); | 3654 | } else |
| 3622 | if (CalcNTLMv2_partial_mac_key(pSesInfo, | 3655 | v2_response = kmalloc(16 + 64 /* blob*/, |
| 3623 | nls_info)) { | 3656 | GFP_KERNEL); |
| 3624 | rc = -ENOMEM; | 3657 | if (v2_response) { |
| 3625 | goto ss_err_exit; | 3658 | CalcNTLMv2_response(pSesInfo, |
| 3626 | } else | 3659 | v2_response); |
| 3627 | v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL); | 3660 | /* if (first_time) |
| 3628 | if (v2_response) { | 3661 | cifs_calculate_ntlmv2_mac_key */ |
| 3629 | CalcNTLMv2_response(pSesInfo, | 3662 | kfree(v2_response); |
| 3630 | v2_response); | ||
| 3631 | /* if (first_time) | ||
| 3632 | cifs_calculate_ntlmv2_mac_key( | ||
| 3633 | pSesInfo->server->mac_signing_key, | ||
| 3634 | response, ntlm_session_key,*/ | ||
| 3635 | kfree(v2_response); | ||
| 3636 | /* BB Put dummy sig in SessSetup PDU? */ | 3663 | /* BB Put dummy sig in SessSetup PDU? */ |
| 3637 | } else { | ||
| 3638 | rc = -ENOMEM; | ||
| 3639 | goto ss_err_exit; | ||
| 3640 | } | ||
| 3641 | |||
| 3642 | } else { | 3664 | } else { |
| 3643 | SMBNTencrypt(pSesInfo->password, | 3665 | rc = -ENOMEM; |
| 3644 | pSesInfo->server->cryptKey, | 3666 | goto ss_err_exit; |
| 3645 | ntlm_session_key); | ||
| 3646 | |||
| 3647 | if (first_time) | ||
| 3648 | cifs_calculate_mac_key( | ||
| 3649 | &pSesInfo->server->mac_signing_key, | ||
| 3650 | ntlm_session_key, | ||
| 3651 | pSesInfo->password); | ||
| 3652 | } | 3667 | } |
| 3668 | |||
| 3669 | } else { | ||
| 3670 | SMBNTencrypt(pSesInfo->password, | ||
| 3671 | pSesInfo->server->cryptKey, | ||
| 3672 | ntlm_session_key); | ||
| 3673 | |||
| 3674 | if (first_time) | ||
| 3675 | cifs_calculate_mac_key( | ||
| 3676 | &pSesInfo->server->mac_signing_key, | ||
| 3677 | ntlm_session_key, | ||
| 3678 | pSesInfo->password); | ||
| 3679 | } | ||
| 3653 | /* for better security the weaker lanman hash not sent | 3680 | /* for better security the weaker lanman hash not sent |
| 3654 | in AuthSessSetup so we no longer calculate it */ | 3681 | in AuthSessSetup so we no longer calculate it */ |
| 3655 | 3682 | ||
| 3656 | rc = CIFSNTLMSSPAuthSessSetup(xid, | 3683 | rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo, |
| 3657 | pSesInfo, | 3684 | ntlm_session_key, |
| 3658 | ntlm_session_key, | 3685 | ntlmv2_flag, |
| 3659 | ntlmv2_flag, | 3686 | nls_info); |
| 3660 | nls_info); | 3687 | } |
| 3661 | } | 3688 | } else { /* old style NTLM 0.12 session setup */ |
| 3662 | } else { /* old style NTLM 0.12 session setup */ | 3689 | SMBNTencrypt(pSesInfo->password, pSesInfo->server->cryptKey, |
| 3663 | SMBNTencrypt(pSesInfo->password, | 3690 | ntlm_session_key); |
| 3664 | pSesInfo->server->cryptKey, | ||
| 3665 | ntlm_session_key); | ||
| 3666 | 3691 | ||
| 3667 | if (first_time) | 3692 | if (first_time) |
| 3668 | cifs_calculate_mac_key( | 3693 | cifs_calculate_mac_key( |
| 3669 | &pSesInfo->server->mac_signing_key, | 3694 | &pSesInfo->server->mac_signing_key, |
| 3670 | ntlm_session_key, pSesInfo->password); | 3695 | ntlm_session_key, pSesInfo->password); |
| 3671 | 3696 | ||
| 3672 | rc = CIFSSessSetup(xid, pSesInfo, | 3697 | rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info); |
| 3673 | ntlm_session_key, nls_info); | 3698 | } |
| 3674 | } | 3699 | if (rc) { |
| 3675 | if (rc) { | 3700 | cERROR(1, ("Send error in SessSetup = %d", rc)); |
| 3676 | cERROR(1, ("Send error in SessSetup = %d", rc)); | 3701 | } else { |
| 3677 | } else { | 3702 | cFYI(1, ("CIFS Session Established successfully")); |
| 3678 | cFYI(1, ("CIFS Session Established successfully")); | ||
| 3679 | pSesInfo->status = CifsGood; | 3703 | pSesInfo->status = CifsGood; |
| 3680 | } | ||
| 3681 | } | 3704 | } |
| 3705 | |||
| 3682 | ss_err_exit: | 3706 | ss_err_exit: |
| 3683 | return rc; | 3707 | return rc; |
| 3684 | } | 3708 | } |
