Fix malformed ipv6 packet causing an endless loop in exthdr decoding.

remotes/origin/master-1.0.x
Victor Julien 16 years ago
parent 2910759943
commit 54c2804ce4

@ -38,9 +38,11 @@
static void
DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
SCEnter();
uint8_t *orig_pkt = pkt;
uint8_t nh;
uint8_t hdrextlen;
uint16_t hdrextlen;
uint16_t plen;
char dstopts = 0;
char exthdr_fh_done = 0;
@ -50,31 +52,36 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
while(1)
{
if (plen < 2) /* minimal needed in a hdr */
return;
if (plen < 2) { /* minimal needed in a hdr */
SCReturn;
}
switch(nh)
{
case IPPROTO_TCP:
IPV6_SET_L4PROTO(p,nh);
DecodeTCP(tv, dtv, p, pkt, plen, pq);
return;
SCReturn;
case IPPROTO_UDP:
IPV6_SET_L4PROTO(p,nh);
DecodeUDP(tv, dtv, p, pkt, plen, pq);
return;
SCReturn;
case IPPROTO_ICMPV6:
IPV6_SET_L4PROTO(p,nh);
DecodeICMPV6(tv, dtv, p, pkt, plen, pq);
return;
SCReturn;
case IPPROTO_ROUTING:
hdrextlen = (*(pkt+1) + 1) << 3; /* 8 octet units */
hdrextlen = sizeof(IPV6RouteHdr);
hdrextlen += (*(pkt+1) * 8); /* 8 octet units */
SCLogDebug("hdrextlen %"PRIu8, hdrextlen);
if (hdrextlen > plen) {
DECODER_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
return;
SCReturn;
}
if (p->IPV6_EH_CNT < IPV6_MAX_OPT)
@ -98,7 +105,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
IPV6_EXTHDR_SET_RH(p, pkt);
IPV6_EXTHDR_RH(p)->ip6rh_len = hdrextlen;
/** \todo move into own function and load on demand */
/** \todo move into own function and load on demand */
if (IPV6_EXTHDR_RH(p)->ip6rh_type == 0) {
uint8_t i;
@ -109,7 +116,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
* sized */
for (i = 0; i < (n/8) && i < sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr)/sizeof(struct in6_addr); ++i) {
/* the address header fields are 16 bytes in size */
/** \todo do this without memcpy since it's expensive */
/** \todo do this without memcpy since it's expensive */
memcpy(&IPV6_EXTHDR_RH(p)->ip6rh0_addr[i], pkt+(i*16)+8, sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr[i]));
}
IPV6_EXTHDR_RH(p)->ip6rh0_num_addrs = i;
@ -131,7 +138,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
hdrextlen = (*(pkt+1) + 1) << 3;
if (hdrextlen > plen) {
DECODER_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
return;
SCReturn;
}
if (p->IPV6_EH_CNT < IPV6_MAX_OPT)
@ -264,7 +271,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
hdrextlen = sizeof(IPV6FragHdr);
if (hdrextlen > plen) {
DECODER_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
return;
SCReturn;
}
if(p->IPV6_EH_CNT<IPV6_MAX_OPT)
@ -297,7 +304,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
hdrextlen = sizeof(IPV6EspHdr);
if (hdrextlen > plen) {
DECODER_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
return;
SCReturn;
}
if(p->IPV6_EH_CNT<IPV6_MAX_OPT)
@ -311,7 +318,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
if (IPV6_EXTHDR_ISSET_EH(p)) {
DECODER_SET_EVENT(p, IPV6_EXTHDR_DUPL_EH);
return;
SCReturn;
}
IPV6_EXTHDR_SET_EH(p, pkt);
@ -323,10 +330,16 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
}
case IPPROTO_AH:
{
hdrextlen = (*(pkt+1) + 1) << 3;
/* we need the header as a minimum */
hdrextlen = sizeof(IPV6AuthHdr);
/* the payload len field is the number of extra 4 byte fields */
hdrextlen += (*(pkt+1)) * 4;
SCLogDebug("hdrextlen %"PRIu8, hdrextlen);
if (hdrextlen > plen) {
DECODER_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
return;
SCReturn;
}
if(p->IPV6_EH_CNT<IPV6_MAX_OPT)
@ -355,15 +368,15 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
}
case IPPROTO_NONE:
IPV6_SET_L4PROTO(p,nh);
return;
SCReturn;
default:
IPV6_SET_L4PROTO(p,nh);
return;
SCReturn;
}
}
return;
SCReturn;
}
static int DecodeIPV6Packet (ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len)

Loading…
Cancel
Save