Static analysis reports that 'queue' may be a user controlled value that
is used as a data dependency to read 'txq_params' from the
'priv->tx_queue_params.params' array.  In order to avoid potential leaks
of kernel memory values, block speculative execution of the instruction
stream that could issue reads based on an invalid value of 'txq_params'.
In this case 'txq_params' is referenced later in the function.

Based on an original patch by Elena Reshetova.

Cc: Solomon Peachy <pi...@shaftnet.org>
Cc: Kalle Valo <kv...@codeaurora.org>
Cc: linux-wirel...@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
Signed-off-by: Dan Williams <dan.j.willi...@intel.com>
---
 drivers/net/wireless/st/cw1200/sta.c |   10 ++++++----
 drivers/net/wireless/st/cw1200/wsm.h |    4 +---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/st/cw1200/sta.c 
b/drivers/net/wireless/st/cw1200/sta.c
index 38678e9a0562..886942617f14 100644
--- a/drivers/net/wireless/st/cw1200/sta.c
+++ b/drivers/net/wireless/st/cw1200/sta.c
@@ -14,6 +14,7 @@
 #include <linux/firmware.h>
 #include <linux/module.h>
 #include <linux/etherdevice.h>
+#include <linux/compiler.h>
 
 #include "cw1200.h"
 #include "sta.h"
@@ -612,18 +613,19 @@ int cw1200_conf_tx(struct ieee80211_hw *dev, struct 
ieee80211_vif *vif,
                   u16 queue, const struct ieee80211_tx_queue_params *params)
 {
        struct cw1200_common *priv = dev->priv;
+       struct wsm_set_tx_queue_params *txq_params;
        int ret = 0;
        /* To prevent re-applying PM request OID again and again*/
        bool old_uapsd_flags;
 
        mutex_lock(&priv->conf_mutex);
 
-       if (queue < dev->queues) {
+       if ((txq_params = nospec_array_ptr(priv->tx_queue_params.params,
+                                       queue, dev->queues))) {
                old_uapsd_flags = le16_to_cpu(priv->uapsd_info.uapsd_flags);
 
-               WSM_TX_QUEUE_SET(&priv->tx_queue_params, queue, 0, 0, 0);
-               ret = wsm_set_tx_queue_params(priv,
-                                             
&priv->tx_queue_params.params[queue], queue);
+               WSM_TX_QUEUE_SET(txq_params, 0, 0, 0);
+               ret = wsm_set_tx_queue_params(priv, txq_params, queue);
                if (ret) {
                        ret = -EINVAL;
                        goto out;
diff --git a/drivers/net/wireless/st/cw1200/wsm.h 
b/drivers/net/wireless/st/cw1200/wsm.h
index 48086e849515..8c8d9191e233 100644
--- a/drivers/net/wireless/st/cw1200/wsm.h
+++ b/drivers/net/wireless/st/cw1200/wsm.h
@@ -1099,10 +1099,8 @@ struct wsm_tx_queue_params {
 };
 
 
-#define WSM_TX_QUEUE_SET(queue_params, queue, ack_policy, allowed_time,\
-               max_life_time)  \
+#define WSM_TX_QUEUE_SET(p, ack_policy, allowed_time, max_life_time)   \
 do {                                                   \
-       struct wsm_set_tx_queue_params *p = &(queue_params)->params[queue]; \
        p->ackPolicy = (ack_policy);                            \
        p->allowedMediumTime = (allowed_time);                          \
        p->maxTransmitLifetime = (max_life_time);                       \

Reply via email to