diff options
| author | Surabhi Vishnoi <svishnoi@codeaurora.org> | 2017-08-31 17:54:50 +0530 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2017-10-09 02:43:32 -0700 |
| commit | e54d4de979419b68cb6f7a73c96923d2af036b58 (patch) | |
| tree | 54e5f8ab0e47b999976c450648976807b00855e5 | |
| parent | 689f438e735d87ddaeabe710a8022cf2377f03e1 (diff) | |
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
| -rw-r--r-- | hif/src/ath_procfs.c | 16 | ||||
| -rw-r--r-- | hif/src/dispatcher/dummy.c | 6 | ||||
| -rw-r--r-- | hif/src/dispatcher/dummy.h | 2 | ||||
| -rw-r--r-- | hif/src/dispatcher/multibus.h | 1 | ||||
| -rw-r--r-- | hif/src/dispatcher/multibus_ahb.c | 3 | ||||
| -rw-r--r-- | hif/src/dispatcher/multibus_pci.c | 3 | ||||
| -rw-r--r-- | hif/src/dispatcher/multibus_sdio.c | 3 | ||||
| -rw-r--r-- | hif/src/dispatcher/multibus_snoc.c | 1 | ||||
| -rw-r--r-- | hif/src/dispatcher/multibus_usb.c | 3 | ||||
| -rw-r--r-- | hif/src/pcie/if_pci.c | 14 | ||||
| -rw-r--r-- | hif/src/pcie/if_pci.h | 5 |
11 files changed, 46 insertions, 11 deletions
diff --git a/hif/src/ath_procfs.c b/hif/src/ath_procfs.c index 93a14ddd1ed7..30a87087b962 100644 --- a/hif/src/ath_procfs.c +++ b/hif/src/ath_procfs.c @@ -72,17 +72,21 @@ static ssize_t ath_procfs_diag_read(struct file *file, char __user *buf, struct hif_softc *scn; uint32_t offset = 0, memtype = 0; + 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); if (scn->bus_type == QDF_BUS_TYPE_SNOC) { memtype = ((uint32_t)(*pos) & 0xff000000) >> 24; offset = (uint32_t)(*pos) & 0xffffff; @@ -127,6 +131,12 @@ static ssize_t ath_procfs_diag_write(struct file *file, struct hif_softc *scn; uint32_t offset = 0, memtype = 0; + 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__); @@ -139,12 +149,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); if (scn->bus_type == QDF_BUS_TYPE_SNOC) { memtype = ((uint32_t)(*pos) & 0xff000000) >> 24; offset = (uint32_t)(*pos) & 0xffffff; diff --git a/hif/src/dispatcher/dummy.c b/hif/src/dispatcher/dummy.c index bfe6bc9c3abe..45380807b3c7 100644 --- a/hif/src/dispatcher/dummy.c +++ b/hif/src/dispatcher/dummy.c @@ -331,3 +331,9 @@ int hif_dummy_bus_reset_resume(struct hif_softc *hif_ctx) { return 0; } + +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 58557e177343..b82957a206bb 100644 --- a/hif/src/dispatcher/dummy.h +++ b/hif/src/dispatcher/dummy.h @@ -60,4 +60,4 @@ void hif_dummy_clear_stats(struct hif_softc *hif_ctx); 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_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 3247869624a8..cd46b2cc2440 100644 --- a/hif/src/dispatcher/multibus.h +++ b/hif/src/dispatcher/multibus.h @@ -83,6 +83,7 @@ struct hif_bus_ops { void (*hif_set_bundle_mode)(struct hif_softc *hif_ctx, bool enabled, int rx_bundle_cnt); int (*hif_bus_reset_resume)(struct hif_softc *hif_ctx); + 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 d1bee78d6070..fb486fe052ec 100644 --- a/hif/src/dispatcher/multibus_ahb.c +++ b/hif/src/dispatcher/multibus_ahb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -66,6 +66,7 @@ QDF_STATUS hif_initialize_ahb_ops(struct hif_bus_ops *bus_ops) &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_pci.c b/hif/src/dispatcher/multibus_pci.c index 545910515884..2dd5f6d1e751 100644 --- a/hif/src/dispatcher/multibus_pci.c +++ b/hif/src/dispatcher/multibus_pci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -85,6 +85,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; return QDF_STATUS_SUCCESS; } diff --git a/hif/src/dispatcher/multibus_sdio.c b/hif/src/dispatcher/multibus_sdio.c index fc272025516a..ab1641cd48d4 100644 --- a/hif/src/dispatcher/multibus_sdio.c +++ b/hif/src/dispatcher/multibus_sdio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -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 b9b41755fb40..01c4da1eecfa 100644 --- a/hif/src/dispatcher/multibus_snoc.c +++ b/hif/src/dispatcher/multibus_snoc.c @@ -81,6 +81,7 @@ QDF_STATUS hif_initialize_snoc_ops(struct hif_bus_ops *bus_ops) &hif_snoc_display_stats; bus_ops->hif_clear_stats = &hif_snoc_clear_stats; + 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 0f3af6007cb8..68f73bc7cd2e 100644 --- a/hif/src/dispatcher/multibus_usb.c +++ b/hif/src/dispatcher/multibus_usb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -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 c785585df1a5..02f9767fdae5 100644 --- a/hif/src/pcie/if_pci.c +++ b/hif/src/pcie/if_pci.c @@ -2134,6 +2134,7 @@ static int hif_enable_pci(struct hif_pci_softc *sc, goto err_iomap; } sc->mem = mem; + sc->mem_len = pci_resource_len(pdev, BAR_NUM); sc->pdev = pdev; sc->dev = &pdev->dev; sc->devid = id->device; @@ -4125,3 +4126,16 @@ void hif_runtime_lock_deinit(struct hif_opaque_softc *hif_ctx, qdf_mem_free(context); } #endif /* FEATURE_RUNTIME_PM */ + +int hif_pci_addr_in_boundary(struct hif_softc *scn, uint32_t offset) +{ + struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn); + + if (unlikely(offset + sizeof(unsigned int) > sc->mem_len)) { + HIF_TRACE("Refusing to read memory at 0x%x - 0x%x (max 0x%x)\n", + offset, offset + sizeof(unsigned int), sc->mem_len); + return -EINVAL; + } + + return 0; +} diff --git a/hif/src/pcie/if_pci.h b/hif/src/pcie/if_pci.h index b515f6cce195..3a42a4a532ee 100644 --- a/hif/src/pcie/if_pci.h +++ b/hif/src/pcie/if_pci.h @@ -109,9 +109,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 */ @@ -149,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 |
