Hello,

While playing with the 6lowpan code, I found a few more bugs. Some a not very serious as long as interoperability is not required, some other are more serious and prevent the fragment reassembly to be performed correctly (after 256 fragments have been sent) or mangle the packet length field.

I attached a patch to this mail. I hope it applies correctly, as I'm also modifying the code so that it behaves as described in the RFC (see my previous mail).

Please let me know what you think, and if you need more details.

Regards,
Tony
From e15083579d7e2b853aa022c4b84edbd091644cbd Mon Sep 17 00:00:00 2001
From: Tony Cheneau <tony.chen...@amnesiak.org>
Date: Tue, 5 Jun 2012 17:26:54 -0400
Subject: [PATCH 1/1] Fixes various u8/u16 storage/usage bugs in the 6lowpan
 code: - tag would not be passed down correctly in
 lowpan_alloc_new_frame() (pass down   a u16 to the
 function when it only accepts a u8) -
 lowpan_skb_fragmentation() and lowpan_fetch_skb_u16()
 would not   store/retrieve the data correctly -
 lowpan_process_data() and lowpan_alloc_new_frame():
 frame length would get   corrupted

---
 net/ieee802154/6lowpan.c |   26 +++++++++++++++-----------
 1 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 245d765..c9428b9 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -313,7 +313,7 @@ static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, 
u16 *val)
        if (WARN_ON_ONCE(!pskb_may_pull(skb, 2)))
                return -EINVAL;
 
-       *val = skb->data[0] | (skb->data[1] << 8);
+       *val = (skb->data[0] << 8) | skb->data[1];
        skb_pull(skb, 2);
 
        return 0;
@@ -660,7 +660,7 @@ static void lowpan_fragment_timer_expired(unsigned long 
entry_addr)
 }
 
 static struct lowpan_fragment *
-lowpan_alloc_new_frame(struct sk_buff *skb, u8 iphc0, u8 len, u8 tag)
+lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag)
 {
        struct lowpan_fragment *frame;
 
@@ -671,7 +671,7 @@ lowpan_alloc_new_frame(struct sk_buff *skb, u8 iphc0, u8 
len, u8 tag)
 
        INIT_LIST_HEAD(&frame->list);
 
-       frame->length = (iphc0 & 7) | (len << 3);
+       frame->length = len; 
        frame->tag = tag;
 
        /* allocate buffer for frame assembling */
@@ -729,14 +729,15 @@ lowpan_process_data(struct sk_buff *skb)
        case LOWPAN_DISPATCH_FRAGN:
        {
                struct lowpan_fragment *frame;
-               u8 len, offset;
-               u16 tag;
+               u8 slen, offset = 0; /* slen is short length */
+               u16 len, tag;
                bool found = false;
 
-               if (lowpan_fetch_skb_u8(skb, &len) || /* frame length */
+               if (lowpan_fetch_skb_u8(skb, &slen) || /* 8 LSB of frame length 
*/
                    lowpan_fetch_skb_u16(skb, &tag))  /* fragment tag */
                        goto drop;
 
+        len = ((iphc0 & 7) << 8) | slen; /* adds the 3 MSB to the 8 LSB to 
obtain the 11 bits length */
                /*
                 * check if frame assembling with the same tag is
                 * already in progress
@@ -751,7 +752,10 @@ lowpan_process_data(struct sk_buff *skb)
 
                /* alloc new frame structure */
                if (!found) {
-                       frame = lowpan_alloc_new_frame(skb, iphc0, len, tag);
+#ifdef DEBUG
+        printk(KERN_DEBUG "%s first fragment received for tag %d, begin packet 
reassembly", __func__, tag);
+#endif /* DEBUG */
+                       frame = lowpan_alloc_new_frame(skb, len, tag);
                        if (!frame)
                                goto unlock_and_drop;
                }
@@ -1014,10 +1018,10 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
        tag = fragment_tag++;
 
        /* first fragment header */
-       head[0] = LOWPAN_DISPATCH_FRAG1 | (payload_length & 0x7);
-       head[1] = (payload_length >> 3) & 0xff;
-       head[2] = tag & 0xff;
-       head[3] = tag >> 8;
+       head[0] = LOWPAN_DISPATCH_FRAG1 | ((payload_length >> 8) & 0x7);
+       head[1] = payload_length & 0xff;
+       head[2] = tag >> 8;
+       head[3] = tag & 0xff;
 
        err = lowpan_fragment_xmit(skb, head, header_length, 0, 0);
 
-- 
1.7.6.5

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Linux-zigbee-devel mailing list
Linux-zigbee-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

Reply via email to