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 | } |