soc: qcom: qmi: Fix wait event in handle destroy

If there is a packet in flight during ssr, send failure and
handle destruction can happen simultaneously. Although, the
handle is freed only after the transactions lists are empty,
the list check and wakeup happen without any locks held. This
may lead to a free after use crash when wakeup is triggered
after handle is freed.

Invoke wakeup and list check with appropriate lock being held.

CRs-Fixed: 899087
Change-Id: I38306cfe12e0c7ffb1f54b091a23cecb487ae9a0
Signed-off-by: Atish Kumar Patra <apatra@codeaurora.org>
This commit is contained in:
Atish Kumar Patra 2015-08-28 15:49:18 -06:00 committed by Arun Kumar Neelakantam
parent e9a497530e
commit 7bae1e4145

View file

@ -828,6 +828,8 @@ static void clean_txn_info(struct qmi_handle *handle)
int qmi_handle_destroy(struct qmi_handle *handle)
{
DEFINE_WAIT(wait);
if (!handle)
return -EINVAL;
@ -843,10 +845,18 @@ int qmi_handle_destroy(struct qmi_handle *handle)
mutex_unlock(&handle->handle_lock);
flush_workqueue(handle->handle_wq);
destroy_workqueue(handle->handle_wq);
wait_event(handle->reset_waitq,
(list_empty(&handle->txn_list) &&
list_empty(&handle->pending_txn_list)));
mutex_lock(&handle->handle_lock);
while (!list_empty(&handle->txn_list) ||
!list_empty(&handle->pending_txn_list)) {
prepare_to_wait(&handle->reset_waitq, &wait,
TASK_UNINTERRUPTIBLE);
mutex_unlock(&handle->handle_lock);
schedule();
mutex_lock(&handle->handle_lock);
finish_wait(&handle->reset_waitq, &wait);
}
mutex_unlock(&handle->handle_lock);
kfree(handle->dest_info);
kfree(handle);
return 0;
@ -1052,8 +1062,8 @@ int qmi_send_req_wait(struct qmi_handle *handle,
send_req_wait_err:
list_del(&txn_handle->list);
kfree(txn_handle);
mutex_unlock(&handle->handle_lock);
wake_up(&handle->reset_waitq);
mutex_unlock(&handle->handle_lock);
return rc;
}
EXPORT_SYMBOL(qmi_send_req_wait);