From b56a2c3b3f2943cc5346649b26f3a0b39148b2bbabce3458bbbbc4249d722e4c Mon Sep 17 00:00:00 2001 From: Lars Vogdt Date: Tue, 10 Feb 2015 09:23:34 +0000 Subject: [PATCH] Accepting request 284472 from home:vitezslav_cizek:branches:network:utilities - fix CVE-2014-8767 (bnc#905870) * denial of service in verbose mode using malformed OLSR payload * added tcpdump-CVE-2014-8767.patch - fix CVE-2014-8768 (bnc#905871) * denial of service in verbose mode using malformed Geonet payload * added tcpdump-CVE-2014-8768.patch - fix CVE-2014-8769 (bnc#905872) * unreliable output using malformed AOVD payload * added tcpdump-CVE-2014-8769.patch * added 0001-Clean-up-error-message-printing.patch OBS-URL: https://build.opensuse.org/request/show/284472 OBS-URL: https://build.opensuse.org/package/show/network:utilities/tcpdump?expand=0&rev=23 --- 0001-Clean-up-error-message-printing.patch | 190 ++++++++ tcpdump-CVE-2014-8767.patch | 183 ++++++++ tcpdump-CVE-2014-8768.patch | 343 ++++++++++++++ tcpdump-CVE-2014-8769.patch | 516 +++++++++++++++++++++ tcpdump.changes | 14 + tcpdump.spec | 10 +- 6 files changed, 1255 insertions(+), 1 deletion(-) create mode 100644 0001-Clean-up-error-message-printing.patch create mode 100644 tcpdump-CVE-2014-8767.patch create mode 100644 tcpdump-CVE-2014-8768.patch create mode 100644 tcpdump-CVE-2014-8769.patch diff --git a/0001-Clean-up-error-message-printing.patch b/0001-Clean-up-error-message-printing.patch new file mode 100644 index 0000000..ead403b --- /dev/null +++ b/0001-Clean-up-error-message-printing.patch @@ -0,0 +1,190 @@ +From 3e8a443c3671baa37ae7870f08fb9b4bf386fd24 Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Tue, 11 Nov 2014 18:37:35 -0800 +Subject: [PATCH] Clean up error message printing. + +Have "struct aodv_rerr" just be the header, not including the actual +destinations. + +Simplify the logic somewhat, and make it similar in the print routines +for the three types of error messages. +--- + print-aodv.c | 88 +++++++++++++++++++++++++++++++----------------------------- + 1 file changed, 46 insertions(+), 42 deletions(-) + +diff --git a/print-aodv.c b/print-aodv.c +index da5b169..da26473 100644 +--- a/print-aodv.c ++++ b/print-aodv.c +@@ -146,13 +146,6 @@ struct aodv_rerr { + uint8_t rerr_flags; /* various flags */ + uint8_t rerr_zero0; /* reserved, set to zero */ + uint8_t rerr_dc; /* destination count */ +- union { +- struct rerr_unreach dest[1]; +-#ifdef INET6 +- struct rerr_unreach6 dest6[1]; +- struct rerr_unreach6_draft_01 dest6_draft_01[1]; +-#endif +- } r; + }; + + #define RERR_NODELETE 0x80 /* don't delete the link */ +@@ -284,32 +277,29 @@ static void + aodv_rerr(netdissect_options *ndo, + const struct aodv_rerr *ap, const u_char *dat, u_int length) + { +- u_int i; +- const struct rerr_unreach *dp = NULL; +- int n, trunc; ++ u_int i, dc; ++ const struct rerr_unreach *dp; + + if (ndo->ndo_snapend < dat) { + ND_PRINT((ndo, " [|aodv]")); + return; + } + i = min(length, (u_int)(ndo->ndo_snapend - dat)); +- if (i < offsetof(struct aodv_rerr, r)) { ++ if (i < sizeof(*ap)) { + ND_PRINT((ndo, " [|rerr]")); + return; + } +- i -= offsetof(struct aodv_rerr, r); +- dp = &ap->r.dest[0]; +- n = ap->rerr_dc * sizeof(ap->r.dest[0]); ++ i -= sizeof(*ap); + ND_PRINT((ndo, " rerr %s [items %u] [%u]:", + ap->rerr_flags & RERR_NODELETE ? "[D]" : "", + ap->rerr_dc, length)); +- trunc = n - (i/sizeof(ap->r.dest[0])); +- for (; i >= sizeof(ap->r.dest[0]); +- ++dp, i -= sizeof(ap->r.dest[0])) { ++ dp = (struct rerr_unreach *)(void *)(ap + 1); ++ for (dc = ap->rerr_dc; dc != 0 && i >= sizeof(*dp); ++ ++dp, --dc, i -= sizeof(*dp)) { + ND_PRINT((ndo, " {%s}(%ld)", ipaddr_string(ndo, &dp->u_da), + (unsigned long)EXTRACT_32BITS(&dp->u_ds))); + } +- if (trunc) ++ if ((i % sizeof(*dp)) != 0) + ND_PRINT((ndo, "[|rerr]")); + } + +@@ -397,29 +387,36 @@ aodv_v6_rrep(netdissect_options *ndo, + static void + #ifdef INET6 + aodv_v6_rerr(netdissect_options *ndo, +- const struct aodv_rerr *ap, u_int length) ++ const struct aodv_rerr *ap, const u_char *dat, u_int length) + #else + aodv_v6_rerr(netdissect_options *ndo, +- const struct aodv_rerr *ap _U_, u_int length) ++ const struct aodv_rerr *ap _U_, const u_char *dat, u_int length) + #endif + { + #ifdef INET6 +- const struct rerr_unreach6 *dp6 = NULL; +- int i, j, n, trunc; ++ u_int i, dc; ++ const struct rerr_unreach6 *dp6; + +- i = length - offsetof(struct aodv_rerr, r); +- j = sizeof(ap->r.dest6[0]); +- dp6 = &ap->r.dest6[0]; +- n = ap->rerr_dc * j; ++ if (ndo->ndo_snapend < dat) { ++ ND_PRINT((ndo, " [|aodv]")); ++ return; ++ } ++ i = min(length, (u_int)(ndo->ndo_snapend - dat)); ++ if (i < sizeof(*ap)) { ++ ND_PRINT((ndo, " [|rerr]")); ++ return; ++ } ++ i -= sizeof(*ap); + ND_PRINT((ndo, " rerr %s [items %u] [%u]:", + ap->rerr_flags & RERR_NODELETE ? "[D]" : "", + ap->rerr_dc, length)); +- trunc = n - (i/j); +- for (; i -= j >= 0; ++dp6) { ++ dp6 = (struct rerr_unreach6 *)(void *)(ap + 1); ++ for (dc = ap->rerr_dc; dc != 0 && i >= sizeof(*dp6); ++ ++dp6, --dc, i -= sizeof(*dp6)) { + ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da), + (unsigned long)EXTRACT_32BITS(&dp6->u_ds))); + } +- if (trunc) ++ if ((i % sizeof(*dp6)) != 0) + ND_PRINT((ndo, "[|rerr]")); + #else + ND_PRINT((ndo, " rerr %u", length)); +@@ -510,29 +507,36 @@ aodv_v6_draft_01_rrep(netdissect_options *ndo, + static void + #ifdef INET6 + aodv_v6_draft_01_rerr(netdissect_options *ndo, +- const struct aodv_rerr *ap, u_int length) ++ const struct aodv_rerr *ap, const u_char *dat, u_int length) + #else + aodv_v6_draft_01_rerr(netdissect_options *ndo, +- const struct aodv_rerr *ap _U_, u_int length) ++ const struct aodv_rerr *ap _U_, const u_char *dat, u_int length) + #endif + { + #ifdef INET6 +- const struct rerr_unreach6_draft_01 *dp6 = NULL; +- int i, j, n, trunc; ++ u_int i, dc; ++ const struct rerr_unreach6_draft_01 *dp6; + +- i = length - offsetof(struct aodv_rerr, r); +- j = sizeof(ap->r.dest6_draft_01[0]); +- dp6 = &ap->r.dest6_draft_01[0]; +- n = ap->rerr_dc * j; ++ if (ndo->ndo_snapend < dat) { ++ ND_PRINT((ndo, " [|aodv]")); ++ return; ++ } ++ i = min(length, (u_int)(ndo->ndo_snapend - dat)); ++ if (i < sizeof(*ap)) { ++ ND_PRINT((ndo, " [|rerr]")); ++ return; ++ } ++ i -= sizeof(*ap); + ND_PRINT((ndo, " rerr %s [items %u] [%u]:", + ap->rerr_flags & RERR_NODELETE ? "[D]" : "", + ap->rerr_dc, length)); +- trunc = n - (i/j); +- for (; i -= j >= 0; ++dp6) { ++ dp6 = (struct rerr_unreach6_draft_01 *)(void *)(ap + 1); ++ for (dc = ap->rerr_dc; dc != 0 && i >= sizeof(*dp6); ++ ++dp6, --dc, i -= sizeof(*dp6)) { + ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da), + (unsigned long)EXTRACT_32BITS(&dp6->u_ds))); + } +- if (trunc) ++ if ((i % sizeof(*dp6)) != 0) + ND_PRINT((ndo, "[|rerr]")); + #else + ND_PRINT((ndo, " rerr %u", length)); +@@ -571,7 +575,7 @@ aodv_print(netdissect_options *ndo, + + case AODV_RERR: + if (is_ip6) +- aodv_v6_rerr(ndo, (const struct aodv_rerr *)dat, length); ++ aodv_v6_rerr(ndo, (const struct aodv_rerr *)dat, dat, length); + else + aodv_rerr(ndo, (const struct aodv_rerr *)dat, dat, length); + break; +@@ -589,7 +593,7 @@ aodv_print(netdissect_options *ndo, + break; + + case AODV_V6_DRAFT_01_RERR: +- aodv_v6_draft_01_rerr(ndo, (const struct aodv_rerr *)dat, length); ++ aodv_v6_draft_01_rerr(ndo, (const struct aodv_rerr *)dat, dat, length); + break; + + case AODV_V6_DRAFT_01_RREP_ACK: +-- +2.1.2 + diff --git a/tcpdump-CVE-2014-8767.patch b/tcpdump-CVE-2014-8767.patch new file mode 100644 index 0000000..98ea22d --- /dev/null +++ b/tcpdump-CVE-2014-8767.patch @@ -0,0 +1,183 @@ +From 4038f83ebf654804829b258dde5e0a508c1c2003 Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Tue, 11 Nov 2014 16:49:39 -0800 +Subject: [PATCH 2/3] Do more bounds checking and length checking. + +Don't run past the end of the captured data, and don't run past the end +of the packet (i.e., don't make the length variable go negative). + +Also, stop dissecting if the message length isn't valid. +--- + print-olsr.c | 56 +++++++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 43 insertions(+), 13 deletions(-) + +diff --git a/print-olsr.c b/print-olsr.c +index 6fa0d76..6d2d65f 100644 +--- a/print-olsr.c ++++ b/print-olsr.c +@@ -178,7 +178,7 @@ struct olsr_lq_neighbor6 { + /* + * print a neighbor list with LQ extensions. + */ +-static void ++static int + olsr_print_lq_neighbor4(netdissect_options *ndo, + const u_char *msg_data, u_int hello_len) + { +@@ -187,6 +187,8 @@ olsr_print_lq_neighbor4(netdissect_options *ndo, + while (hello_len >= sizeof(struct olsr_lq_neighbor4)) { + + lq_neighbor = (struct olsr_lq_neighbor4 *)msg_data; ++ if (!ND_TTEST(*lq_neighbor)) ++ return (-1); + + ND_PRINT((ndo, "\n\t neighbor %s, link-quality %.2lf%%" + ", neighbor-link-quality %.2lf%%", +@@ -197,10 +199,11 @@ olsr_print_lq_neighbor4(netdissect_options *ndo, + msg_data += sizeof(struct olsr_lq_neighbor4); + hello_len -= sizeof(struct olsr_lq_neighbor4); + } ++ return (0); + } + + #if INET6 +-static void ++static int + olsr_print_lq_neighbor6(netdissect_options *ndo, + const u_char *msg_data, u_int hello_len) + { +@@ -209,6 +212,8 @@ olsr_print_lq_neighbor6(netdissect_options *ndo, + while (hello_len >= sizeof(struct olsr_lq_neighbor6)) { + + lq_neighbor = (struct olsr_lq_neighbor6 *)msg_data; ++ if (!ND_TTEST(*lq_neighbor)) ++ return (-1); + + ND_PRINT((ndo, "\n\t neighbor %s, link-quality %.2lf%%" + ", neighbor-link-quality %.2lf%%", +@@ -219,13 +224,14 @@ olsr_print_lq_neighbor6(netdissect_options *ndo, + msg_data += sizeof(struct olsr_lq_neighbor6); + hello_len -= sizeof(struct olsr_lq_neighbor6); + } ++ return (0); + } + #endif /* INET6 */ + + /* + * print a neighbor list. + */ +-static void ++static int + olsr_print_neighbor(netdissect_options *ndo, + const u_char *msg_data, u_int hello_len) + { +@@ -236,6 +242,8 @@ olsr_print_neighbor(netdissect_options *ndo, + + while (hello_len >= sizeof(struct in_addr)) { + ++ if (!ND_TTEST2(*msg_data, sizeof(struct in_addr))) ++ return (-1); + /* print 4 neighbors per line */ + + ND_PRINT((ndo, "%s%s", ipaddr_string(ndo, msg_data), +@@ -244,6 +252,7 @@ olsr_print_neighbor(netdissect_options *ndo, + msg_data += sizeof(struct in_addr); + hello_len -= sizeof(struct in_addr); + } ++ return (0); + } + + +@@ -326,6 +335,9 @@ olsr_print(netdissect_options *ndo, + ME_TO_DOUBLE(msgptr.v6->vtime), + EXTRACT_16BITS(msgptr.v6->msg_seq), + msg_len, (msg_len_valid == 0) ? " (invalid)" : "")); ++ if (!msg_len_valid) { ++ return; ++ } + + msg_tlen = msg_len - sizeof(struct olsr_msg6); + msg_data = tptr + sizeof(struct olsr_msg6); +@@ -354,6 +366,9 @@ olsr_print(netdissect_options *ndo, + ME_TO_DOUBLE(msgptr.v4->vtime), + EXTRACT_16BITS(msgptr.v4->msg_seq), + msg_len, (msg_len_valid == 0) ? " (invalid)" : "")); ++ if (!msg_len_valid) { ++ return; ++ } + + msg_tlen = msg_len - sizeof(struct olsr_msg4); + msg_data = tptr + sizeof(struct olsr_msg4); +@@ -362,6 +377,8 @@ olsr_print(netdissect_options *ndo, + switch (msg_type) { + case OLSR_HELLO_MSG: + case OLSR_HELLO_LQ_MSG: ++ if (msg_tlen < sizeof(struct olsr_hello)) ++ goto trunc; + ND_TCHECK2(*msg_data, sizeof(struct olsr_hello)); + + ptr.hello = (struct olsr_hello *)msg_data; +@@ -401,15 +418,21 @@ olsr_print(netdissect_options *ndo, + msg_tlen -= sizeof(struct olsr_hello_link); + hello_len -= sizeof(struct olsr_hello_link); + ++ ND_TCHECK2(*msg_data, hello_len); + if (msg_type == OLSR_HELLO_MSG) { +- olsr_print_neighbor(ndo, msg_data, hello_len); ++ if (olsr_print_neighbor(ndo, msg_data, hello_len) == -1) ++ goto trunc; + } else { + #if INET6 +- if (is_ipv6) +- olsr_print_lq_neighbor6(ndo, msg_data, hello_len); +- else ++ if (is_ipv6) { ++ if (olsr_print_lq_neighbor6(ndo, msg_data, hello_len) == -1) ++ goto trunc; ++ } else + #endif +- olsr_print_lq_neighbor4(ndo, msg_data, hello_len); ++ { ++ if (olsr_print_lq_neighbor4(ndo, msg_data, hello_len) == -1) ++ goto trunc; ++ } + } + + msg_data += hello_len; +@@ -419,6 +442,8 @@ olsr_print(netdissect_options *ndo, + + case OLSR_TC_MSG: + case OLSR_TC_LQ_MSG: ++ if (msg_tlen < sizeof(struct olsr_tc)) ++ goto trunc; + ND_TCHECK2(*msg_data, sizeof(struct olsr_tc)); + + ptr.tc = (struct olsr_tc *)msg_data; +@@ -428,14 +453,19 @@ olsr_print(netdissect_options *ndo, + msg_tlen -= sizeof(struct olsr_tc); + + if (msg_type == OLSR_TC_MSG) { +- olsr_print_neighbor(ndo, msg_data, msg_tlen); ++ if (olsr_print_neighbor(ndo, msg_data, msg_tlen) == -1) ++ goto trunc; + } else { + #if INET6 +- if (is_ipv6) +- olsr_print_lq_neighbor6(ndo, msg_data, msg_tlen); +- else ++ if (is_ipv6) { ++ if (olsr_print_lq_neighbor6(ndo, msg_data, msg_tlen) == -1) ++ goto trunc; ++ } else + #endif +- olsr_print_lq_neighbor4(ndo, msg_data, msg_tlen); ++ { ++ if (olsr_print_lq_neighbor4(ndo, msg_data, msg_tlen) == -1) ++ goto trunc; ++ } + } + break; + +-- +2.1.2 + diff --git a/tcpdump-CVE-2014-8768.patch b/tcpdump-CVE-2014-8768.patch new file mode 100644 index 0000000..03fd146 --- /dev/null +++ b/tcpdump-CVE-2014-8768.patch @@ -0,0 +1,343 @@ +From 9255c9b05b0a04b8d89739b3efcb9f393a617fe9 Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Tue, 11 Nov 2014 15:51:54 -0800 +Subject: [PATCH 1/3] Do bounds checking and length checking. + +Don't run past the end of the captured data, and don't run past the end +of the packet (i.e., don't make the length variable go negative). +--- + print-geonet.c | 270 ++++++++++++++++++++++++++++++++------------------------- + 1 file changed, 151 insertions(+), 119 deletions(-) + +diff --git a/print-geonet.c b/print-geonet.c +index d902066..edfb7f2 100644 +--- a/print-geonet.c ++++ b/print-geonet.c +@@ -56,16 +56,12 @@ static const struct tok msg_type_values[] = { + + static void + print_btp_body(netdissect_options *ndo, +- const u_char *bp, u_int length) ++ const u_char *bp) + { + int version; + int msg_type; + const char *msg_type_str; + +- if (length <= 2) { +- return; +- } +- + /* Assuming ItsDpuHeader */ + version = bp[0]; + msg_type = bp[1]; +@@ -83,7 +79,7 @@ print_btp(netdissect_options *ndo, + ND_PRINT((ndo, "; BTP Dst:%u Src:%u", dest, src)); + } + +-static void ++static int + print_long_pos_vector(netdissect_options *ndo, + const u_char *bp) + { +@@ -91,10 +87,13 @@ print_long_pos_vector(netdissect_options *ndo, + + ND_PRINT((ndo, "GN_ADDR:%s ", linkaddr_string (ndo, bp, 0, GEONET_ADDR_LEN))); + ++ if (!ND_TTEST2(*(bp+12), 8)) ++ return (-1); + lat = EXTRACT_32BITS(bp+12); + ND_PRINT((ndo, "lat:%d ", lat)); + lon = EXTRACT_32BITS(bp+16); + ND_PRINT((ndo, "lon:%d", lon)); ++ return (0); + } + + +@@ -105,137 +104,170 @@ print_long_pos_vector(netdissect_options *ndo, + void + geonet_print(netdissect_options *ndo, const u_char *eth, const u_char *bp, u_int length) + { ++ int version; ++ int next_hdr; ++ int hdr_type; ++ int hdr_subtype; ++ uint16_t payload_length; ++ int hop_limit; ++ const char *next_hdr_txt = "Unknown"; ++ const char *hdr_type_txt = "Unknown"; ++ int hdr_size = -1; ++ + ND_PRINT((ndo, "GeoNet src:%s; ", etheraddr_string(ndo, eth+6))); + +- if (length >= 36) { +- /* Process Common Header */ +- int version = bp[0] >> 4; +- int next_hdr = bp[0] & 0x0f; +- int hdr_type = bp[1] >> 4; +- int hdr_subtype = bp[1] & 0x0f; +- uint16_t payload_length = EXTRACT_16BITS(bp+4); +- int hop_limit = bp[7]; +- const char *next_hdr_txt = "Unknown"; +- const char *hdr_type_txt = "Unknown"; +- int hdr_size = -1; ++ /* Process Common Header */ ++ if (length < 36) ++ goto malformed; ++ ++ ND_TCHECK2(*bp, 7); ++ version = bp[0] >> 4; ++ next_hdr = bp[0] & 0x0f; ++ hdr_type = bp[1] >> 4; ++ hdr_subtype = bp[1] & 0x0f; ++ payload_length = EXTRACT_16BITS(bp+4); ++ hop_limit = bp[7]; + +- switch (next_hdr) { +- case 0: next_hdr_txt = "Any"; break; +- case 1: next_hdr_txt = "BTP-A"; break; +- case 2: next_hdr_txt = "BTP-B"; break; +- case 3: next_hdr_txt = "IPv6"; break; +- } ++ switch (next_hdr) { ++ case 0: next_hdr_txt = "Any"; break; ++ case 1: next_hdr_txt = "BTP-A"; break; ++ case 2: next_hdr_txt = "BTP-B"; break; ++ case 3: next_hdr_txt = "IPv6"; break; ++ } + +- switch (hdr_type) { +- case 0: hdr_type_txt = "Any"; break; +- case 1: hdr_type_txt = "Beacon"; break; +- case 2: hdr_type_txt = "GeoUnicast"; break; +- case 3: switch (hdr_subtype) { +- case 0: hdr_type_txt = "GeoAnycastCircle"; break; +- case 1: hdr_type_txt = "GeoAnycastRect"; break; +- case 2: hdr_type_txt = "GeoAnycastElipse"; break; +- } +- break; +- case 4: switch (hdr_subtype) { +- case 0: hdr_type_txt = "GeoBroadcastCircle"; break; +- case 1: hdr_type_txt = "GeoBroadcastRect"; break; +- case 2: hdr_type_txt = "GeoBroadcastElipse"; break; +- } +- break; +- case 5: switch (hdr_subtype) { +- case 0: hdr_type_txt = "TopoScopeBcast-SH"; break; +- case 1: hdr_type_txt = "TopoScopeBcast-MH"; break; +- } +- break; +- case 6: switch (hdr_subtype) { +- case 0: hdr_type_txt = "LocService-Request"; break; +- case 1: hdr_type_txt = "LocService-Reply"; break; +- } +- break; +- } ++ switch (hdr_type) { ++ case 0: hdr_type_txt = "Any"; break; ++ case 1: hdr_type_txt = "Beacon"; break; ++ case 2: hdr_type_txt = "GeoUnicast"; break; ++ case 3: switch (hdr_subtype) { ++ case 0: hdr_type_txt = "GeoAnycastCircle"; break; ++ case 1: hdr_type_txt = "GeoAnycastRect"; break; ++ case 2: hdr_type_txt = "GeoAnycastElipse"; break; ++ } ++ break; ++ case 4: switch (hdr_subtype) { ++ case 0: hdr_type_txt = "GeoBroadcastCircle"; break; ++ case 1: hdr_type_txt = "GeoBroadcastRect"; break; ++ case 2: hdr_type_txt = "GeoBroadcastElipse"; break; ++ } ++ break; ++ case 5: switch (hdr_subtype) { ++ case 0: hdr_type_txt = "TopoScopeBcast-SH"; break; ++ case 1: hdr_type_txt = "TopoScopeBcast-MH"; break; ++ } ++ break; ++ case 6: switch (hdr_subtype) { ++ case 0: hdr_type_txt = "LocService-Request"; break; ++ case 1: hdr_type_txt = "LocService-Reply"; break; ++ } ++ break; ++ } ++ ++ ND_PRINT((ndo, "v:%d ", version)); ++ ND_PRINT((ndo, "NH:%d-%s ", next_hdr, next_hdr_txt)); ++ ND_PRINT((ndo, "HT:%d-%d-%s ", hdr_type, hdr_subtype, hdr_type_txt)); ++ ND_PRINT((ndo, "HopLim:%d ", hop_limit)); ++ ND_PRINT((ndo, "Payload:%d ", payload_length)); ++ if (print_long_pos_vector(ndo, bp + 8) == -1) ++ goto trunc; + +- ND_PRINT((ndo, "v:%d ", version)); +- ND_PRINT((ndo, "NH:%d-%s ", next_hdr, next_hdr_txt)); +- ND_PRINT((ndo, "HT:%d-%d-%s ", hdr_type, hdr_subtype, hdr_type_txt)); +- ND_PRINT((ndo, "HopLim:%d ", hop_limit)); +- ND_PRINT((ndo, "Payload:%d ", payload_length)); +- print_long_pos_vector(ndo, bp + 8); ++ /* Skip Common Header */ ++ length -= 36; ++ bp += 36; + +- /* Skip Common Header */ +- length -= 36; +- bp += 36; ++ /* Process Extended Headers */ ++ switch (hdr_type) { ++ case 0: /* Any */ ++ hdr_size = 0; ++ break; ++ case 1: /* Beacon */ ++ hdr_size = 0; ++ break; ++ case 2: /* GeoUnicast */ ++ break; ++ case 3: switch (hdr_subtype) { ++ case 0: /* GeoAnycastCircle */ ++ break; ++ case 1: /* GeoAnycastRect */ ++ break; ++ case 2: /* GeoAnycastElipse */ ++ break; ++ } ++ break; ++ case 4: switch (hdr_subtype) { ++ case 0: /* GeoBroadcastCircle */ ++ break; ++ case 1: /* GeoBroadcastRect */ ++ break; ++ case 2: /* GeoBroadcastElipse */ ++ break; ++ } ++ break; ++ case 5: switch (hdr_subtype) { ++ case 0: /* TopoScopeBcast-SH */ ++ hdr_size = 0; ++ break; ++ case 1: /* TopoScopeBcast-MH */ ++ hdr_size = 68 - 36; ++ break; ++ } ++ break; ++ case 6: switch (hdr_subtype) { ++ case 0: /* LocService-Request */ ++ break; ++ case 1: /* LocService-Reply */ ++ break; ++ } ++ break; ++ } + +- /* Process Extended Headers */ +- switch (hdr_type) { ++ /* Skip Extended headers */ ++ if (hdr_size >= 0) { ++ if (length < (u_int)hdr_size) ++ goto malformed; ++ ND_TCHECK2(*bp, hdr_size); ++ length -= hdr_size; ++ bp += hdr_size; ++ switch (next_hdr) { + case 0: /* Any */ +- hdr_size = 0; +- break; +- case 1: /* Beacon */ +- hdr_size = 0; +- break; +- case 2: /* GeoUnicast */ + break; +- case 3: switch (hdr_subtype) { +- case 0: /* GeoAnycastCircle */ +- break; +- case 1: /* GeoAnycastRect */ +- break; +- case 2: /* GeoAnycastElipse */ +- break; ++ case 1: ++ case 2: /* BTP A/B */ ++ if (length < 4) ++ goto malformed; ++ ND_TCHECK2(*bp, 4); ++ print_btp(ndo, bp); ++ length -= 4; ++ bp += 4; ++ if (length >= 2) { ++ /* ++ * XXX - did print_btp_body() ++ * return if length < 2 ++ * because this is optional, ++ * or was that just not ++ * reporting genuine errors? ++ */ ++ ND_TCHECK2(*bp, 2); ++ print_btp_body(ndo, bp); + } + break; +- case 4: switch (hdr_subtype) { +- case 0: /* GeoBroadcastCircle */ +- break; +- case 1: /* GeoBroadcastRect */ +- break; +- case 2: /* GeoBroadcastElipse */ +- break; +- } +- break; +- case 5: switch (hdr_subtype) { +- case 0: /* TopoScopeBcast-SH */ +- hdr_size = 0; +- break; +- case 1: /* TopoScopeBcast-MH */ +- hdr_size = 68 - 36; +- break; +- } +- break; +- case 6: switch (hdr_subtype) { +- case 0: /* LocService-Request */ +- break; +- case 1: /* LocService-Reply */ +- break; +- } ++ case 3: /* IPv6 */ + break; + } +- +- /* Skip Extended headers */ +- if (hdr_size >= 0) { +- length -= hdr_size; +- bp += hdr_size; +- switch (next_hdr) { +- case 0: /* Any */ +- break; +- case 1: +- case 2: /* BTP A/B */ +- print_btp(ndo, bp); +- length -= 4; +- bp += 4; +- print_btp_body(ndo, bp, length); +- break; +- case 3: /* IPv6 */ +- break; +- } +- } +- } else { +- ND_PRINT((ndo, "Malformed (small) ")); + } + + /* Print user data part */ + if (ndo->ndo_vflag) + ND_DEFAULTPRINT(bp, length); ++ return; ++ ++malformed: ++ ND_PRINT((ndo, " Malformed (small) ")); ++ /* XXX - print the remaining data as hex? */ ++ return; ++ ++trunc: ++ ND_PRINT((ndo, "[|geonet]")); + } + + +-- +2.1.2 + diff --git a/tcpdump-CVE-2014-8769.patch b/tcpdump-CVE-2014-8769.patch new file mode 100644 index 0000000..f178381 --- /dev/null +++ b/tcpdump-CVE-2014-8769.patch @@ -0,0 +1,516 @@ +From ab4e52b94aac6cb729a5a695aa612d5ebda2ec3a Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Tue, 11 Nov 2014 17:24:12 -0800 +Subject: [PATCH 3/3] Add initial bounds check, get rid of union aodv. + +Fetch the type field without using a structure, and check to make sure +it's not past the end of the packet. + +Pass to each dissection routine a pointer to the appropriate message +type structure, rather than a pointer to a union of all the message type +structures. +--- + print-aodv.c | 274 ++++++++++++++++++++++++++++------------------------------- + 1 file changed, 130 insertions(+), 144 deletions(-) + +diff --git a/print-aodv.c b/print-aodv.c +index 093e174..da5b169 100644 +--- a/print-aodv.c ++++ b/print-aodv.c +@@ -163,19 +163,6 @@ struct aodv_rrep_ack { + uint8_t ra_zero0; + }; + +-union aodv { +- struct aodv_rreq rreq; +- struct aodv_rrep rrep; +- struct aodv_rerr rerr; +- struct aodv_rrep_ack rrep_ack; +-#ifdef INET6 +- struct aodv_rreq6 rreq6; +- struct aodv_rreq6_draft_01 rreq6_draft_01; +- struct aodv_rrep6 rrep6; +- struct aodv_rrep6_draft_01 rrep6_draft_01; +-#endif +-}; +- + #define AODV_RREQ 1 /* route request */ + #define AODV_RREP 2 /* route response */ + #define AODV_RERR 3 /* error report */ +@@ -232,7 +219,7 @@ aodv_extension(netdissect_options *ndo, + + static void + aodv_rreq(netdissect_options *ndo, +- const union aodv *ap, const u_char *dat, u_int length) ++ const struct aodv_rreq *ap, const u_char *dat, u_int length) + { + u_int i; + +@@ -241,31 +228,31 @@ aodv_rreq(netdissect_options *ndo, + return; + } + i = min(length, (u_int)(ndo->ndo_snapend - dat)); +- if (i < sizeof(ap->rreq)) { ++ if (i < sizeof(*ap)) { + ND_PRINT((ndo, " [|rreq]")); + return; + } +- i -= sizeof(ap->rreq); ++ i -= sizeof(*ap); + ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n" + "\tdst %s seq %lu src %s seq %lu", length, +- ap->rreq.rreq_type & RREQ_JOIN ? "[J]" : "", +- ap->rreq.rreq_type & RREQ_REPAIR ? "[R]" : "", +- ap->rreq.rreq_type & RREQ_GRAT ? "[G]" : "", +- ap->rreq.rreq_type & RREQ_DEST ? "[D]" : "", +- ap->rreq.rreq_type & RREQ_UNKNOWN ? "[U] " : " ", +- ap->rreq.rreq_hops, +- (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_id), +- ipaddr_string(ndo, &ap->rreq.rreq_da), +- (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_ds), +- ipaddr_string(ndo, &ap->rreq.rreq_oa), +- (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_os))); ++ ap->rreq_type & RREQ_JOIN ? "[J]" : "", ++ ap->rreq_type & RREQ_REPAIR ? "[R]" : "", ++ ap->rreq_type & RREQ_GRAT ? "[G]" : "", ++ ap->rreq_type & RREQ_DEST ? "[D]" : "", ++ ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ", ++ ap->rreq_hops, ++ (unsigned long)EXTRACT_32BITS(&ap->rreq_id), ++ ipaddr_string(ndo, &ap->rreq_da), ++ (unsigned long)EXTRACT_32BITS(&ap->rreq_ds), ++ ipaddr_string(ndo, &ap->rreq_oa), ++ (unsigned long)EXTRACT_32BITS(&ap->rreq_os))); + if (i >= sizeof(struct aodv_ext)) +- aodv_extension(ndo, (void *)(&ap->rreq + 1), i); ++ aodv_extension(ndo, (void *)(ap + 1), i); + } + + static void + aodv_rrep(netdissect_options *ndo, +- const union aodv *ap, const u_char *dat, u_int length) ++ const struct aodv_rrep *ap, const u_char *dat, u_int length) + { + u_int i; + +@@ -274,28 +261,28 @@ aodv_rrep(netdissect_options *ndo, + return; + } + i = min(length, (u_int)(ndo->ndo_snapend - dat)); +- if (i < sizeof(ap->rrep)) { ++ if (i < sizeof(*ap)) { + ND_PRINT((ndo, " [|rrep]")); + return; + } +- i -= sizeof(ap->rrep); ++ i -= sizeof(*ap); + ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n" + "\tdst %s dseq %lu src %s %lu ms", length, +- ap->rrep.rrep_type & RREP_REPAIR ? "[R]" : "", +- ap->rrep.rrep_type & RREP_ACK ? "[A] " : " ", +- ap->rrep.rrep_ps & RREP_PREFIX_MASK, +- ap->rrep.rrep_hops, +- ipaddr_string(ndo, &ap->rrep.rrep_da), +- (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_ds), +- ipaddr_string(ndo, &ap->rrep.rrep_oa), +- (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_life))); ++ ap->rrep_type & RREP_REPAIR ? "[R]" : "", ++ ap->rrep_type & RREP_ACK ? "[A] " : " ", ++ ap->rrep_ps & RREP_PREFIX_MASK, ++ ap->rrep_hops, ++ ipaddr_string(ndo, &ap->rrep_da), ++ (unsigned long)EXTRACT_32BITS(&ap->rrep_ds), ++ ipaddr_string(ndo, &ap->rrep_oa), ++ (unsigned long)EXTRACT_32BITS(&ap->rrep_life))); + if (i >= sizeof(struct aodv_ext)) +- aodv_extension(ndo, (void *)(&ap->rrep + 1), i); ++ aodv_extension(ndo, (void *)(ap + 1), i); + } + + static void + aodv_rerr(netdissect_options *ndo, +- const union aodv *ap, const u_char *dat, u_int length) ++ const struct aodv_rerr *ap, const u_char *dat, u_int length) + { + u_int i; + const struct rerr_unreach *dp = NULL; +@@ -311,14 +298,14 @@ aodv_rerr(netdissect_options *ndo, + return; + } + i -= offsetof(struct aodv_rerr, r); +- dp = &ap->rerr.r.dest[0]; +- n = ap->rerr.rerr_dc * sizeof(ap->rerr.r.dest[0]); ++ dp = &ap->r.dest[0]; ++ n = ap->rerr_dc * sizeof(ap->r.dest[0]); + ND_PRINT((ndo, " rerr %s [items %u] [%u]:", +- ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "", +- ap->rerr.rerr_dc, length)); +- trunc = n - (i/sizeof(ap->rerr.r.dest[0])); +- for (; i >= sizeof(ap->rerr.r.dest[0]); +- ++dp, i -= sizeof(ap->rerr.r.dest[0])) { ++ ap->rerr_flags & RERR_NODELETE ? "[D]" : "", ++ ap->rerr_dc, length)); ++ trunc = n - (i/sizeof(ap->r.dest[0])); ++ for (; i >= sizeof(ap->r.dest[0]); ++ ++dp, i -= sizeof(ap->r.dest[0])) { + ND_PRINT((ndo, " {%s}(%ld)", ipaddr_string(ndo, &dp->u_da), + (unsigned long)EXTRACT_32BITS(&dp->u_ds))); + } +@@ -329,10 +316,10 @@ aodv_rerr(netdissect_options *ndo, + static void + #ifdef INET6 + aodv_v6_rreq(netdissect_options *ndo, +- const union aodv *ap, const u_char *dat, u_int length) ++ const struct aodv_rreq6 *ap, const u_char *dat, u_int length) + #else + aodv_v6_rreq(netdissect_options *ndo, +- const union aodv *ap _U_, const u_char *dat _U_, u_int length) ++ const struct aodv_rreq6 *ap _U_, const u_char *dat _U_, u_int length) + #endif + { + #ifdef INET6 +@@ -343,26 +330,26 @@ aodv_v6_rreq(netdissect_options *ndo, + return; + } + i = min(length, (u_int)(ndo->ndo_snapend - dat)); +- if (i < sizeof(ap->rreq6)) { ++ if (i < sizeof(*ap)) { + ND_PRINT((ndo, " [|rreq6]")); + return; + } +- i -= sizeof(ap->rreq6); ++ i -= sizeof(*ap); + ND_PRINT((ndo, " v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n" + "\tdst %s seq %lu src %s seq %lu", length, +- ap->rreq6.rreq_type & RREQ_JOIN ? "[J]" : "", +- ap->rreq6.rreq_type & RREQ_REPAIR ? "[R]" : "", +- ap->rreq6.rreq_type & RREQ_GRAT ? "[G]" : "", +- ap->rreq6.rreq_type & RREQ_DEST ? "[D]" : "", +- ap->rreq6.rreq_type & RREQ_UNKNOWN ? "[U] " : " ", +- ap->rreq6.rreq_hops, +- (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_id), +- ip6addr_string(ndo, &ap->rreq6.rreq_da), +- (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_ds), +- ip6addr_string(ndo, &ap->rreq6.rreq_oa), +- (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_os))); ++ ap->rreq_type & RREQ_JOIN ? "[J]" : "", ++ ap->rreq_type & RREQ_REPAIR ? "[R]" : "", ++ ap->rreq_type & RREQ_GRAT ? "[G]" : "", ++ ap->rreq_type & RREQ_DEST ? "[D]" : "", ++ ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ", ++ ap->rreq_hops, ++ (unsigned long)EXTRACT_32BITS(&ap->rreq_id), ++ ip6addr_string(ndo, &ap->rreq_da), ++ (unsigned long)EXTRACT_32BITS(&ap->rreq_ds), ++ ip6addr_string(ndo, &ap->rreq_oa), ++ (unsigned long)EXTRACT_32BITS(&ap->rreq_os))); + if (i >= sizeof(struct aodv_ext)) +- aodv_extension(ndo, (void *)(&ap->rreq6 + 1), i); ++ aodv_extension(ndo, (void *)(ap + 1), i); + #else + ND_PRINT((ndo, " v6 rreq %u", length)); + #endif +@@ -371,10 +358,10 @@ aodv_v6_rreq(netdissect_options *ndo, + static void + #ifdef INET6 + aodv_v6_rrep(netdissect_options *ndo, +- const union aodv *ap, const u_char *dat, u_int length) ++ const struct aodv_rrep6 *ap, const u_char *dat, u_int length) + #else + aodv_v6_rrep(netdissect_options *ndo, +- const union aodv *ap _U_, const u_char *dat _U_, u_int length) ++ const struct aodv_rrep6 *ap _U_, const u_char *dat _U_, u_int length) + #endif + { + #ifdef INET6 +@@ -385,23 +372,23 @@ aodv_v6_rrep(netdissect_options *ndo, + return; + } + i = min(length, (u_int)(ndo->ndo_snapend - dat)); +- if (i < sizeof(ap->rrep6)) { ++ if (i < sizeof(*ap)) { + ND_PRINT((ndo, " [|rrep6]")); + return; + } +- i -= sizeof(ap->rrep6); ++ i -= sizeof(*ap); + ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n" + "\tdst %s dseq %lu src %s %lu ms", length, +- ap->rrep6.rrep_type & RREP_REPAIR ? "[R]" : "", +- ap->rrep6.rrep_type & RREP_ACK ? "[A] " : " ", +- ap->rrep6.rrep_ps & RREP_PREFIX_MASK, +- ap->rrep6.rrep_hops, +- ip6addr_string(ndo, &ap->rrep6.rrep_da), +- (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_ds), +- ip6addr_string(ndo, &ap->rrep6.rrep_oa), +- (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_life))); ++ ap->rrep_type & RREP_REPAIR ? "[R]" : "", ++ ap->rrep_type & RREP_ACK ? "[A] " : " ", ++ ap->rrep_ps & RREP_PREFIX_MASK, ++ ap->rrep_hops, ++ ip6addr_string(ndo, &ap->rrep_da), ++ (unsigned long)EXTRACT_32BITS(&ap->rrep_ds), ++ ip6addr_string(ndo, &ap->rrep_oa), ++ (unsigned long)EXTRACT_32BITS(&ap->rrep_life))); + if (i >= sizeof(struct aodv_ext)) +- aodv_extension(ndo, (void *)(&ap->rrep6 + 1), i); ++ aodv_extension(ndo, (void *)(ap + 1), i); + #else + ND_PRINT((ndo, " rrep %u", length)); + #endif +@@ -410,10 +397,10 @@ aodv_v6_rrep(netdissect_options *ndo, + static void + #ifdef INET6 + aodv_v6_rerr(netdissect_options *ndo, +- const union aodv *ap, u_int length) ++ const struct aodv_rerr *ap, u_int length) + #else + aodv_v6_rerr(netdissect_options *ndo, +- const union aodv *ap _U_, u_int length) ++ const struct aodv_rerr *ap _U_, u_int length) + #endif + { + #ifdef INET6 +@@ -421,12 +408,12 @@ aodv_v6_rerr(netdissect_options *ndo, + int i, j, n, trunc; + + i = length - offsetof(struct aodv_rerr, r); +- j = sizeof(ap->rerr.r.dest6[0]); +- dp6 = &ap->rerr.r.dest6[0]; +- n = ap->rerr.rerr_dc * j; ++ j = sizeof(ap->r.dest6[0]); ++ dp6 = &ap->r.dest6[0]; ++ n = ap->rerr_dc * j; + ND_PRINT((ndo, " rerr %s [items %u] [%u]:", +- ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "", +- ap->rerr.rerr_dc, length)); ++ ap->rerr_flags & RERR_NODELETE ? "[D]" : "", ++ ap->rerr_dc, length)); + trunc = n - (i/j); + for (; i -= j >= 0; ++dp6) { + ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da), +@@ -442,11 +429,10 @@ aodv_v6_rerr(netdissect_options *ndo, + static void + #ifdef INET6 + aodv_v6_draft_01_rreq(netdissect_options *ndo, +- const union aodv *ap, const u_char *dat, u_int length) ++ const struct aodv_rreq6_draft_01 *ap, const u_char *dat, u_int length) + #else + aodv_v6_draft_01_rreq(netdissect_options *ndo, +- const union aodv *ap _U_, const u_char *dat _U_, +- u_int length) ++ const struct aodv_rreq6_draft_01 *ap _U_, const u_char *dat _U_, u_int length) + #endif + { + #ifdef INET6 +@@ -457,26 +443,26 @@ aodv_v6_draft_01_rreq(netdissect_options *ndo, + return; + } + i = min(length, (u_int)(ndo->ndo_snapend - dat)); +- if (i < sizeof(ap->rreq6_draft_01)) { ++ if (i < sizeof(*ap)) { + ND_PRINT((ndo, " [|rreq6]")); + return; + } +- i -= sizeof(ap->rreq6_draft_01); ++ i -= sizeof(*ap); + ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n" + "\tdst %s seq %lu src %s seq %lu", length, +- ap->rreq6_draft_01.rreq_type & RREQ_JOIN ? "[J]" : "", +- ap->rreq6_draft_01.rreq_type & RREQ_REPAIR ? "[R]" : "", +- ap->rreq6_draft_01.rreq_type & RREQ_GRAT ? "[G]" : "", +- ap->rreq6_draft_01.rreq_type & RREQ_DEST ? "[D]" : "", +- ap->rreq6_draft_01.rreq_type & RREQ_UNKNOWN ? "[U] " : " ", +- ap->rreq6_draft_01.rreq_hops, +- (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_id), +- ip6addr_string(ndo, &ap->rreq6_draft_01.rreq_da), +- (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_ds), +- ip6addr_string(ndo, &ap->rreq6_draft_01.rreq_oa), +- (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_os))); ++ ap->rreq_type & RREQ_JOIN ? "[J]" : "", ++ ap->rreq_type & RREQ_REPAIR ? "[R]" : "", ++ ap->rreq_type & RREQ_GRAT ? "[G]" : "", ++ ap->rreq_type & RREQ_DEST ? "[D]" : "", ++ ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ", ++ ap->rreq_hops, ++ (unsigned long)EXTRACT_32BITS(&ap->rreq_id), ++ ip6addr_string(ndo, &ap->rreq_da), ++ (unsigned long)EXTRACT_32BITS(&ap->rreq_ds), ++ ip6addr_string(ndo, &ap->rreq_oa), ++ (unsigned long)EXTRACT_32BITS(&ap->rreq_os))); + if (i >= sizeof(struct aodv_ext)) +- aodv_extension(ndo, (void *)(&ap->rreq6_draft_01 + 1), i); ++ aodv_extension(ndo, (void *)(ap + 1), i); + #else + ND_PRINT((ndo, " rreq %u", length)); + #endif +@@ -485,11 +471,10 @@ aodv_v6_draft_01_rreq(netdissect_options *ndo, + static void + #ifdef INET6 + aodv_v6_draft_01_rrep(netdissect_options *ndo, +- const union aodv *ap, const u_char *dat, u_int length) ++ const struct aodv_rrep6_draft_01 *ap, const u_char *dat, u_int length) + #else + aodv_v6_draft_01_rrep(netdissect_options *ndo, +- const union aodv *ap _U_, const u_char *dat _U_, +- u_int length) ++ const struct aodv_rrep6_draft_01 *ap _U_, const u_char *dat _U_, u_int length) + #endif + { + #ifdef INET6 +@@ -500,23 +485,23 @@ aodv_v6_draft_01_rrep(netdissect_options *ndo, + return; + } + i = min(length, (u_int)(ndo->ndo_snapend - dat)); +- if (i < sizeof(ap->rrep6_draft_01)) { ++ if (i < sizeof(*ap)) { + ND_PRINT((ndo, " [|rrep6]")); + return; + } +- i -= sizeof(ap->rrep6_draft_01); ++ i -= sizeof(*ap); + ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n" + "\tdst %s dseq %lu src %s %lu ms", length, +- ap->rrep6_draft_01.rrep_type & RREP_REPAIR ? "[R]" : "", +- ap->rrep6_draft_01.rrep_type & RREP_ACK ? "[A] " : " ", +- ap->rrep6_draft_01.rrep_ps & RREP_PREFIX_MASK, +- ap->rrep6_draft_01.rrep_hops, +- ip6addr_string(ndo, &ap->rrep6_draft_01.rrep_da), +- (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_ds), +- ip6addr_string(ndo, &ap->rrep6_draft_01.rrep_oa), +- (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_life))); ++ ap->rrep_type & RREP_REPAIR ? "[R]" : "", ++ ap->rrep_type & RREP_ACK ? "[A] " : " ", ++ ap->rrep_ps & RREP_PREFIX_MASK, ++ ap->rrep_hops, ++ ip6addr_string(ndo, &ap->rrep_da), ++ (unsigned long)EXTRACT_32BITS(&ap->rrep_ds), ++ ip6addr_string(ndo, &ap->rrep_oa), ++ (unsigned long)EXTRACT_32BITS(&ap->rrep_life))); + if (i >= sizeof(struct aodv_ext)) +- aodv_extension(ndo, (void *)(&ap->rrep6_draft_01 + 1), i); ++ aodv_extension(ndo, (void *)(ap + 1), i); + #else + ND_PRINT((ndo, " rrep %u", length)); + #endif +@@ -525,10 +510,10 @@ aodv_v6_draft_01_rrep(netdissect_options *ndo, + static void + #ifdef INET6 + aodv_v6_draft_01_rerr(netdissect_options *ndo, +- const union aodv *ap, u_int length) ++ const struct aodv_rerr *ap, u_int length) + #else + aodv_v6_draft_01_rerr(netdissect_options *ndo, +- const union aodv *ap _U_, u_int length) ++ const struct aodv_rerr *ap _U_, u_int length) + #endif + { + #ifdef INET6 +@@ -536,12 +521,12 @@ aodv_v6_draft_01_rerr(netdissect_options *ndo, + int i, j, n, trunc; + + i = length - offsetof(struct aodv_rerr, r); +- j = sizeof(ap->rerr.r.dest6_draft_01[0]); +- dp6 = &ap->rerr.r.dest6_draft_01[0]; +- n = ap->rerr.rerr_dc * j; ++ j = sizeof(ap->r.dest6_draft_01[0]); ++ dp6 = &ap->r.dest6_draft_01[0]; ++ n = ap->rerr_dc * j; + ND_PRINT((ndo, " rerr %s [items %u] [%u]:", +- ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "", +- ap->rerr.rerr_dc, length)); ++ ap->rerr_flags & RERR_NODELETE ? "[D]" : "", ++ ap->rerr_dc, length)); + trunc = n - (i/j); + for (; i -= j >= 0; ++dp6) { + ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da), +@@ -558,40 +543,37 @@ void + aodv_print(netdissect_options *ndo, + const u_char *dat, u_int length, int is_ip6) + { +- const union aodv *ap; +- +- ap = (union aodv *)dat; +- if (ndo->ndo_snapend < dat) { +- ND_PRINT((ndo, " [|aodv]")); +- return; +- } +- if (min(length, (u_int)(ndo->ndo_snapend - dat)) < sizeof(ap->rrep_ack)) { +- ND_PRINT((ndo, " [|aodv]")); +- return; +- } ++ uint8_t msg_type; ++ ++ /* ++ * The message type is the first byte; make sure we have it ++ * and then fetch it. ++ */ ++ ND_TCHECK(*dat); ++ msg_type = *dat; + ND_PRINT((ndo, " aodv")); + +- switch (ap->rerr.rerr_type) { ++ switch (msg_type) { + + case AODV_RREQ: + if (is_ip6) +- aodv_v6_rreq(ndo, ap, dat, length); ++ aodv_v6_rreq(ndo, (const struct aodv_rreq6 *)dat, dat, length); + else +- aodv_rreq(ndo, ap, dat, length); ++ aodv_rreq(ndo, (const struct aodv_rreq *)dat, dat, length); + break; + + case AODV_RREP: + if (is_ip6) +- aodv_v6_rrep(ndo, ap, dat, length); ++ aodv_v6_rrep(ndo, (const struct aodv_rrep6 *)dat, dat, length); + else +- aodv_rrep(ndo, ap, dat, length); ++ aodv_rrep(ndo, (const struct aodv_rrep *)dat, dat, length); + break; + + case AODV_RERR: + if (is_ip6) +- aodv_v6_rerr(ndo, ap, length); ++ aodv_v6_rerr(ndo, (const struct aodv_rerr *)dat, length); + else +- aodv_rerr(ndo, ap, dat, length); ++ aodv_rerr(ndo, (const struct aodv_rerr *)dat, dat, length); + break; + + case AODV_RREP_ACK: +@@ -599,15 +581,15 @@ aodv_print(netdissect_options *ndo, + break; + + case AODV_V6_DRAFT_01_RREQ: +- aodv_v6_draft_01_rreq(ndo, ap, dat, length); ++ aodv_v6_draft_01_rreq(ndo, (const struct aodv_rreq6_draft_01 *)dat, dat, length); + break; + + case AODV_V6_DRAFT_01_RREP: +- aodv_v6_draft_01_rrep(ndo, ap, dat, length); ++ aodv_v6_draft_01_rrep(ndo, (const struct aodv_rrep6_draft_01 *)dat, dat, length); + break; + + case AODV_V6_DRAFT_01_RERR: +- aodv_v6_draft_01_rerr(ndo, ap, length); ++ aodv_v6_draft_01_rerr(ndo, (const struct aodv_rerr *)dat, length); + break; + + case AODV_V6_DRAFT_01_RREP_ACK: +@@ -615,6 +597,10 @@ aodv_print(netdissect_options *ndo, + break; + + default: +- ND_PRINT((ndo, " %u %u", ap->rreq.rreq_type, length)); ++ ND_PRINT((ndo, " type %u %u", msg_type, length)); + } ++ return; ++ ++trunc: ++ ND_PRINT((ndo, " [|aodv]")); + } +-- +2.1.2 + diff --git a/tcpdump.changes b/tcpdump.changes index 4daec44..960f117 100644 --- a/tcpdump.changes +++ b/tcpdump.changes @@ -1,3 +1,17 @@ +------------------------------------------------------------------- +Fri Feb 6 12:31:23 UTC 2015 - vcizek@suse.com + +- fix CVE-2014-8767 (bnc#905870) + * denial of service in verbose mode using malformed OLSR payload + * added tcpdump-CVE-2014-8767.patch +- fix CVE-2014-8768 (bnc#905871) + * denial of service in verbose mode using malformed Geonet payload + * added tcpdump-CVE-2014-8768.patch +- fix CVE-2014-8769 (bnc#905872) + * unreliable output using malformed AOVD payload + * added tcpdump-CVE-2014-8769.patch + * added 0001-Clean-up-error-message-printing.patch + ------------------------------------------------------------------- Wed Sep 3 18:44:03 UTC 2014 - andreas.stieger@gmx.de diff --git a/tcpdump.spec b/tcpdump.spec index 2851cb8..15b0a8a 100644 --- a/tcpdump.spec +++ b/tcpdump.spec @@ -1,7 +1,7 @@ # # spec file for package tcpdump # -# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -30,6 +30,10 @@ Source: http://www.tcpdump.org/release/%{name}-%{version}.tar.gz Source1: tcpdump-qeth Source2: http://www.tcpdump.org/release/%{name}-%{version}.tar.gz.sig Source3: http://www.tcpdump.org/tcpdump-workers.asc#/%{name}.keyring +Patch3: tcpdump-CVE-2014-8767.patch +Patch4: tcpdump-CVE-2014-8768.patch +Patch5: tcpdump-CVE-2014-8769.patch +Patch6: 0001-Clean-up-error-message-printing.patch BuildRequires: libpcap-devel >= %{min_libpcap_version} BuildRequires: libsmi-devel BuildRequires: openssl-devel @@ -42,6 +46,10 @@ ethernet. It can be used to debug specific network problems. %prep %setup -q +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 %build export CFLAGS="%{optflags} -Wall -DGUESS_TSO -fstack-protector -fno-strict-aliasing"