iwlwifi: pcie: validate queue ID before array deref/bit ops
authorJohannes Berg <johannes.berg@intel.com>
Tue, 8 Oct 2019 14:03:15 +0000 (16:03 +0200)
committerLuca Coelho <luciano.coelho@intel.com>
Mon, 23 Dec 2019 09:54:31 +0000 (11:54 +0200)
Validate that the queue ID is in range before trying to use it as
an index or for test_bit() - the previous bug showed that this has
in fact happened, and it was lucky that we caught it there, had the
bit been set then we'd have actually used the value despite being
far out of range.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c

index 8ca0250..c3683cd 100644 (file)
@@ -587,6 +587,10 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
        int idx;
        void *tfd;
 
+       if (WARN_ONCE(txq_id >= IWL_MAX_TVQM_QUEUES,
+                     "queue %d out of range", txq_id))
+               return -EINVAL;
+
        if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used),
                      "TX on unused queue %d\n", txq_id))
                return -EINVAL;
@@ -1101,9 +1105,15 @@ void iwl_pcie_gen2_txq_free_memory(struct iwl_trans *trans,
 static void iwl_pcie_gen2_txq_free(struct iwl_trans *trans, int txq_id)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_txq *txq = trans_pcie->txq[txq_id];
+       struct iwl_txq *txq;
        int i;
 
+       if (WARN_ONCE(txq_id >= IWL_MAX_TVQM_QUEUES,
+                     "queue %d out of range", txq_id))
+               return;
+
+       txq = trans_pcie->txq[txq_id];
+
        if (WARN_ON(!txq))
                return;
 
@@ -1258,6 +1268,10 @@ void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, int queue)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
+       if (WARN(queue >= IWL_MAX_TVQM_QUEUES,
+                "queue %d out of range", queue))
+               return;
+
        /*
         * Upon HW Rfkill - we stop the device, and then stop the queues
         * in the op_mode. Just for the sake of the simplicity of the op_mode,