summaryrefslogtreecommitdiff
path: root/hif
diff options
context:
space:
mode:
authorSurabhi Vishnoi <svishnoi@codeaurora.org>2017-08-31 17:54:50 +0530
committersnandini <snandini@codeaurora.org>2017-11-05 20:37:06 -0800
commit6f752b487b336ddb12610dea95cb122fc26589b1 (patch)
tree5b145afb50c0062e6917e0544e8f38d5267bbf9d /hif
parent5b55c8e85787b7706c24ceb53923ada9a48a6a11 (diff)
downloadqca-wfi-host-cmn-6f752b487b336ddb12610dea95cb122fc26589b1.tar.gz
qcacmn: Check target address boundary before access
Athdiag procfs entry does not have address sanity check, this is resulting in invalid ioread32/iowrite32 if out of PCIE BAR address is used. Fix this by allowing address with in PCIE BAR range. Change-Id: I8365eacca7ccc4f489b7d0bda6c998384d0fec7b CRs-Fixed: 2112270
Diffstat (limited to 'hif')
-rw-r--r--hif/src/ath_procfs.c16
-rw-r--r--hif/src/dispatcher/dummy.c5
-rw-r--r--hif/src/dispatcher/dummy.h2
-rw-r--r--hif/src/dispatcher/multibus.h1
-rw-r--r--hif/src/dispatcher/multibus_ahb.c1
-rw-r--r--hif/src/dispatcher/multibus_pci.c1
-rw-r--r--hif/src/dispatcher/multibus_sdio.c1
-rw-r--r--hif/src/dispatcher/multibus_snoc.c1
-rw-r--r--hif/src/dispatcher/multibus_usb.c1
-rw-r--r--hif/src/pcie/if_pci.c16
-rw-r--r--hif/src/pcie/if_pci.h6
11 files changed, 44 insertions, 7 deletions
diff --git a/hif/src/ath_procfs.c b/hif/src/ath_procfs.c
index 6a9ae11dd..d18b82a3f 100644
--- a/hif/src/ath_procfs.c
+++ b/hif/src/ath_procfs.c
@@ -73,17 +73,21 @@ static ssize_t ath_procfs_diag_read(struct file *file, char __user *buf,
uint32_t offset = 0, memtype = 0;
struct hif_target_info *tgt_info;
+ hif_hdl = get_hif_hdl_from_file(file);
+ scn = HIF_GET_SOFTC(hif_hdl);
+
+ if (scn->bus_ops.hif_addr_in_boundary(hif_hdl, (uint32_t)(*pos)))
+ return -EINVAL;
+
read_buffer = qdf_mem_malloc(count);
if (NULL == read_buffer) {
HIF_ERROR("%s: cdf_mem_alloc failed", __func__);
return -ENOMEM;
}
- hif_hdl = get_hif_hdl_from_file(file);
HIF_DBG("rd buff 0x%pK cnt %zu offset 0x%x buf 0x%pK",
read_buffer, count, (int)*pos, buf);
- scn = HIF_GET_SOFTC(hif_hdl);
tgt_info = hif_get_target_info_handle(GET_HIF_OPAQUE_HDL(hif_hdl));
if (scn->bus_type == QDF_BUS_TYPE_SNOC ||
(scn->bus_type == QDF_BUS_TYPE_PCI &&
@@ -133,6 +137,12 @@ static ssize_t ath_procfs_diag_write(struct file *file,
uint32_t offset = 0, memtype = 0;
struct hif_target_info *tgt_info;
+ hif_hdl = get_hif_hdl_from_file(file);
+ scn = HIF_GET_SOFTC(hif_hdl);
+
+ if (scn->bus_ops.hif_addr_in_boundary(hif_hdl, (uint32_t)(*pos)))
+ return -EINVAL;
+
write_buffer = qdf_mem_malloc(count);
if (NULL == write_buffer) {
HIF_ERROR("%s: cdf_mem_alloc failed", __func__);
@@ -145,12 +155,10 @@ static ssize_t ath_procfs_diag_write(struct file *file,
return -EFAULT;
}
- hif_hdl = get_hif_hdl_from_file(file);
HIF_DBG("wr buff 0x%pK buf 0x%pK cnt %zu offset 0x%x value 0x%x",
write_buffer, buf, count,
(int)*pos, *((uint32_t *) write_buffer));
- scn = HIF_GET_SOFTC(hif_hdl);
tgt_info = hif_get_target_info_handle(GET_HIF_OPAQUE_HDL(hif_hdl));
if (scn->bus_type == QDF_BUS_TYPE_SNOC ||
(scn->bus_type == QDF_BUS_TYPE_PCI &&
diff --git a/hif/src/dispatcher/dummy.c b/hif/src/dispatcher/dummy.c
index 88dc45c7b..b88293a3b 100644
--- a/hif/src/dispatcher/dummy.c
+++ b/hif/src/dispatcher/dummy.c
@@ -372,3 +372,8 @@ int hif_dummy_map_ce_to_irq(struct hif_softc *scn, int ce_id)
return -(1);
}
+int hif_dummy_addr_in_boundary(struct hif_softc *scn, uint32_t offset)
+{
+ return 0;
+}
+
diff --git a/hif/src/dispatcher/dummy.h b/hif/src/dispatcher/dummy.h
index b32df0974..b02183234 100644
--- a/hif/src/dispatcher/dummy.h
+++ b/hif/src/dispatcher/dummy.h
@@ -66,4 +66,4 @@ void hif_dummy_set_bundle_mode(struct hif_softc *hif_ctx,
bool enabled, int rx_bundle_cnt);
int hif_dummy_bus_reset_resume(struct hif_softc *hif_ctx);
int hif_dummy_map_ce_to_irq(struct hif_softc *scn, int ce_id);
-
+int hif_dummy_addr_in_boundary(struct hif_softc *scn, uint32_t offset);
diff --git a/hif/src/dispatcher/multibus.h b/hif/src/dispatcher/multibus.h
index 8acab762a..2bbb586d2 100644
--- a/hif/src/dispatcher/multibus.h
+++ b/hif/src/dispatcher/multibus.h
@@ -87,6 +87,7 @@ struct hif_bus_ops {
int rx_bundle_cnt);
int (*hif_bus_reset_resume)(struct hif_softc *hif_ctx);
int (*hif_map_ce_to_irq)(struct hif_softc *hif_sc, int ce_id);
+ int (*hif_addr_in_boundary)(struct hif_softc *scn, uint32_t offset);
};
#ifdef HIF_SNOC
diff --git a/hif/src/dispatcher/multibus_ahb.c b/hif/src/dispatcher/multibus_ahb.c
index 0b6e40750..960f8cea6 100644
--- a/hif/src/dispatcher/multibus_ahb.c
+++ b/hif/src/dispatcher/multibus_ahb.c
@@ -67,6 +67,7 @@ QDF_STATUS hif_initialize_ahb_ops(struct hif_bus_ops *bus_ops)
bus_ops->hif_disable_power_management =
&hif_dummy_disable_power_management;
bus_ops->hif_grp_irq_configure = &hif_ahb_configure_grp_irq;
+ bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
return QDF_STATUS_SUCCESS;
}
diff --git a/hif/src/dispatcher/multibus_pci.c b/hif/src/dispatcher/multibus_pci.c
index 4c93600d1..332e3b047 100644
--- a/hif/src/dispatcher/multibus_pci.c
+++ b/hif/src/dispatcher/multibus_pci.c
@@ -88,6 +88,7 @@ QDF_STATUS hif_initialize_pci_ops(struct hif_softc *hif_sc)
&hif_pci_display_stats;
bus_ops->hif_clear_stats =
&hif_pci_clear_stats;
+ bus_ops->hif_addr_in_boundary = &hif_pci_addr_in_boundary;
/* default to legacy mapping handler; override as needed */
bus_ops->hif_map_ce_to_irq = &hif_pci_legacy_map_ce_to_irq;
diff --git a/hif/src/dispatcher/multibus_sdio.c b/hif/src/dispatcher/multibus_sdio.c
index 4b5163fed..ab1641cd4 100644
--- a/hif/src/dispatcher/multibus_sdio.c
+++ b/hif/src/dispatcher/multibus_sdio.c
@@ -64,6 +64,7 @@ QDF_STATUS hif_initialize_sdio_ops(struct hif_softc *hif_sc)
&hif_dummy_enable_power_management;
bus_ops->hif_disable_power_management =
&hif_dummy_disable_power_management;
+ bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
return QDF_STATUS_SUCCESS;
}
diff --git a/hif/src/dispatcher/multibus_snoc.c b/hif/src/dispatcher/multibus_snoc.c
index 5edb37124..9c2193b9d 100644
--- a/hif/src/dispatcher/multibus_snoc.c
+++ b/hif/src/dispatcher/multibus_snoc.c
@@ -82,6 +82,7 @@ QDF_STATUS hif_initialize_snoc_ops(struct hif_bus_ops *bus_ops)
bus_ops->hif_clear_stats =
&hif_snoc_clear_stats;
bus_ops->hif_map_ce_to_irq = &hif_snoc_map_ce_to_irq;
+ bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
return QDF_STATUS_SUCCESS;
}
diff --git a/hif/src/dispatcher/multibus_usb.c b/hif/src/dispatcher/multibus_usb.c
index bbe5d9b34..68f73bc7c 100644
--- a/hif/src/dispatcher/multibus_usb.c
+++ b/hif/src/dispatcher/multibus_usb.c
@@ -64,6 +64,7 @@ QDF_STATUS hif_initialize_usb_ops(struct hif_bus_ops *bus_ops)
&hif_dummy_disable_power_management;
bus_ops->hif_set_bundle_mode = hif_usb_set_bundle_mode;
bus_ops->hif_bus_reset_resume = hif_usb_bus_reset_resume;
+ bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
return QDF_STATUS_SUCCESS;
}
diff --git a/hif/src/pcie/if_pci.c b/hif/src/pcie/if_pci.c
index e4392142b..ddd147746 100644
--- a/hif/src/pcie/if_pci.c
+++ b/hif/src/pcie/if_pci.c
@@ -2208,6 +2208,7 @@ static int hif_enable_pci(struct hif_pci_softc *sc,
__func__, sc->mem);
}
+ sc->mem_len = pci_resource_len(pdev, BAR_NUM);
ol_sc->mem = mem;
ol_sc->mem_pa = pci_resource_start(pdev, BAR_NUM);
sc->pci_enabled = true;
@@ -4464,3 +4465,18 @@ int hif_pci_legacy_map_ce_to_irq(struct hif_softc *scn, int ce_id)
/* legacy case only has one irq */
return pci_scn->irq;
}
+
+int hif_pci_addr_in_boundary(struct hif_softc *scn, uint32_t offset)
+{
+ struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
+
+ if ((offset >= DRAM_BASE_ADDRESS && offset <= DRAM_BASE_ADDRESS + DRAM_SIZE)
+ || (offset + sizeof(unsigned int) <= sc->mem_len)) {
+ return 0;
+ }
+
+ HIF_TRACE("Refusing to read memory at 0x%x - 0x%lx (max 0x%zx)\n",
+ offset, offset + sizeof(unsigned int), sc->mem_len);
+
+ return -EINVAL;
+}
diff --git a/hif/src/pcie/if_pci.h b/hif/src/pcie/if_pci.h
index 98bfbd726..991be8379 100644
--- a/hif/src/pcie/if_pci.h
+++ b/hif/src/pcie/if_pci.h
@@ -33,6 +33,7 @@
#include <linux/interrupt.h>
#define ATH_DBG_DEFAULT 0
+#define DRAM_SIZE 0x000a8000
#include "hif.h"
#include "cepci.h"
#include "ce_main.h"
@@ -109,9 +110,9 @@ struct hif_msi_info {
struct hif_pci_softc {
struct HIF_CE_state ce_sc;
void __iomem *mem; /* PCI address. */
- /* For efficiency, should be first in struct */
+ size_t mem_len;
- struct device *dev;
+ struct device *dev; /* For efficiency, should be first in struct */
struct pci_dev *pdev;
int num_msi_intrs; /* number of MSI interrupts granted */
/* 0 --> using legacy PCI line interrupts */
@@ -148,6 +149,7 @@ int hif_configure_irq(struct hif_softc *sc);
void hif_pci_cancel_deferred_target_sleep(struct hif_softc *scn);
void wlan_tasklet(unsigned long data);
irqreturn_t hif_pci_interrupt_handler(int irq, void *arg);
+int hif_pci_addr_in_boundary(struct hif_softc *scn, uint32_t offset);
/*
* A firmware interrupt to the Host is indicated by the