soc: qcom: qmi_interface: Fix race between net_reset and release

qmi client calling qmi_handle_release while handling net_reset cause
NULL pointer access.

Synchronize the net_reset handling with qmi_handle_release to avoid
memory leak and invalid pointer access.

CRs-Fixed: 2383987
Change-Id: I8179f96e5dfabe945b1a37f83530bc3b05ed746a
Signed-off-by: Arun Kumar Neelakantam <aneela@codeaurora.org>
This commit is contained in:
Arun Kumar Neelakantam 2019-01-22 16:48:57 +05:30 • committed by Gerrit - the friendly Code Review server
commit 0aa2d8ef9b

View file

@ -453,17 +453,18 @@ static void qmi_handle_net_reset(struct qmi_handle *qmi)
if (IS_ERR(sock))
return;
mutex_lock(&qmi->sock_lock);
sock_release(qmi->sock);
qmi->sock = NULL;
mutex_unlock(&qmi->sock_lock);
qmi_recv_del_server(qmi, -1, -1);
if (qmi->ops.net_reset)
qmi->ops.net_reset(qmi);
mutex_lock(&qmi->sock_lock);
/* Already qmi_handle_release() started */
if (!qmi->sock) {
sock_release(sock);
return;
}
sock_release(qmi->sock);
qmi->sock = sock;
qmi->sq = sq;
mutex_unlock(&qmi->sock_lock);
@ -695,23 +696,24 @@ EXPORT_SYMBOL(qmi_handle_init);
*/
void qmi_handle_release(struct qmi_handle *qmi)
{
struct socket *sock = qmi->sock;
struct socket *sock;
struct qmi_service *svc, *tmp;
struct qmi_txn *txn;
int txn_id;
mutex_lock(&qmi->sock_lock);
sock = qmi->sock;
write_lock_bh(&sock->sk->sk_callback_lock);
sock->sk->sk_user_data = NULL;
write_unlock_bh(&sock->sk->sk_callback_lock);
cancel_work_sync(&qmi->work);
qmi_recv_del_server(qmi, -1, -1);
mutex_lock(&qmi->sock_lock);
sock_release(sock);
qmi->sock = NULL;
mutex_unlock(&qmi->sock_lock);
cancel_work_sync(&qmi->work);
qmi_recv_del_server(qmi, -1, -1);
destroy_workqueue(qmi->wq);
mutex_lock(&qmi->txn_lock);