From a172c24c714b118cd15a5295d11e992216785a82 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Fri, 2 Dec 2016 15:31:18 +0530 Subject: qcacld-2.0: Check target address boundary before access LTP tests each procfs entry with random address, as athdiag procfs does not have address sanity check. This is resulting in invalid ioread32/iowrite32. Fix this by checking address with in PCIE BAR range. Change-Id: I8365eacca7ccc4f489b7d0bda6c998384d0fec7b CRs-Fixed: 1097111 --- CORE/SERVICES/COMMON/hif.h | 8 ++++++++ CORE/SERVICES/HIF/PCIe/hif_pci.c | 26 ++++++++++++++++++++++++++ CORE/SERVICES/HIF/PCIe/if_pci.c | 1 + CORE/SERVICES/HIF/PCIe/if_pci.h | 2 +- CORE/SERVICES/HIF/ath_procfs.c | 11 ++++++++--- 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/CORE/SERVICES/COMMON/hif.h b/CORE/SERVICES/COMMON/hif.h index a3c31af..06a02ee 100644 --- a/CORE/SERVICES/COMMON/hif.h +++ b/CORE/SERVICES/COMMON/hif.h @@ -880,4 +880,12 @@ static inline void hif_request_runtime_pm_resume(void *ol_sc) A_BOOL HIFIsMailBoxSwapped(HIF_DEVICE *hd); +#ifdef HIF_PCI +int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset); +#else +static inline int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset) +{ + return 0; +} +#endif #endif /* _HIF_H_ */ diff --git a/CORE/SERVICES/HIF/PCIe/hif_pci.c b/CORE/SERVICES/HIF/PCIe/hif_pci.c index 2e1d580..e640b45 100644 --- a/CORE/SERVICES/HIF/PCIe/hif_pci.c +++ b/CORE/SERVICES/HIF/PCIe/hif_pci.c @@ -3627,3 +3627,29 @@ bool hif_is_80211_fw_wow_required(void) { return false; } + +/* hif_addr_in_boundary() - API to check if addr is with in PCIE BAR range + * @hif_device: context of cd + * @offset: offset from PCI BAR mapped base address. + * + * API determines if address to be accessed is with in range or out + * of bound. + * + * Return: success if address is with in PCI BAR range. + */ +int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset) +{ + struct HIF_CE_state *hif_state; + struct hif_pci_softc *sc; + + hif_state = (struct HIF_CE_state *)hif_device; + sc = hif_state->sc; + if (unlikely(offset + sizeof(unsigned int) > sc->mem_len)) { + VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, + "refusing to read mmio out of bounds at 0x%08x - 0x%08zx (max 0x%08zx)\n", + offset, offset + sizeof(unsigned int), sc->mem_len); + return -EINVAL; + } + + return 0; +} diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c index 018855c..f4988c7 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -1682,6 +1682,7 @@ again: OS_MEMZERO(sc, sizeof(*sc)); sc->mem = mem; + sc->mem_len = pci_resource_len(pdev, BAR_NUM); sc->pdev = pdev; sc->dev = &pdev->dev; diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.h b/CORE/SERVICES/HIF/PCIe/if_pci.h index ffb4df9..0abd26a 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.h +++ b/CORE/SERVICES/HIF/PCIe/if_pci.h @@ -82,7 +82,7 @@ struct hif_pci_pm_stats { struct hif_pci_softc { void __iomem *mem; /* PCI address. */ /* For efficiency, should be first in struct */ - + size_t mem_len; struct device *dev; struct pci_dev *pdev; struct _NIC_DEV aps_osdev; diff --git a/CORE/SERVICES/HIF/ath_procfs.c b/CORE/SERVICES/HIF/ath_procfs.c index 7b653a1..cfdf97a 100644 --- a/CORE/SERVICES/HIF/ath_procfs.c +++ b/CORE/SERVICES/HIF/ath_procfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -90,13 +90,16 @@ static ssize_t ath_procfs_diag_read(struct file *file, char __user *buf, int rv; A_UINT8 *read_buffer = NULL; + hif_hdl = get_hif_hdl_from_file(file); + if (hif_addr_in_boundary(hif_hdl, (A_UINT32)(*pos))) + return -EINVAL; + read_buffer = (A_UINT8 *)vos_mem_malloc(count); if (NULL == read_buffer) { pr_debug("%s: vos_mem_alloc failed\n", __func__); return -EINVAL; } - hif_hdl = get_hif_hdl_from_file(file); pr_debug("rd buff 0x%p cnt %zu offset 0x%x buf 0x%p\n", read_buffer,count, (int)*pos, buf); @@ -130,6 +133,9 @@ static ssize_t ath_procfs_diag_write(struct file *file, const char __user *buf, int rv; A_UINT8 *write_buffer = NULL; + hif_hdl = get_hif_hdl_from_file(file); + if (hif_addr_in_boundary(hif_hdl, (A_UINT32)(*pos))) + return -EINVAL; write_buffer = (A_UINT8 *)vos_mem_malloc(count); if (NULL == write_buffer) { pr_debug("%s: vos_mem_alloc failed\n", __func__); @@ -140,7 +146,6 @@ static ssize_t ath_procfs_diag_write(struct file *file, const char __user *buf, return -EFAULT; } - hif_hdl = get_hif_hdl_from_file(file); pr_debug("wr buff 0x%p buf 0x%p cnt %zu offset 0x%x value 0x%x\n", write_buffer, buf, count, (int)*pos, *((A_UINT32 *)write_buffer)); -- cgit v1.1