From 146047ddb040b5515b8aeab3f52fb0cde0c67d3d Mon Sep 17 00:00:00 2001 From: Tony Truong Date: Thu, 31 Mar 2016 12:06:24 -0700 Subject: [PATCH] msm: mhi: fix latent issues in MHI drivers Incorrect checks in MHI drivers may crash the system. Fix these checks so that MHI drivers will handle the errors gracefully. Change-Id: I462263799c2e76573300ed43b51e39ecba42914b Signed-off-by: Tony Truong --- drivers/net/ethernet/msm/msm_rmnet_mhi.c | 1 + drivers/platform/msm/mhi/mhi_ring_ops.c | 6 +++--- drivers/platform/msm/mhi/mhi_ssr.c | 4 +++- drivers/platform/msm/mhi/mhi_sys.c | 4 ++-- drivers/platform/msm/mhi_uci/mhi_uci.c | 22 +++++++++++++--------- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/msm/msm_rmnet_mhi.c b/drivers/net/ethernet/msm/msm_rmnet_mhi.c index ecdb806a2ae2..a55a26be4273 100644 --- a/drivers/net/ethernet/msm/msm_rmnet_mhi.c +++ b/drivers/net/ethernet/msm/msm_rmnet_mhi.c @@ -915,6 +915,7 @@ static void rmnet_mhi_cb(struct mhi_cb_info *cb_info) } else { rmnet_log(MSG_CRITICAL, "Invalid data in MHI callback, quitting\n"); + return; } switch (cb_info->cb_reason) { diff --git a/drivers/platform/msm/mhi/mhi_ring_ops.c b/drivers/platform/msm/mhi/mhi_ring_ops.c index a8521a7fe814..e5a6dd51f51a 100644 --- a/drivers/platform/msm/mhi/mhi_ring_ops.c +++ b/drivers/platform/msm/mhi/mhi_ring_ops.c @@ -19,7 +19,7 @@ static int add_element(struct mhi_ring *ring, void **rp, uintptr_t d_wp = 0, d_rp = 0, ring_size = 0; int r; - if (0 == ring->el_size || NULL == ring + if (NULL == ring || 0 == ring->el_size || NULL == ring->base || 0 == ring->len) { mhi_log(MHI_MSG_ERROR, "Bad input parameters, quitting.\n"); return -EINVAL; @@ -77,7 +77,7 @@ int delete_element(struct mhi_ring *ring, void **rp, uintptr_t d_wp = 0, d_rp = 0, ring_size = 0; int r; - if (0 == ring->el_size || NULL == ring || + if (NULL == ring || 0 == ring->el_size || NULL == ring->base || 0 == ring->len) return -EINVAL; @@ -143,7 +143,7 @@ int get_nr_enclosed_el(struct mhi_ring *ring, void *rp, uintptr_t ring_size = 0; int r = 0; - if (0 == ring->el_size || NULL == ring || + if (NULL == ring || 0 == ring->el_size || NULL == ring->base || 0 == ring->len) { mhi_log(MHI_MSG_ERROR, "Bad input parameters, quitting.\n"); return -EINVAL; diff --git a/drivers/platform/msm/mhi/mhi_ssr.c b/drivers/platform/msm/mhi/mhi_ssr.c index 856bb58fe013..8ee3deddbb95 100644 --- a/drivers/platform/msm/mhi/mhi_ssr.c +++ b/drivers/platform/msm/mhi/mhi_ssr.c @@ -179,7 +179,7 @@ static int set_mhi_base_state(struct mhi_pcie_dev_info *mhi_pcie_dev) void mhi_link_state_cb(struct msm_pcie_notify *notify) { int ret_val = 0; - struct mhi_pcie_dev_info *mhi_pcie_dev = notify->data; + struct mhi_pcie_dev_info *mhi_pcie_dev; struct mhi_device_ctxt *mhi_dev_ctxt = NULL; int r = 0; @@ -188,6 +188,8 @@ void mhi_link_state_cb(struct msm_pcie_notify *notify) "Incomplete handle received\n"); return; } + + mhi_pcie_dev = notify->data; mhi_dev_ctxt = &mhi_pcie_dev->mhi_ctxt; switch (notify->event) { case MSM_PCIE_EVENT_LINKDOWN: diff --git a/drivers/platform/msm/mhi/mhi_sys.c b/drivers/platform/msm/mhi/mhi_sys.c index e1bd39dfeb34..b8652770275e 100644 --- a/drivers/platform/msm/mhi/mhi_sys.c +++ b/drivers/platform/msm/mhi/mhi_sys.c @@ -53,16 +53,16 @@ static ssize_t mhi_dbgfs_chan_read(struct file *fp, char __user *buf, *offp = (u32)(*offp) % MHI_MAX_CHANNELS; while (!valid_chan) { - client_handle = mhi_dev_ctxt->client_handle_list[*offp]; if (*offp == (MHI_MAX_CHANNELS - 1)) msleep(1000); if (!VALID_CHAN_NR(*offp) || !cc_list[*offp].mhi_trb_ring_base_addr || - !client_handle) { + !mhi_dev_ctxt->client_handle_list[*offp]) { *offp += 1; *offp = (u32)(*offp) % MHI_MAX_CHANNELS; continue; } + client_handle = mhi_dev_ctxt->client_handle_list[*offp]; valid_chan = 1; } diff --git a/drivers/platform/msm/mhi_uci/mhi_uci.c b/drivers/platform/msm/mhi_uci/mhi_uci.c index 9ae1b63a75c9..d6eb96a3e89e 100644 --- a/drivers/platform/msm/mhi_uci/mhi_uci.c +++ b/drivers/platform/msm/mhi_uci/mhi_uci.c @@ -623,17 +623,20 @@ static int mhi_uci_client_release(struct inode *mhi_inode, struct file *file_handle) { struct uci_client *uci_handle = file_handle->private_data; - struct mhi_uci_ctxt_t *uci_ctxt = uci_handle->uci_ctxt; + struct mhi_uci_ctxt_t *uci_ctxt; u32 nr_in_bufs = 0; int in_chan = 0; int i = 0; u32 buf_size = 0; + + if (uci_handle == NULL) + return -EINVAL; + + uci_ctxt = uci_handle->uci_ctxt; in_chan = iminor(mhi_inode) + 1; nr_in_bufs = uci_ctxt->chan_attrib[in_chan].nr_trbs; buf_size = uci_ctxt->chan_attrib[in_chan].max_packet_size; - if (uci_handle == NULL) - return -EINVAL; if (atomic_sub_return(1, &uci_handle->ref_count) == 0) { uci_log(UCI_DBG_ERROR, "Last client left, closing channel 0x%x\n", @@ -1021,14 +1024,15 @@ static void uci_xfer_cb(struct mhi_cb_info *cb_info) u32 client_index; struct mhi_result *result; - if (!cb_info) + if (!cb_info || !cb_info->result) { uci_log(UCI_DBG_CRITICAL, "Bad CB info from MHI.\n"); - if (cb_info->result) { - chan_nr = (uintptr_t)cb_info->result->user_data; - client_index = CHAN_TO_CLIENT(chan_nr); - uci_handle = - &uci_ctxt.client_handles[client_index]; + return; } + + chan_nr = (uintptr_t)cb_info->result->user_data; + client_index = CHAN_TO_CLIENT(chan_nr); + uci_handle = &uci_ctxt.client_handles[client_index]; + switch (cb_info->cb_reason) { case MHI_CB_MHI_ENABLED: atomic_set(&uci_handle->mhi_disabled, 0); -- 2.11.0