[PATCH bluetooth-next 2/2] ieee802154: iface: fix header parse buffer overflow

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch fixes a buffer overflow for header_parse callback. This
callback is used by net/packet/af_packet.c which calls:

sll->sll_halen = dev_parse_header(skb, sll->sll_addr);

The "sll->sll_addr" is an array of eight bytes, but the size of struct
ieee802154_addr is more than eight bytes long. I got funny mac header
overwrites while dumping with wireshark/tcpdump.

I suppose with this function we can do filtering stuff by source
address, so we do if extended address then copy the full address and
"sll->sll_addr" is eight bytes long. If short address we copy a
combination with "pan_id+short_addr", the "sll->sll_addr" should be four
then. In case of none, we do nothing and "sll->sll_addr" returns zero.
This should provide some unique address matching mechanism.

Signed-off-by: Alexander Aring <alex.aring@xxxxxxxxx>
---
 include/linux/ieee802154.h |  2 ++
 net/mac802154/iface.c      | 26 +++++++++++++++++++++++---
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h
index db01492..7b1a28a 100644
--- a/include/linux/ieee802154.h
+++ b/include/linux/ieee802154.h
@@ -37,6 +37,8 @@
 #define IEEE802154_ADDR_SHORT_UNSPEC	0xfffe
 
 #define IEEE802154_EXTENDED_ADDR_LEN	8
+#define IEEE802154_SHORT_ADDR_LEN	2
+#define IEEE802154_PAN_ID_LEN		2
 
 #define IEEE802154_LIFS_PERIOD		40
 #define IEEE802154_SIFS_PERIOD		12
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
index ed26952..87e4183 100644
--- a/net/mac802154/iface.c
+++ b/net/mac802154/iface.c
@@ -427,15 +427,35 @@ static int
 mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
 {
 	struct ieee802154_hdr hdr;
-	struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
+	int pos = 0;
 
 	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) {
 		pr_debug("malformed packet\n");
 		return 0;
 	}
 
-	*addr = hdr.source;
-	return sizeof(*addr);
+	switch (hdr.source.mode) {
+	case IEEE802154_ADDR_LONG:
+		memcpy(haddr + pos, &hdr.source.extended_addr,
+		       IEEE802154_EXTENDED_ADDR_LEN);
+		pos += IEEE802154_EXTENDED_ADDR_LEN;
+		break;
+	case IEEE802154_ADDR_SHORT:
+		memcpy(haddr + pos, &hdr.source.pan_id,
+		       IEEE802154_PAN_ID_LEN);
+		pos += IEEE802154_PAN_ID_LEN;
+		memcpy(haddr + pos, &hdr.source.short_addr,
+		       IEEE802154_SHORT_ADDR_LEN);
+		pos += IEEE802154_SHORT_ADDR_LEN;
+		break;
+	case IEEE802154_ADDR_NONE:
+		/* fall-through */
+
+	default:
+		break;
+	}
+
+	return pos;
 }
 
 static struct header_ops mac802154_header_ops = {
-- 
2.5.1

--
To unsubscribe from this list: send the line "unsubscribe linux-wpan" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux