diff options
| author | Karthikeyan Ramasubramanian <kramasub@codeaurora.org> | 2016-04-12 21:56:23 -0600 |
|---|---|---|
| committer | Jeevan Shriram <jshriram@codeaurora.org> | 2016-04-18 17:06:16 -0700 |
| commit | 8266c2d117a731a3bb1ecf93b6198d4754e864b0 (patch) | |
| tree | c19e613194df901b2bde2aaa09a7b59025dda349 /drivers/soc | |
| parent | a63df786422a0dda04423157fdd9dd2ff4125ff7 (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.c | 18 |
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) |
