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