From 2de05ba6fbfa56d174daa0dad11dc15a2ec8ec6b Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Wed, 24 Oct 2018 15:26:40 +0530 Subject: [PATCH] soc: qcom: qmi_interface: Abort pending transaction In some cases like SSR, qmi clients are releasing handles without considering the waiting transactions which results in use after free of qmi handles after the transaction wait time completes. Abort the pending transaction during qmi_handle_release to avoid the use after free. CRs-Fixed: 2328443 Change-Id: I59e19222b2b9a8ace3d37b4a70ea891ff88db07e Signed-off-by: Arun Kumar Neelakantam --- drivers/soc/qcom/qmi_interface.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c index ddb36513a2ac..246ed68cea5c 100644 --- a/drivers/soc/qcom/qmi_interface.c +++ b/drivers/soc/qcom/qmi_interface.c @@ -347,6 +347,9 @@ int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout) ret = wait_for_completion_timeout(&txn->completion, timeout); + if (txn->result == -ENETRESET) + return txn->result; + mutex_lock(&qmi->txn_lock); mutex_lock(&txn->lock); idr_remove(&qmi->txns, txn->id); @@ -685,6 +688,8 @@ void qmi_handle_release(struct qmi_handle *qmi) { struct socket *sock = qmi->sock; struct qmi_service *svc, *tmp; + struct qmi_txn *txn; + int txn_id; sock->sk->sk_user_data = NULL; cancel_work_sync(&qmi->work); @@ -698,6 +703,12 @@ void qmi_handle_release(struct qmi_handle *qmi) destroy_workqueue(qmi->wq); + mutex_lock(&qmi->txn_lock); + idr_for_each_entry(&qmi->txns, txn, txn_id) { + txn->result = -ENETRESET; + complete(&txn->completion); + } + mutex_unlock(&qmi->txn_lock); idr_destroy(&qmi->txns); kfree(qmi->recv_buf);