OSDN Git Service

msm: mhi: fix latent issues in MHI drivers
authorTony Truong <truong@codeaurora.org>
Thu, 31 Mar 2016 19:06:24 +0000 (12:06 -0700)
committerGerrit - the friendly Code Review server <code-review@localhost>
Fri, 10 Feb 2017 20:04:51 +0000 (12:04 -0800)
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 <truong@codeaurora.org>
drivers/net/ethernet/msm/msm_rmnet_mhi.c
drivers/platform/msm/mhi/mhi_ring_ops.c
drivers/platform/msm/mhi/mhi_ssr.c
drivers/platform/msm/mhi/mhi_sys.c
drivers/platform/msm/mhi_uci/mhi_uci.c

index ecdb806..a55a26b 100644 (file)
@@ -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) {
index a8521a7..e5a6dd5 100644 (file)
@@ -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;
index 856bb58..8ee3ded 100644 (file)
@@ -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:
index e1bd39d..b865277 100644 (file)
@@ -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;
        }
 
index 9ae1b63..d6eb96a 100644 (file)
@@ -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);