4.14-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Hao Wei Tee <[email protected]>

[ Upstream commit ab1068d6866e28bf6427ceaea681a381e5870a4a ]

When there are 16 or more logical CPUs, we request for
`IWL_MAX_RX_HW_QUEUES` (16) IRQs only as we limit to that number of
IRQs, but later on we compare the number of IRQs returned to
nr_online_cpus+2 instead of max_irqs, the latter being what we
actually asked for. This ends up setting num_rx_queues to 17 which
causes lots of out-of-bounds array accesses later on.

Compare to max_irqs instead, and also add an assertion in case
num_rx_queues > IWM_MAX_RX_HW_QUEUES.

This fixes https://bugzilla.kernel.org/show_bug.cgi?id=199551

Fixes: 2e5d4a8f61dc ("iwlwifi: pcie: Add new configuration to enable MSIX")
Signed-off-by: Hao Wei Tee <[email protected]>
Tested-by: Sara Sharon <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1499,14 +1499,13 @@ static void iwl_pcie_set_interrupt_capa(
                                        struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       int max_irqs, num_irqs, i, ret, nr_online_cpus;
+       int max_irqs, num_irqs, i, ret;
        u16 pci_cmd;
 
        if (!trans->cfg->mq_rx_supported)
                goto enable_msi;
 
-       nr_online_cpus = num_online_cpus();
-       max_irqs = min_t(u32, nr_online_cpus + 2, IWL_MAX_RX_HW_QUEUES);
+       max_irqs = min_t(u32, num_online_cpus() + 2, IWL_MAX_RX_HW_QUEUES);
        for (i = 0; i < max_irqs; i++)
                trans_pcie->msix_entries[i].entry = i;
 
@@ -1532,16 +1531,17 @@ static void iwl_pcie_set_interrupt_capa(
         * Two interrupts less: non rx causes shared with FBQ and RSS.
         * More than two interrupts: we will use fewer RSS queues.
         */
-       if (num_irqs <= nr_online_cpus) {
+       if (num_irqs <= max_irqs - 2) {
                trans_pcie->trans->num_rx_queues = num_irqs + 1;
                trans_pcie->shared_vec_mask = IWL_SHARED_IRQ_NON_RX |
                        IWL_SHARED_IRQ_FIRST_RSS;
-       } else if (num_irqs == nr_online_cpus + 1) {
+       } else if (num_irqs == max_irqs - 1) {
                trans_pcie->trans->num_rx_queues = num_irqs;
                trans_pcie->shared_vec_mask = IWL_SHARED_IRQ_NON_RX;
        } else {
                trans_pcie->trans->num_rx_queues = num_irqs - 1;
        }
+       WARN_ON(trans_pcie->trans->num_rx_queues > IWL_MAX_RX_HW_QUEUES);
 
        trans_pcie->alloc_vecs = num_irqs;
        trans_pcie->msix_enabled = true;


Reply via email to