wil6210: fix length check in __wmi_send
authorLior David <qca_liord@qca.qualcomm.com>
Tue, 21 Apr 2020 12:40:13 +0000 (13:40 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 24 Apr 2020 06:01:08 +0000 (08:01 +0200)
[ Upstream commit 26a6d5274865532502c682ff378ac8ebe2886238 ]

The current length check:
sizeof(cmd) + len > r->entry_size
will allow very large values of len (> U16_MAX - sizeof(cmd))
and can cause a buffer overflow. Fix the check to cover this case.
In addition, ensure the mailbox entry_size is not too small,
since this can also bypass the above check.

Signed-off-by: Lior David <qca_liord@qca.qualcomm.com>
Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/wireless/ath/wil6210/interrupt.c
drivers/net/wireless/ath/wil6210/wmi.c

index 59def4f3fcf3dcb1e65fead988befe4dae02b226..5cf341702dc117cf6d0c362fa648bb836de9002e 100644 (file)
@@ -358,6 +358,25 @@ static void wil_cache_mbox_regs(struct wil6210_priv *wil)
        wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
 }
 
+static bool wil_validate_mbox_regs(struct wil6210_priv *wil)
+{
+       size_t min_size = sizeof(struct wil6210_mbox_hdr) +
+               sizeof(struct wmi_cmd_hdr);
+
+       if (wil->mbox_ctl.rx.entry_size < min_size) {
+               wil_err(wil, "rx mbox entry too small (%d)\n",
+                       wil->mbox_ctl.rx.entry_size);
+               return false;
+       }
+       if (wil->mbox_ctl.tx.entry_size < min_size) {
+               wil_err(wil, "tx mbox entry too small (%d)\n",
+                       wil->mbox_ctl.tx.entry_size);
+               return false;
+       }
+
+       return true;
+}
+
 static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
 {
        struct wil6210_priv *wil = cookie;
@@ -393,7 +412,8 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
        if (isr & ISR_MISC_FW_READY) {
                wil_dbg_irq(wil, "IRQ: FW ready\n");
                wil_cache_mbox_regs(wil);
-               set_bit(wil_status_mbox_ready, wil->status);
+               if (wil_validate_mbox_regs(wil))
+                       set_bit(wil_status_mbox_ready, wil->status);
                /**
                 * Actual FW ready indicated by the
                 * WMI_FW_READY_EVENTID
index 6cfb820caa3ee7d1080252675be5f082d0d0288d..22bfa10ea8276d991c9b85a041fe0dc4b7614e99 100644 (file)
@@ -231,7 +231,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
        uint retry;
        int rc = 0;
 
-       if (sizeof(cmd) + len > r->entry_size) {
+       if (len > r->entry_size - sizeof(cmd)) {
                wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
                        (int)(sizeof(cmd) + len), r->entry_size);
                return -ERANGE;