aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeepak Kumar Singh <deesin@codeaurora.org>2019-12-06 17:50:32 +0530
committerRaymon Sang <csang@codeaurora.org>2019-12-24 17:46:28 +0800
commit41638a35005583dad6d13e78da78397199291ee4 (patch)
tree237e73a736c8fa8476ff9e2f2c4c91b2e89bf1c4
parentcb47f0788cf1e133019591115adc6ff2ab816f2a (diff)
soc: qcom: glink_probe: use lock while sending ssr notificationLA.UM.8.9.r1-07100-SM6xx.0
In ssr handling of remote subsystem down, all rpmsg devices are removed for that edge. If at the same time ssr down is received for other remote subsystem, it may try to notify already down remote and end up using invalid rpmsg device which results in use after free. Store device state in ssr context and update this with holding a lock. SSR notification function should also use the same lock and perform check for validity of rpmsg device. CRs-Fixed: 2580433 Change-Id: I339e228a527f7b6a737944d8e9e53caa31992914 Signed-off-by: Deepak Kumar Singh <deesin@codeaurora.org>
-rw-r--r--drivers/soc/qcom/glink_probe.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/soc/qcom/glink_probe.c b/drivers/soc/qcom/glink_probe.c
index 36540a1b56db..7b4d99d2ef6d 100644
--- a/drivers/soc/qcom/glink_probe.c
+++ b/drivers/soc/qcom/glink_probe.c
@@ -24,6 +24,7 @@
#define GLINK_PROBE_LOG_PAGE_CNT 4
static void *glink_ilc;
+static DEFINE_MUTEX(ssr_lock);
#define GLINK_INFO(x, ...) \
do { \
@@ -126,14 +127,15 @@ static int glink_ssr_ssr_cb(struct notifier_block *this,
{
struct glink_ssr_nb *nb = container_of(this, struct glink_ssr_nb, nb);
struct glink_ssr *ssr = nb->ssr;
- struct device *dev = ssr->dev;
+ struct device *dev;
struct do_cleanup_msg msg;
int ret;
- if (!dev || !ssr->ept)
- return NOTIFY_DONE;
-
kref_get(&ssr->refcount);
+ mutex_lock(&ssr_lock);
+ dev = ssr->dev;
+ if (!dev || !ssr->ept)
+ goto out;
if (code == SUBSYS_AFTER_SHUTDOWN) {
ssr->seq_num++;
@@ -153,8 +155,7 @@ static int glink_ssr_ssr_cb(struct notifier_block *this,
if (ret) {
GLINK_ERR(dev, "fail to send do cleanup to %s %d\n",
nb->ssr_label, ret);
- kref_put(&ssr->refcount, glink_ssr_release);
- return NOTIFY_DONE;
+ goto out;
}
ret = wait_for_completion_timeout(&ssr->completion, HZ);
@@ -162,6 +163,8 @@ static int glink_ssr_ssr_cb(struct notifier_block *this,
GLINK_ERR(dev, "timeout waiting for cleanup resp\n");
}
+out:
+ mutex_unlock(&ssr_lock);
kref_put(&ssr->refcount, glink_ssr_release);
return NOTIFY_DONE;
}
@@ -274,10 +277,12 @@ static void glink_ssr_remove(struct rpmsg_device *rpdev)
{
struct glink_ssr *ssr = dev_get_drvdata(&rpdev->dev);
+ mutex_lock(&ssr_lock);
ssr->dev = NULL;
ssr->ept = NULL;
- dev_set_drvdata(&rpdev->dev, NULL);
+ mutex_unlock(&ssr_lock);
+ dev_set_drvdata(&rpdev->dev, NULL);
schedule_work(&ssr->unreg_work);
}