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
This commit is contained in:
committed by
snandini
parent
5b55c8e857
commit
6f752b487b
@@ -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 &&
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user