From acddcfffa0d187f6050931229f6fe8fbe5d47ddd Mon Sep 17 00:00:00 2001 From: Dhoat Harpal Date: Fri, 23 Jun 2017 20:12:15 +0530 Subject: [PATCH] soc: qcom: glink_pkt: fix number of intent queued glink_pkt driver has no limit on number of intents auto queued for rx. Intent are auto queued when remote side request for intent without checking how many packets are pending to be read by client. A max limit check is added to avoid memory exhaustion case with indefinite intent queueing. CRs-Fixed: 2042581 Change-Id: I68aa102b323716f591841b192477a70397a5536b Signed-off-by: Dhoat Harpal --- drivers/soc/qcom/msm_glink_pkt.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/msm_glink_pkt.c b/drivers/soc/qcom/msm_glink_pkt.c index a92e5c416678..0a80016f1942 100644 --- a/drivers/soc/qcom/msm_glink_pkt.c +++ b/drivers/soc/qcom/msm_glink_pkt.c @@ -33,7 +33,8 @@ #include #include - +/* This Limit ensures that auto queue will not exhaust memory on remote side */ +#define MAX_PENDING_GLINK_PKT 5 #define MODULE_NAME "msm_glinkpkt" #define DEVICE_NAME "glinkpkt" #define WAKEUPSOURCE_TIMEOUT (2000) /* two seconds */ @@ -136,6 +137,7 @@ struct glink_pkt_dev { struct glink_link_info link_info; void *link_state_handle; bool link_up; + bool auto_intent_enabled; }; /** @@ -447,8 +449,26 @@ void glink_pkt_notify_state(void *handle, const void *priv, unsigned event) bool glink_pkt_rmt_rx_intent_req_cb(void *handle, const void *priv, size_t sz) { struct queue_rx_intent_work *work_item; + int pending_pkt_count = 0; + struct glink_rx_pkt *pkt = NULL; + unsigned long flags; + struct glink_pkt_dev *devp = (struct glink_pkt_dev *)priv; + GLINK_PKT_INFO("%s(): QUEUE RX INTENT to receive size[%zu]\n", __func__, sz); + if (devp->auto_intent_enabled) { + spin_lock_irqsave(&devp->pkt_list_lock, flags); + list_for_each_entry(pkt, &devp->pkt_list, list) + pending_pkt_count++; + spin_unlock_irqrestore(&devp->pkt_list_lock, flags); + if (pending_pkt_count > MAX_PENDING_GLINK_PKT) { + GLINK_PKT_ERR("%s failed, max limit reached\n", + __func__); + return false; + } + } else { + return false; + } work_item = kzalloc(sizeof(*work_item), GFP_ATOMIC); if (!work_item) { @@ -457,7 +477,7 @@ bool glink_pkt_rmt_rx_intent_req_cb(void *handle, const void *priv, size_t sz) } work_item->intent_size = sz; - work_item->devp = (struct glink_pkt_dev *)priv; + work_item->devp = devp; INIT_WORK(&work_item->work, glink_pkt_queue_rx_intent_worker); queue_work(glink_pkt_wq, &work_item->work); @@ -626,10 +646,11 @@ ssize_t glink_pkt_read(struct file *file, } mutex_lock(&devp->ch_lock); - if (!glink_rx_intent_exists(devp->handle, count)) { + if (!glink_pkt_read_avail(devp) && + !glink_rx_intent_exists(devp->handle, count)) { ret = glink_queue_rx_intent(devp->handle, devp, count); if (ret) { - GLINK_PKT_ERR("%s: failed to queue_rx_intent ret[%d]\n", + GLINK_PKT_ERR("%s: failed to queue intent ret[%d]\n", __func__, ret); mutex_unlock(&devp->ch_lock); return ret; @@ -915,6 +936,7 @@ static long glink_pkt_ioctl(struct file *file, unsigned int cmd, case GLINK_PKT_IOCTL_QUEUE_RX_INTENT: ret = get_user(size, (uint32_t *)arg); GLINK_PKT_INFO("%s: intent size[%d]\n", __func__, size); + devp->auto_intent_enabled = false; ret = glink_queue_rx_intent(devp->handle, devp, size); if (ret) { GLINK_PKT_ERR("%s: failed to QUEUE_RX_INTENT ret[%d]\n", @@ -1183,6 +1205,7 @@ static int glink_pkt_init_add_device(struct glink_pkt_dev *devp, int i) glink_pkt_link_state_cb; devp->i = i; devp->poll_mode = 0; + devp->auto_intent_enabled = true; devp->ws_locked = 0; devp->ch_state = GLINK_LOCAL_DISCONNECTED; /* Default timeout for open wait is 120sec */