When there are 16 or more logical CPUs, we request for `IWL_MAX_RX_HW_QUEUES` (16)
IRQs only, but later on create `num_irqs+1` RX queues, which could end up more
than `IWL_MAX_RX_HW_QUEUES` if the OS does return us 16 IRQs. This wreaks lots
of havoc elsewhere later on due to code that uses `num_rx_queues` to calculate
array sizes.
Limit to IWL_MAX_RX_HW_QUEUES - 1 IRQs so num_rx_queues is never more than
IWL_MAX_RX_HW_QUEUES.
---
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 6e9a9ecfb11c..f5c12924c836 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1607,7 +1607,7 @@ static void iwl_pcie_set_interrupt_capa(struct pci_dev *pdev,
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, nr_online_cpus + 2, IWL_MAX_RX_HW_QUEUES - 1);
for (i = 0; i < max_irqs; i++)
trans_pcie->msix_entries[i].entry = i;
--
2.17.0
When there are 16 or more logical CPUs, we request for `IWL_MAX_RX_HW_QUEUES` (16)
IRQs only, but later on create `num_irqs+1` RX queues, which could end up more
than `IWL_MAX_RX_HW_QUEUES` if the OS does return us 16 IRQs. This wreaks lots
of havoc elsewhere later on due to code that uses `num_rx_queues` to calculate
array sizes.
Limit to IWL_MAX_RX_HW_QUEUES - 1 IRQs so num_rx_queues is never more than
IWL_MAX_RX_HW_QUEUES.
Signed-off-by: Hao Wei Tee <[email protected]>
---
My bad. Forgot to sign off.
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 6e9a9ecfb11c..f5c12924c836 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1607,7 +1607,7 @@ static void iwl_pcie_set_interrupt_capa(struct pci_dev *pdev,
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, nr_online_cpus + 2, IWL_MAX_RX_HW_QUEUES - 1);
for (i = 0; i < max_irqs; i++)
trans_pcie->msix_entries[i].entry = i;
--
2.17.0
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.
Signed-off-by: Hao Wei Tee <[email protected]>
---
I think this is a better fix than what I sent previously.
But you guys are probably looking into it now, so please disregard my
probably-incorrect fix.
Thanks.
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 6e9a9ecfb11c..aa469046f86c 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1633,16 +1633,17 @@ static void iwl_pcie_set_interrupt_capa(struct pci_dev *pdev,
* 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;
--
2.17.0