summaryrefslogtreecommitdiff
path: root/drivers/soc
diff options
context:
space:
mode:
authorKarthikeyan Ramasubramanian <kramasub@codeaurora.org>2016-04-12 21:56:23 -0600
committerJeevan Shriram <jshriram@codeaurora.org>2016-04-18 17:06:16 -0700
commit8266c2d117a731a3bb1ecf93b6198d4754e864b0 (patch)
treec19e613194df901b2bde2aaa09a7b59025dda349 /drivers/soc
parenta63df786422a0dda04423157fdd9dd2ff4125ff7 (diff)
soc: qcom: glink: Fix channel migration logic
Channel migration logic assumes that the remote & local channel contexts are always different and exist in different transports. If the remote & local channel contexts exist in the same transport, then it leads to a use-after-free scenario. Fix the channel migration logic by not freeing the channel context if the local & remote side opens in the same initial transport. Change-Id: I319a93c49022b08e5c33b561d982a751d5223a58 Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/qcom/glink.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index aad67abc709a..388fb70604b6 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -4338,6 +4338,9 @@ static bool ch_migrate(struct channel_ctx *l_ctx, struct channel_ctx *r_ctx)
list_del_init(&l_ctx->port_list_node);
spin_unlock_irqrestore(&l_ctx->transport_ptr->xprt_ctx_lock_lhb1,
flags);
+ mutex_lock(&l_ctx->transport_ptr->xprt_dbgfs_lock_lhb3);
+ glink_debugfs_remove_channel(l_ctx, l_ctx->transport_ptr);
+ mutex_unlock(&l_ctx->transport_ptr->xprt_dbgfs_lock_lhb3);
memcpy(ctx_clone, l_ctx, sizeof(*ctx_clone));
ctx_clone->local_xprt_req = 0;
@@ -4372,11 +4375,13 @@ static bool ch_migrate(struct channel_ctx *l_ctx, struct channel_ctx *r_ctx)
l_ctx->transport_ptr = xprt;
l_ctx->local_xprt_req = 0;
l_ctx->local_xprt_resp = 0;
- if (new_xprt != r_ctx->transport_ptr->id) {
- r_ctx->local_xprt_req = 0;
- r_ctx->local_xprt_resp = 0;
- r_ctx->remote_xprt_req = 0;
- r_ctx->remote_xprt_resp = 0;
+ if (new_xprt != r_ctx->transport_ptr->id || l_ctx == r_ctx) {
+ if (new_xprt != r_ctx->transport_ptr->id) {
+ r_ctx->local_xprt_req = 0;
+ r_ctx->local_xprt_resp = 0;
+ r_ctx->remote_xprt_req = 0;
+ r_ctx->remote_xprt_resp = 0;
+ }
l_ctx->remote_xprt_req = 0;
l_ctx->remote_xprt_resp = 0;
@@ -4409,6 +4414,9 @@ static bool ch_migrate(struct channel_ctx *l_ctx, struct channel_ctx *r_ctx)
spin_unlock_irqrestore(&xprt->xprt_ctx_lock_lhb1, flags);
}
+ mutex_lock(&xprt->xprt_dbgfs_lock_lhb3);
+ glink_debugfs_add_channel(l_ctx, xprt);
+ mutex_unlock(&xprt->xprt_dbgfs_lock_lhb3);
mutex_lock(&transport_list_lock_lha0);
list_for_each_entry(xprt, &transport_list, list_node)