From cd776a6894f9bee212de74897c808f2db443f2b8 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Fri, 22 Jan 2010 00:29:43 -0800 Subject: [PATCH] Fix issue 65. - Update unit test to trigger the failure found in the issue 65 pcap. - Increase pkt buffer to account for the IPv6 header, as a maximum size IPv6 datagram is 40 + 0xffff. - Account for IPv4 header when checking where end of fragment lies. - Second sanity check during re-assembly to check for writing past the end of the pkt buffer. --- src/decode.h | 2 +- src/defrag.c | 28 ++++++++++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/decode.h b/src/decode.h index f849550..f46515f 100644 --- a/src/decode.h +++ b/src/decode.h @@ -242,7 +242,7 @@ typedef struct Packet_ int datalink; /* storage: maximum ip packet size + link header */ - uint8_t pkt[65536 + 28]; + uint8_t pkt[IPV6_HEADER_LEN + 65536 + 28]; uint32_t pktlen; /* flow */ diff --git a/src/defrag.c b/src/defrag.c index 51ffd1e..d220f63 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -514,6 +514,13 @@ DefragInsertFrag(DefragContext *dc, DefragTracker *tracker, Packet *p) data_len = IPV4_GET_IPLEN(p) - hlen; frag_end = frag_offset + data_len; ip_hdr_offset = (uint8_t *)p->ip4h - p->pkt; + + /* Ignore fragment if the end of packet extends past the + * maximum size of a packet. */ + if (IPV4_HEADER_LEN + frag_offset + data_len > IPV4_MAXPACKET_LEN) { + /** \todo Perhaps log something? */ + return; + } } else if (tracker->family == AF_INET6) { more_frags = IPV6_EXTHDR_GET_FH_FLAG(p); @@ -525,6 +532,13 @@ DefragInsertFrag(DefragContext *dc, DefragTracker *tracker, Packet *p) frag_end = frag_offset + data_len; ip_hdr_offset = (uint8_t *)p->ip6h - p->pkt; frag_hdr_offset = (uint8_t *)p->ip6eh.ip6fh - p->pkt; + + /* Ignore fragment if the end of packet extends past the + * maximum size of a packet. */ + if (frag_offset + data_len > IPV6_MAXPACKET) { + /** \todo Perhaps log something? */ + return; + } } else { /* Abort - should not happen. */ @@ -532,11 +546,6 @@ DefragInsertFrag(DefragContext *dc, DefragTracker *tracker, Packet *p) exit(EXIT_FAILURE); } - if (frag_offset + data_len > IPV4_MAXPACKET_LEN) { - /* \todo Log this - packet is too large to be re-assembled. */ - return; - } - /* Lock this tracker as we'll be doing list operations on it. */ SCMutexLock(&tracker->lock); @@ -762,8 +771,11 @@ Defrag4Reassemble(ThreadVars *tv, DefragContext *dc, DefragTracker *tracker, fragmentable_len = frag->data_len; } else { - BUG_ON(fragmentable_offset + frag->offset + frag->data_len > - (int)sizeof(rp->pkt)); + int pkt_end = fragmentable_offset + frag->offset + frag->data_len; + if (pkt_end > (int)sizeof(rp->pkt)) { + SCLogWarning(SC_ERR_REASSEMBLY_FAILED, "Failed re-assemble fragmented packet, exceeds size of packet buffer."); + goto remove_tracker; + } memcpy(rp->pkt + fragmentable_offset + frag->offset + frag->ltrim, frag->pkt + frag->data_offset + frag->ltrim, frag->data_len - frag->ltrim); @@ -2376,7 +2388,7 @@ DefragIPv4TooLargeTest(void) /* Create a fragment that would extend past the max allowable size * for an IPv4 packet. */ - p = BuildTestPacket(1, 8190, 0, 'A', 8192); + p = BuildTestPacket(1, 8183, 0, 'A', 71); if (p == NULL) goto end; -- 1.6.6