mm81x_yaps_read_pkt() casts skb->data to struct mm81x_skb_hdr and
accesses header fields without first verifying that the skb contains
enough data for the header structure. A malformed device response with
a valid YAPS delimiter but undersized payload would cause out-of-bounds
reads from heap memory.
Additionally, the function computes the expected packet length from
header-embedded fields (hdr->offset and hdr->len) but never checks
this against the actual skb length. Since skb_trim() only shrinks, a
claimed length exceeding the real data is silently accepted, and the
subsequent __skb_pull() in the dispatch path underflows skb->len.
Add two validation checks:
1. Verify skb->len >= sizeof(struct mm81x_skb_hdr) before accessing
any header fields.
2. Verify the header-claimed total length does not exceed the actual
skb length before enqueuing.
Fixes: b1906cea00b0 ("wifi: mm81x: add mm81x Wi-Fi HaLow driver")
Signed-off-by: Aamir Ahmed <redacted>
---
drivers/net/wireless/morsemicro/mm81x/yaps.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/net/wireless/morsemicro/mm81x/yaps.c b/drivers/net/wireless/morsemicro/mm81x/yaps.c
index e98a2a58726f..da2c88901d64 100644
--- a/drivers/net/wireless/morsemicro/mm81x/yaps.c
+++ b/drivers/net/wireless/morsemicro/mm81x/yaps.c
@@ -147,6 +147,13 @@ static int mm81x_yaps_read_pkt(struct mm81x_yaps *yaps, struct sk_buff *skb)
__skb_queue_head_init(&skbq);
+ if (skb->len < sizeof(*hdr)) {
+ dev_err(mors->dev, "packet too short for header (%u < %zu)",
+ skb->len, sizeof(*hdr));
+ ret = -EINVAL;
+ goto exit_return_page;
+ }
+
hdr = (struct mm81x_skb_hdr *)skb->data;
if (hdr->sync != MM81X_SKB_HEADER_SYNC) {
dev_err(mors->dev, "sync value error [0xAA:%d], hdr.len %d",@@ -186,6 +193,14 @@ static int mm81x_yaps_read_pkt(struct mm81x_yaps *yaps, struct sk_buff *skb)
}
skb_len = sizeof(*hdr) + hdr->offset + le16_to_cpu(hdr->len);
+ if (skb_len > skb->len) {
+ dev_err(mors->dev,
+ "header claims %d bytes but packet is only %u",
+ skb_len, skb->len);
+ ret = -EINVAL;
+ goto exit_return_page;
+ }
+
skb_bytes_remaining = mm81x_skbq_space(mq);
if (skb_len > skb_bytes_remaining) {--
2.43.0