Commit 0caf36e7 authored by Wang Zhaolong's avatar Wang Zhaolong
Browse files

cifs: Fix an infinite loop in cifsd caused by a failed mount attempt on port 139

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBSSQA


CVE: NA

----------------------------------------

If an error occurs when port 139 is used to mount the CIFS, the mount
process may racy with the reconnect process. If the mount process first
sets tcpStatus to CifsExiting and then the reconnect process sets
tcpStatus to CifsNeedReconnect later, the cifs_reconnect() function
enters an infinite loop and and the cifsd process cannot exit.

 mount.cifs                       cifsd
 ------------------------------------------------------------------
 cifs_do_mount
  cifs_smb3_do_mount
   cifs_mount
    mount_get_conns
     cifs_get_smb_ses
                          cifs_demultiplex_thread
      cifs_negotiate_protocol
       smb2_need_neg
       smb2_negotiate
        SMB2_negotiate
         cifs_send_recv
          compound_send_recv
           wait_for_response
                           cifs_read_from_socket
                            cifs_readv_from_socket
                             cifs_readv_from_socket
                              smb2_can_echo
                               cifs_reconnect
                                do {
                                generic_ip_connect
           cifs_sync_mid_result
            DeleteMidQEntry
             _cifs_mid_q_entry_release
              cifs_small_buf_release
    cifs_put_tcp_session
     tcpStatus = CifsExiting;
     // The status will not be changed later in mount.cifs.
                                ip_rfc1001_connect
                                 smb_send
                                  __smb_send_rqst
                                   tcpStatus = CifsNeedReconnect;
                                // infinite loop
                                } while (tcpStatus == CifsNeedReconnect)

This patch adds a check in __smb_send_rqst() to not change tcpStatus to
CifsNeedReconnect if tcpStatus is CifsExiting.

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Signed-off-by: default avatarWang Zhaolong <wangzhaolong1@huawei.com>
parent 9b569f9f
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -376,7 +376,10 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
		 * be taken as the remainder of this one. We need to kill the
		 * socket so the server throws away the partial SMB
		 */
		spin_lock(&GlobalMid_Lock);
		if (server->tcpStatus != CifsExiting)
			server->tcpStatus = CifsNeedReconnect;
		spin_unlock(&GlobalMid_Lock);
		trace_smb3_partial_send_reconnect(server->CurrentMid,
						  server->hostname);
	}