From dcff893174aa7fd9ecb60f27a5f09c694de2b0f5 Mon Sep 17 00:00:00 2001 From: Dhoat Harpal Date: Wed, 21 Jun 2017 21:33:45 +0530 Subject: [PATCH] soc: qcom: glink: Remove magic number logic Possible use after free issue while accessing magic number, if the ctx is already freed. Magic number check is removed. CRs-Fixed: 2061287 Change-Id: Ie157a930c7eb310829766319e0af742114337e6c Signed-off-by: Dhoat Harpal --- drivers/soc/qcom/glink.c | 91 ++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 57 deletions(-) diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c index f4ffc7df1e9c..d1bafbd3b11d 100644 --- a/drivers/soc/qcom/glink.c +++ b/drivers/soc/qcom/glink.c @@ -30,7 +30,6 @@ #include "glink_private.h" #include "glink_xprt_if.h" -#define GLINK_CTX_CANARY 0x58544324 /* "$CTX" */ /* Number of internal IPC Logging log pages */ #define NUM_LOG_PAGES 10 #define GLINK_PM_QOS_HOLDOFF_MS 10 @@ -40,7 +39,6 @@ #define GLINK_KTHREAD_PRIO 1 -static rwlock_t magic_lock; /** * struct glink_qos_priority_bin - Packet Scheduler's priority bucket * @max_rate_kBps: Maximum rate supported by the priority bucket. @@ -316,7 +314,6 @@ struct channel_ctx { uint32_t rt_vote_on; uint32_t rt_vote_off; - uint32_t magic_number; }; static struct glink_core_if core_impl; @@ -447,33 +444,15 @@ static void glink_core_deinit_xprt_qos_cfg( static int glink_get_ch_ctx(struct channel_ctx *ctx) { - unsigned long flags; - if (!ctx) return -EINVAL; - read_lock_irqsave(&magic_lock, flags); - if (ctx->magic_number != GLINK_CTX_CANARY) { - read_unlock_irqrestore(&magic_lock, flags); - return -EINVAL; - } rwref_get(&ctx->ch_state_lhb2); - read_unlock_irqrestore(&magic_lock, flags); return 0; } -static int glink_put_ch_ctx(struct channel_ctx *ctx, bool update_magic) +static void glink_put_ch_ctx(struct channel_ctx *ctx) { - unsigned long flags; - - if (!update_magic) { - rwref_put(&ctx->ch_state_lhb2); - return 0; - } - write_lock_irqsave(&magic_lock, flags); - ctx->magic_number = 0; rwref_put(&ctx->ch_state_lhb2); - write_unlock_irqrestore(&magic_lock, flags); - return 0; } /** @@ -2624,7 +2603,6 @@ void *glink_open(const struct glink_open_config *cfg) ctx->notify_tx_abort = cfg->notify_tx_abort; ctx->notify_rx_tracer_pkt = cfg->notify_rx_tracer_pkt; ctx->notify_remote_rx_intent = cfg->notify_remote_rx_intent; - ctx->magic_number = GLINK_CTX_CANARY; if (!ctx->notify_rx_intent_req) ctx->notify_rx_intent_req = glink_dummy_notify_rx_intent_req; @@ -2764,13 +2742,13 @@ int glink_close(void *handle) GLINK_INFO_CH(ctx, "%s: Closing channel, ctx: %p\n", __func__, ctx); if (ctx->local_open_state == GLINK_CHANNEL_CLOSED) { - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return 0; } if (ctx->local_open_state == GLINK_CHANNEL_CLOSING) { /* close already pending */ - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EBUSY; } @@ -2835,7 +2813,7 @@ relock: xprt_ctx = ctx->transport_ptr; rwref_put(&ctx->ch_state_lhb2); rwref_read_put(&xprt_ctx->xprt_state_lhb0); - glink_put_ch_ctx(ctx, true); + glink_put_ch_ctx(ctx); return ret; } EXPORT_SYMBOL(glink_close); @@ -3051,13 +3029,13 @@ static int glink_tx_common(void *handle, void *pkt_priv, xprt_schedule_tx(ctx->transport_ptr, ctx, tx_info); rwref_read_put(&ctx->ch_state_lhb2); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ret; glink_tx_common_err: rwref_read_put(&ctx->ch_state_lhb2); glink_tx_common_err_2: - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); kfree(tx_info); return ret; } @@ -3107,7 +3085,7 @@ int glink_queue_rx_intent(void *handle, const void *pkt_priv, size_t size) /* Can only queue rx intents if channel is fully opened */ GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EBUSY; } @@ -3116,14 +3094,14 @@ int glink_queue_rx_intent(void *handle, const void *pkt_priv, size_t size) GLINK_ERR_CH(ctx, "%s: Intent pointer allocation failed size[%zu]\n", __func__, size); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -ENOMEM; } GLINK_DBG_CH(ctx, "%s: L[%u]:%zu\n", __func__, intent_ptr->id, intent_ptr->intent_size); if (ctx->transport_ptr->capabilities & GCAP_INTENTLESS) { - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ret; } @@ -3133,7 +3111,7 @@ int glink_queue_rx_intent(void *handle, const void *pkt_priv, size_t size) if (ret) /* unable to transmit, dequeue intent */ ch_remove_local_rx_intent(ctx, intent_ptr->id); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ret; } EXPORT_SYMBOL(glink_queue_rx_intent); @@ -3165,12 +3143,12 @@ bool glink_rx_intent_exists(void *handle, size_t size) if (size <= intent->intent_size) { spin_unlock_irqrestore( &ctx->local_rx_intent_lst_lock_lhc1, flags); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return true; } } spin_unlock_irqrestore(&ctx->local_rx_intent_lst_lock_lhc1, flags); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return false; } EXPORT_SYMBOL(glink_rx_intent_exists); @@ -3199,7 +3177,7 @@ int glink_rx_done(void *handle, const void *ptr, bool reuse) if (IS_ERR_OR_NULL(liid_ptr)) { /* invalid pointer */ GLINK_ERR_CH(ctx, "%s: Invalid pointer %p\n", __func__, ptr); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EINVAL; } @@ -3225,7 +3203,7 @@ int glink_rx_done(void *handle, const void *ptr, bool reuse) /* send rx done */ ctx->transport_ptr->ops->tx_cmd_local_rx_done(ctx->transport_ptr->ops, ctx->lcid, id, reuse); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ret; } EXPORT_SYMBOL(glink_rx_done); @@ -3279,7 +3257,7 @@ int glink_sigs_set(void *handle, uint32_t sigs) if (!ch_is_fully_opened(ctx)) { GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EBUSY; } @@ -3289,7 +3267,7 @@ int glink_sigs_set(void *handle, uint32_t sigs) ctx->lcid, ctx->lsigs); GLINK_INFO_CH(ctx, "%s: Sent SIGNAL SET command\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ret; } EXPORT_SYMBOL(glink_sigs_set); @@ -3315,12 +3293,12 @@ int glink_sigs_local_get(void *handle, uint32_t *sigs) if (!ch_is_fully_opened(ctx)) { GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EBUSY; } *sigs = ctx->lsigs; - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return 0; } EXPORT_SYMBOL(glink_sigs_local_get); @@ -3347,12 +3325,12 @@ int glink_sigs_remote_get(void *handle, uint32_t *sigs) if (!ch_is_fully_opened(ctx)) { GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EBUSY; } *sigs = ctx->rsigs; - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return 0; } EXPORT_SYMBOL(glink_sigs_remote_get); @@ -3457,7 +3435,7 @@ int glink_qos_latency(void *handle, unsigned long latency_us, size_t pkt_size) if (!ch_is_fully_opened(ctx)) { GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EBUSY; } @@ -3467,7 +3445,7 @@ int glink_qos_latency(void *handle, unsigned long latency_us, size_t pkt_size) if (ret < 0) GLINK_ERR_CH(ctx, "%s: QoS %lu:%zu cannot be met\n", __func__, latency_us, pkt_size); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ret; } EXPORT_SYMBOL(glink_qos_latency); @@ -3491,12 +3469,12 @@ int glink_qos_cancel(void *handle) if (!ch_is_fully_opened(ctx)) { GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EBUSY; } ret = glink_qos_reset_priority(ctx); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ret; } EXPORT_SYMBOL(glink_qos_cancel); @@ -3523,7 +3501,7 @@ int glink_qos_start(void *handle) if (!ch_is_fully_opened(ctx)) { GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EBUSY; } @@ -3532,7 +3510,7 @@ int glink_qos_start(void *handle) ret = glink_qos_add_ch_tx_intent(ctx); spin_unlock(&ctx->tx_lists_lock_lhc3); spin_unlock_irqrestore(&ctx->transport_ptr->tx_ready_lock_lhb3, flags); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ret; } EXPORT_SYMBOL(glink_qos_start); @@ -3560,11 +3538,11 @@ unsigned long glink_qos_get_ramp_time(void *handle, size_t pkt_size) if (!ch_is_fully_opened(ctx)) { GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return (unsigned long)-EBUSY; } - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ctx->transport_ptr->ops->get_power_vote_ramp_time( ctx->transport_ptr->ops, glink_prio_to_power_state(ctx->transport_ptr, @@ -3590,13 +3568,13 @@ int glink_start_rx_rt(void *handle) if (!ch_is_fully_opened(ctx)) { GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EBUSY; } ret = ctx->transport_ptr->ops->rx_rt_vote(ctx->transport_ptr->ops); ctx->rt_vote_on++; GLINK_INFO_CH(ctx, "%s: Voting RX Realtime Thread %d", __func__, ret); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ret; } @@ -3617,13 +3595,13 @@ int glink_end_rx_rt(void *handle) if (!ch_is_fully_opened(ctx)) { GLINK_ERR_CH(ctx, "%s: Channel is not fully opened\n", __func__); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EBUSY; } ret = ctx->transport_ptr->ops->rx_rt_unvote(ctx->transport_ptr->ops); ctx->rt_vote_off++; GLINK_INFO_CH(ctx, "%s: Unvoting RX Realtime Thread %d", __func__, ret); - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ret; } @@ -3709,10 +3687,10 @@ int glink_wait_link_down(void *handle) if (ret) return ret; if (!ctx->transport_ptr) { - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return -EOPNOTSUPP; } - glink_put_ch_ctx(ctx, false); + glink_put_ch_ctx(ctx); return ctx->transport_ptr->ops->wait_link_down(ctx->transport_ptr->ops); } EXPORT_SYMBOL(glink_wait_link_down); @@ -6254,7 +6232,6 @@ EXPORT_SYMBOL(glink_get_xprt_log_ctx); static int glink_init(void) { log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "glink", 0); - rwlock_init(&magic_lock); if (!log_ctx) GLINK_ERR("%s: unable to create log context\n", __func__); glink_debugfs_init(); -- 2.11.0