From cb622fd2aba07c1f8cdb0d67ec80c1cf3759f2d0 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Wed, 27 Jun 2018 18:19:57 -0700 Subject: rpmsg: glink: Set tail pointer to 0 at end of FIFO commit 4623e8bf1de0b86e23a56cdb39a72f054e89c3bd upstream. When wrapping around the FIFO, the remote expects the tail pointer to be reset to 0 on the edge case where the tail equals the FIFO length. Fixes: caf989c350e8 ("rpmsg: glink: Introduce glink smem based transport") Cc: stable@vger.kernel.org Signed-off-by: Chris Lew Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/rpmsg/qcom_glink_smem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index 5cdaa5f8fb61..53b3a43160f4 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -119,7 +119,7 @@ static void glink_smem_rx_advance(struct qcom_glink_pipe *np, tail = le32_to_cpu(*pipe->tail); tail += count; - if (tail > pipe->native.length) + if (tail >= pipe->native.length) tail -= pipe->native.length; *pipe->tail = cpu_to_le32(tail); -- cgit v1.2.3 From e4fbe58ca403f028ce2868d5ce9979443bb61950 Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Fri, 4 Oct 2019 15:26:57 -0700 Subject: rpmsg: glink: Fix reuse intents memory leak issue commit b85f6b601407347f5425c4c058d1b7871f5bf4f0 upstream. Memory allocated for re-usable intents are not freed during channel cleanup which causes memory leak in system. Check and free all re-usable memory to avoid memory leak. Fixes: 933b45da5d1d ("rpmsg: glink: Add support for TX intents") Cc: stable@vger.kernel.org Acked-By: Chris Lew Tested-by: Srinivas Kandagatla Signed-off-by: Arun Kumar Neelakantam Reported-by: Srinivas Kandagatla Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/rpmsg/qcom_glink_native.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index e8e12c2b1d0e..32b8ac9a3fdc 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -243,10 +243,19 @@ static void qcom_glink_channel_release(struct kref *ref) { struct glink_channel *channel = container_of(ref, struct glink_channel, refcount); + struct glink_core_rx_intent *tmp; unsigned long flags; + int iid; spin_lock_irqsave(&channel->intent_lock, flags); + idr_for_each_entry(&channel->liids, tmp, iid) { + kfree(tmp->data); + kfree(tmp); + } idr_destroy(&channel->liids); + + idr_for_each_entry(&channel->riids, tmp, iid) + kfree(tmp); idr_destroy(&channel->riids); spin_unlock_irqrestore(&channel->intent_lock, flags); -- cgit v1.2.3 From ec9bacb6ca32610b89c3ac4b2646271239219920 Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Fri, 4 Oct 2019 15:26:58 -0700 Subject: rpmsg: glink: Fix use after free in open_ack TIMEOUT case commit ac74ea01860170699fb3b6ea80c0476774c8e94f upstream. Extra channel reference put when remote sending OPEN_ACK after timeout causes use-after-free while handling next remote CLOSE command. Remove extra reference put in timeout case to avoid use-after-free. Fixes: b4f8e52b89f6 ("rpmsg: Introduce Qualcomm RPM glink driver") Cc: stable@vger.kernel.org Tested-by: Srinivas Kandagatla Signed-off-by: Arun Kumar Neelakantam Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/rpmsg/qcom_glink_native.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 32b8ac9a3fdc..575203dfd676 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1104,13 +1104,12 @@ static int qcom_glink_create_remote(struct qcom_glink *glink, close_link: /* * Send a close request to "undo" our open-ack. The close-ack will - * release the last reference. + * release qcom_glink_send_open_req() reference and the last reference + * will be relesed after receiving remote_close or transport unregister + * by calling qcom_glink_native_remove(). */ qcom_glink_send_close_req(glink, channel); - /* Release qcom_glink_send_open_req() reference */ - kref_put(&channel->refcount, qcom_glink_channel_release); - return ret; } -- cgit v1.2.3 From 907f2c940db052b5a5f371a7be456bac6d0b267c Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Fri, 4 Oct 2019 15:26:59 -0700 Subject: rpmsg: glink: Put an extra reference during cleanup commit b646293e272816dd0719529dcebbd659de0722f7 upstream. In a remote processor crash scenario, there is no guarantee the remote processor sent close requests before it went into a bad state. Remove the reference that is normally handled by the close command in the so channel resources can be released. Fixes: b4f8e52b89f6 ("rpmsg: Introduce Qualcomm RPM glink driver") Cc: stable@vger.kernel.org Tested-by: Srinivas Kandagatla Signed-off-by: Chris Lew Reported-by: Srinivas Kandagatla Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/rpmsg/qcom_glink_native.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 575203dfd676..aef24a4c9826 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1613,6 +1613,10 @@ void qcom_glink_native_remove(struct qcom_glink *glink) idr_for_each_entry(&glink->lcids, channel, cid) kref_put(&channel->refcount, qcom_glink_channel_release); + /* Release any defunct local channels, waiting for close-req */ + idr_for_each_entry(&glink->rcids, channel, cid) + kref_put(&channel->refcount, qcom_glink_channel_release); + idr_destroy(&glink->lcids); idr_destroy(&glink->rcids); spin_unlock_irqrestore(&glink->idr_lock, flags); -- cgit v1.2.3 From 90be4d4327fc5560b77693dd63922bcc331fa4d8 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Fri, 4 Oct 2019 15:27:00 -0700 Subject: rpmsg: glink: Fix rpmsg_register_device err handling commit f7e714988edaffe6ac578318e99501149b067ba0 upstream. The device release function is set before registering with rpmsg. If rpmsg registration fails, the framework will call device_put(), which invokes the release function. The channel create logic does not need to free rpdev if rpmsg_register_device() fails and release is called. Fixes: b4f8e52b89f6 ("rpmsg: Introduce Qualcomm RPM glink driver") Cc: stable@vger.kernel.org Tested-by: Srinivas Kandagatla Signed-off-by: Chris Lew Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/rpmsg/qcom_glink_native.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index aef24a4c9826..306b3cc6ab13 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1400,15 +1400,13 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, ret = rpmsg_register_device(rpdev); if (ret) - goto free_rpdev; + goto rcid_remove; channel->rpdev = rpdev; } return 0; -free_rpdev: - kfree(rpdev); rcid_remove: spin_lock_irqsave(&glink->idr_lock, flags); idr_remove(&glink->rcids, channel->rcid); -- cgit v1.2.3 From 29166ff96dad3e6b95aa30bcf2aeda6e3e69b791 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 4 Oct 2019 15:27:01 -0700 Subject: rpmsg: glink: Don't send pending rx_done during remove commit c3dadc19b7564c732598b30d637c6f275c3b77b6 upstream. Attempting to transmit rx_done messages after the GLINK instance is being torn down will cause use after free and memory leaks. So cancel the intent_work and free up the pending intents. With this there are no concurrent accessors of the channel left during qcom_glink_native_remove() and there is therefor no need to hold the spinlock during this operation - which would prohibit the use of cancel_work_sync() in the release function. So remove this. Fixes: 1d2ea36eead9 ("rpmsg: glink: Add rx done command") Cc: stable@vger.kernel.org Acked-by: Chris Lew Tested-by: Srinivas Kandagatla Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/rpmsg/qcom_glink_native.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 306b3cc6ab13..57a5d394d650 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -243,11 +243,23 @@ static void qcom_glink_channel_release(struct kref *ref) { struct glink_channel *channel = container_of(ref, struct glink_channel, refcount); + struct glink_core_rx_intent *intent; struct glink_core_rx_intent *tmp; unsigned long flags; int iid; + /* cancel pending rx_done work */ + cancel_work_sync(&channel->intent_work); + spin_lock_irqsave(&channel->intent_lock, flags); + /* Free all non-reuse intents pending rx_done work */ + list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) { + if (!intent->reuse) { + kfree(intent->data); + kfree(intent); + } + } + idr_for_each_entry(&channel->liids, tmp, iid) { kfree(tmp->data); kfree(tmp); @@ -1597,7 +1609,6 @@ void qcom_glink_native_remove(struct qcom_glink *glink) struct glink_channel *channel; int cid; int ret; - unsigned long flags; disable_irq(glink->irq); cancel_work_sync(&glink->rx_work); @@ -1606,7 +1617,6 @@ void qcom_glink_native_remove(struct qcom_glink *glink) if (ret) dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); - spin_lock_irqsave(&glink->idr_lock, flags); /* Release any defunct local channels, waiting for close-ack */ idr_for_each_entry(&glink->lcids, channel, cid) kref_put(&channel->refcount, qcom_glink_channel_release); @@ -1617,7 +1627,6 @@ void qcom_glink_native_remove(struct qcom_glink *glink) idr_destroy(&glink->lcids); idr_destroy(&glink->rcids); - spin_unlock_irqrestore(&glink->idr_lock, flags); mbox_free_channel(glink->mbox_chan); } EXPORT_SYMBOL_GPL(qcom_glink_native_remove); -- cgit v1.2.3 From 50736a155f0f4953ee802699431b3f1eff9d8e6b Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 4 Oct 2019 15:27:02 -0700 Subject: rpmsg: glink: Free pending deferred work on remove commit 278bcb7300f61785dba63840bd2a8cf79f14554c upstream. By just cancelling the deferred rx worker during GLINK instance teardown any pending deferred commands are leaked, so free them. Fixes: b4f8e52b89f6 ("rpmsg: Introduce Qualcomm RPM glink driver") Cc: stable@vger.kernel.org Acked-by: Chris Lew Tested-by: Srinivas Kandagatla Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/rpmsg/qcom_glink_native.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/rpmsg') diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 57a5d394d650..1e6253f1e070 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1539,6 +1539,18 @@ static void qcom_glink_work(struct work_struct *work) } } +static void qcom_glink_cancel_rx_work(struct qcom_glink *glink) +{ + struct glink_defer_cmd *dcmd; + struct glink_defer_cmd *tmp; + + /* cancel any pending deferred rx_work */ + cancel_work_sync(&glink->rx_work); + + list_for_each_entry_safe(dcmd, tmp, &glink->rx_queue, node) + kfree(dcmd); +} + struct qcom_glink *qcom_glink_native_probe(struct device *dev, unsigned long features, struct qcom_glink_pipe *rx, @@ -1611,7 +1623,7 @@ void qcom_glink_native_remove(struct qcom_glink *glink) int ret; disable_irq(glink->irq); - cancel_work_sync(&glink->rx_work); + qcom_glink_cancel_rx_work(glink); ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device); if (ret) -- cgit v1.2.3