[PATCH wireless-next 1/3] wifi: nxpwifi: validate the length of the VDLL indication event

Linmao Li <[email protected]>
Newsgroups org.kernel.vger.linux-wireless,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
nxpwifi_process_vdll_event() reads the ten-byte struct vdll_ind_event
that follows the four-byte event cause without checking that the event
is long enough to hold it.  The receive path does not guarantee that:
nxpwifi_sdio_decode_rx_packet() takes the event cause from the first
four bytes and hands the skb on whatever its length is, copying an
event body only when there is one.

A short event therefore makes the driver read past the end of the
buffer and then act on the type, offset and block length it finds
there.

Check the length before the header is dereferenced.

Fixes: 73b01e57ed3e ("wifi: nxp: add nxpwifi driver for IW61x")
Signed-off-by: Linmao Li <[email protected]>
---
 drivers/net/wireless/nxp/nxpwifi/util.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/nxp/nxpwifi/util.c b/drivers/net/wireless/nxp/nxpwifi/util.c
index bbfefb81d8d3b..549661ca049a0 100644
--- a/drivers/net/wireless/nxp/nxpwifi/util.c
+++ b/drivers/net/wireless/nxp/nxpwifi/util.c
@@ -1255,15 +1255,24 @@ int nxpwifi_process_vdll_event(struct nxpwifi_private *priv,
 			       struct sk_buff *skb)
 {
 	struct nxpwifi_adapter *adapter = priv->adapter;
-	struct vdll_ind_event *vdll_evt =
-		(struct vdll_ind_event *)(skb->data + sizeof(u32));
-	u16 type = le16_to_cpu(vdll_evt->type);
-	u16 vdll_id = le16_to_cpu(vdll_evt->vdll_id);
-	u32 offset = le32_to_cpu(vdll_evt->offset);
-	u16 block_len = le16_to_cpu(vdll_evt->block_len);
 	struct vdll_dnld_ctrl *ctrl = &adapter->vdll_ctrl;
+	struct vdll_ind_event *vdll_evt;
+	u16 type, vdll_id, block_len;
+	u32 offset;
 	int ret = 0;
 
+	if (skb->len < sizeof(u32) + sizeof(*vdll_evt)) {
+		nxpwifi_dbg(adapter, ERROR,
+			    "VDLL IND: event too short: %u\n", skb->len);
+		return -EINVAL;
+	}
+
+	vdll_evt = (struct vdll_ind_event *)(skb->data + sizeof(u32));
+	type = le16_to_cpu(vdll_evt->type);
+	vdll_id = le16_to_cpu(vdll_evt->vdll_id);
+	offset = le32_to_cpu(vdll_evt->offset);
+	block_len = le16_to_cpu(vdll_evt->block_len);
+
 	switch (type) {
 	case VDLL_IND_TYPE_REQ:
 		nxpwifi_dbg(adapter, EVENT,
-- 
2.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.