DivestOS/Patches/Linux_CVEs/CVE-2017-11067/ANY/0.patch
2017-10-29 22:14:37 -04:00

148 lines
4.8 KiB
Diff

From a172c24c714b118cd15a5295d11e992216785a82 Mon Sep 17 00:00:00 2001
From: Govind Singh <govinds@codeaurora.org>
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