diff options
author | Mariano Lopez <mariano.lopez@linux.intel.com> | 2016-03-11 08:47:09 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-05-09 08:11:33 +0100 |
commit | dad3b97a9a3f6e23873e788ff80c06f8ac7e7140 (patch) | |
tree | bddb513c6d166dbb30c7d81699fa64be3c35fb22 /meta/recipes-connectivity/dhcp | |
parent | 900d7d6b59c36b2bdbd1c85febec99e80ab54f95 (diff) | |
download | poky-dad3b97a9a3f6e23873e788ff80c06f8ac7e7140.tar.gz |
dhcp: CVE-2015-8605
ISC DHCP allows remote attackers to cause a denial of
service (application crash) via an invalid length field
in a UDP IPv4 packet.
(From OE-Core rev: 43f2cfdf63fb70e3c2da0224221dae63b05477df)
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
Signed-off-by: Joshua Lock <joshua.g.lock@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-connectivity/dhcp')
-rw-r--r-- | meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605.patch | 101 | ||||
-rw-r--r-- | meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605_1.patch | 131 | ||||
-rw-r--r-- | meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb | 2 |
3 files changed, 234 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605.patch b/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605.patch new file mode 100644 index 0000000000..05f1fa9fd8 --- /dev/null +++ b/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605.patch | |||
@@ -0,0 +1,101 @@ | |||
1 | Solves CVE-2015-8605 that caused DoS when an invalid length field in IPv4 UDP | ||
2 | was received by the server. | ||
3 | |||
4 | Upstream-Status: Backport (v4.3.3p1) | ||
5 | CVE: CVE-2015-8605 | ||
6 | |||
7 | From: https://source.isc.org/cgi-bin/gitweb.cgi?p=dhcp.git;a=commit;h=4ce21cb6301d665de01c1a6209e40f5f35072c0c | ||
8 | |||
9 | Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com> | ||
10 | |||
11 | ======================================================================= | ||
12 | diff --git a/common/packet.c b/common/packet.c | ||
13 | index b530432..e600e37 100644 | ||
14 | --- a/common/packet.c | ||
15 | +++ b/common/packet.c | ||
16 | @@ -220,7 +220,28 @@ ssize_t decode_hw_header (interface, buf, bufix, from) | ||
17 | } | ||
18 | } | ||
19 | |||
20 | -/* UDP header and IP header decoded together for convenience. */ | ||
21 | +/*! | ||
22 | + * | ||
23 | + * \brief UDP header and IP header decoded together for convenience. | ||
24 | + * | ||
25 | + * Attempt to decode the UDP and IP headers and, if necessary, checksum | ||
26 | + * the packet. | ||
27 | + * | ||
28 | + * \param inteface - the interface on which the packet was recevied | ||
29 | + * \param buf - a pointer to the buffer for the received packet | ||
30 | + * \param bufix - where to start processing the buffer, previous | ||
31 | + * routines may have processed parts of the buffer already | ||
32 | + * \param from - space to return the address of the packet sender | ||
33 | + * \param buflen - remaining length of the buffer, this will have been | ||
34 | + * decremented by bufix by the caller | ||
35 | + * \param rbuflen - space to return the length of the payload from the udp | ||
36 | + * header | ||
37 | + * \param csum_ready - indication if the checksum is valid for use | ||
38 | + * non-zero indicates the checksum should be validated | ||
39 | + * | ||
40 | + * \return - the index to the first byte of the udp payload (that is the | ||
41 | + * start of the DHCP packet | ||
42 | + */ | ||
43 | |||
44 | ssize_t | ||
45 | decode_udp_ip_header(struct interface_info *interface, | ||
46 | @@ -231,7 +252,7 @@ decode_udp_ip_header(struct interface_info *interface, | ||
47 | unsigned char *data; | ||
48 | struct ip ip; | ||
49 | struct udphdr udp; | ||
50 | - unsigned char *upp, *endbuf; | ||
51 | + unsigned char *upp; | ||
52 | u_int32_t ip_len, ulen, pkt_len; | ||
53 | static unsigned int ip_packets_seen = 0; | ||
54 | static unsigned int ip_packets_bad_checksum = 0; | ||
55 | @@ -241,11 +262,8 @@ decode_udp_ip_header(struct interface_info *interface, | ||
56 | static unsigned int udp_packets_length_overflow = 0; | ||
57 | unsigned len; | ||
58 | |||
59 | - /* Designate the end of the input buffer for bounds checks. */ | ||
60 | - endbuf = buf + bufix + buflen; | ||
61 | - | ||
62 | /* Assure there is at least an IP header there. */ | ||
63 | - if ((buf + bufix + sizeof(ip)) > endbuf) | ||
64 | + if (sizeof(ip) > buflen) | ||
65 | return -1; | ||
66 | |||
67 | /* Copy the IP header into a stack aligned structure for inspection. | ||
68 | @@ -257,13 +275,17 @@ decode_udp_ip_header(struct interface_info *interface, | ||
69 | ip_len = (*upp & 0x0f) << 2; | ||
70 | upp += ip_len; | ||
71 | |||
72 | - /* Check the IP packet length. */ | ||
73 | + /* Check packet lengths are within the buffer: | ||
74 | + * first the ip header (ip_len) | ||
75 | + * then the packet length from the ip header (pkt_len) | ||
76 | + * then the udp header (ip_len + sizeof(udp) | ||
77 | + * We are liberal in what we accept, the udp payload should fit within | ||
78 | + * pkt_len, but we only check against the full buffer size. | ||
79 | + */ | ||
80 | pkt_len = ntohs(ip.ip_len); | ||
81 | - if (pkt_len > buflen) | ||
82 | - return -1; | ||
83 | - | ||
84 | - /* Assure after ip_len bytes that there is enough room for a UDP header. */ | ||
85 | - if ((upp + sizeof(udp)) > endbuf) | ||
86 | + if ((ip_len > buflen) || | ||
87 | + (pkt_len > buflen) || | ||
88 | + ((ip_len + sizeof(udp)) > buflen)) | ||
89 | return -1; | ||
90 | |||
91 | /* Copy the UDP header into a stack aligned structure for inspection. */ | ||
92 | @@ -284,7 +306,8 @@ decode_udp_ip_header(struct interface_info *interface, | ||
93 | return -1; | ||
94 | |||
95 | udp_packets_length_checked++; | ||
96 | - if ((upp + ulen) > endbuf) { | ||
97 | + /* verify that the payload length from the udp packet fits in the buffer */ | ||
98 | + if ((ip_len + ulen) > buflen) { | ||
99 | udp_packets_length_overflow++; | ||
100 | if (((udp_packets_length_checked > 4) && | ||
101 | (udp_packets_length_overflow != 0)) && | ||
diff --git a/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605_1.patch b/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605_1.patch new file mode 100644 index 0000000000..aa93c5e123 --- /dev/null +++ b/meta/recipes-connectivity/dhcp/dhcp/CVE-2015-8605_1.patch | |||
@@ -0,0 +1,131 @@ | |||
1 | This patch is needed in order to apply the patch for CVE-2015-8605. | ||
2 | |||
3 | Upstream-Status: Backport (4.3.2+) | ||
4 | |||
5 | From: https://source.isc.org/cgi-bin/gitweb.cgi?p=dhcp.git;a=commit;h=0ce1aa94454ce9b50d592c08d7e0c559d38d3bc5 | ||
6 | |||
7 | Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com> | ||
8 | --- | ||
9 | From 0ce1aa94454ce9b50d592c08d7e0c559d38d3bc5 Mon Sep 17 00:00:00 2001 | ||
10 | From: Thomas Markwalder <tmark@isc.org> | ||
11 | Date: Mon, 8 Sep 2014 09:31:32 -0400 | ||
12 | Subject: [PATCH] [master] Corrected error in UDP bad packet logging | ||
13 | |||
14 | Merges in rt36897 | ||
15 | --- | ||
16 | common/packet.c | 55 +++++++++++++++++++++++++++++++++++-------------------- | ||
17 | 1 file changed, 35 insertions(+), 20 deletions(-) | ||
18 | |||
19 | diff --git a/common/packet.c b/common/packet.c | ||
20 | index 45e96e8..7460f3d 100644 | ||
21 | --- a/common/packet.c | ||
22 | +++ b/common/packet.c | ||
23 | @@ -3,7 +3,7 @@ | ||
24 | Packet assembly code, originally contributed by Archie Cobbs. */ | ||
25 | |||
26 | /* | ||
27 | - * Copyright (c) 2009,2012 by Internet Systems Consortium, Inc. ("ISC") | ||
28 | + * Copyright (c) 2009,2012,2014 by Internet Systems Consortium, Inc. ("ISC") | ||
29 | * Copyright (c) 2004,2005,2007 by Internet Systems Consortium, Inc. ("ISC") | ||
30 | * Copyright (c) 1996-2003 by Internet Software Consortium | ||
31 | * | ||
32 | @@ -234,12 +234,12 @@ decode_udp_ip_header(struct interface_info *interface, | ||
33 | unsigned char *upp, *endbuf; | ||
34 | u_int32_t ip_len, ulen, pkt_len; | ||
35 | u_int32_t sum, usum; | ||
36 | - static int ip_packets_seen; | ||
37 | - static int ip_packets_bad_checksum; | ||
38 | - static int udp_packets_seen; | ||
39 | - static int udp_packets_bad_checksum; | ||
40 | - static int udp_packets_length_checked; | ||
41 | - static int udp_packets_length_overflow; | ||
42 | + static unsigned int ip_packets_seen = 0; | ||
43 | + static unsigned int ip_packets_bad_checksum = 0; | ||
44 | + static unsigned int udp_packets_seen = 0; | ||
45 | + static unsigned int udp_packets_bad_checksum = 0; | ||
46 | + static unsigned int udp_packets_length_checked = 0; | ||
47 | + static unsigned int udp_packets_length_overflow = 0; | ||
48 | unsigned len; | ||
49 | |||
50 | /* Designate the end of the input buffer for bounds checks. */ | ||
51 | @@ -287,10 +287,10 @@ decode_udp_ip_header(struct interface_info *interface, | ||
52 | udp_packets_length_checked++; | ||
53 | if ((upp + ulen) > endbuf) { | ||
54 | udp_packets_length_overflow++; | ||
55 | - if ((udp_packets_length_checked > 4) && | ||
56 | - ((udp_packets_length_checked / | ||
57 | - udp_packets_length_overflow) < 2)) { | ||
58 | - log_info("%d udp packets in %d too long - dropped", | ||
59 | + if (((udp_packets_length_checked > 4) && | ||
60 | + (udp_packets_length_overflow != 0)) && | ||
61 | + ((udp_packets_length_checked / udp_packets_length_overflow) < 2)) { | ||
62 | + log_info("%u udp packets in %u too long - dropped", | ||
63 | udp_packets_length_overflow, | ||
64 | udp_packets_length_checked); | ||
65 | udp_packets_length_overflow = 0; | ||
66 | @@ -299,22 +299,31 @@ decode_udp_ip_header(struct interface_info *interface, | ||
67 | return -1; | ||
68 | } | ||
69 | |||
70 | - if ((ulen < sizeof(udp)) || ((upp + ulen) > endbuf)) | ||
71 | - return -1; | ||
72 | + /* If at least 5 with less than 50% bad, start over */ | ||
73 | + if (udp_packets_length_checked > 4) { | ||
74 | + udp_packets_length_overflow = 0; | ||
75 | + udp_packets_length_checked = 0; | ||
76 | + } | ||
77 | |||
78 | /* Check the IP header checksum - it should be zero. */ | ||
79 | - ++ip_packets_seen; | ||
80 | + ip_packets_seen++; | ||
81 | if (wrapsum (checksum (buf + bufix, ip_len, 0))) { | ||
82 | ++ip_packets_bad_checksum; | ||
83 | - if (ip_packets_seen > 4 && | ||
84 | - (ip_packets_seen / ip_packets_bad_checksum) < 2) { | ||
85 | - log_info ("%d bad IP checksums seen in %d packets", | ||
86 | + if (((ip_packets_seen > 4) && (ip_packets_bad_checksum != 0)) && | ||
87 | + ((ip_packets_seen / ip_packets_bad_checksum) < 2)) { | ||
88 | + log_info ("%u bad IP checksums seen in %u packets", | ||
89 | ip_packets_bad_checksum, ip_packets_seen); | ||
90 | ip_packets_seen = ip_packets_bad_checksum = 0; | ||
91 | } | ||
92 | return -1; | ||
93 | } | ||
94 | |||
95 | + /* If at least 5 with less than 50% bad, start over */ | ||
96 | + if (ip_packets_seen > 4) { | ||
97 | + ip_packets_bad_checksum = 0; | ||
98 | + ip_packets_seen = 0; | ||
99 | + } | ||
100 | + | ||
101 | /* Copy out the IP source address... */ | ||
102 | memcpy(&from->sin_addr, &ip.ip_src, 4); | ||
103 | |||
104 | @@ -339,15 +348,21 @@ decode_udp_ip_header(struct interface_info *interface, | ||
105 | udp_packets_seen++; | ||
106 | if (usum && usum != sum) { | ||
107 | udp_packets_bad_checksum++; | ||
108 | - if (udp_packets_seen > 4 && | ||
109 | - (udp_packets_seen / udp_packets_bad_checksum) < 2) { | ||
110 | - log_info ("%d bad udp checksums in %d packets", | ||
111 | + if (((udp_packets_seen > 4) && (udp_packets_bad_checksum != 0)) && | ||
112 | + ((udp_packets_seen / udp_packets_bad_checksum) < 2)) { | ||
113 | + log_info ("%u bad udp checksums in %u packets", | ||
114 | udp_packets_bad_checksum, udp_packets_seen); | ||
115 | udp_packets_seen = udp_packets_bad_checksum = 0; | ||
116 | } | ||
117 | return -1; | ||
118 | } | ||
119 | |||
120 | + /* If at least 5 with less than 50% bad, start over */ | ||
121 | + if (udp_packets_seen > 4) { | ||
122 | + udp_packets_bad_checksum = 0; | ||
123 | + udp_packets_seen = 0; | ||
124 | + } | ||
125 | + | ||
126 | /* Copy out the port... */ | ||
127 | memcpy (&from -> sin_port, &udp.uh_sport, sizeof udp.uh_sport); | ||
128 | |||
129 | -- | ||
130 | 2.6.2 | ||
131 | |||
diff --git a/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb b/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb index d4414cc347..46166932f9 100644 --- a/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb +++ b/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb | |||
@@ -6,7 +6,9 @@ SRC_URI += "file://dhcp-3.0.3-dhclient-dbus.patch;striplevel=0 \ | |||
6 | file://fixsepbuild.patch \ | 6 | file://fixsepbuild.patch \ |
7 | file://dhclient-script-drop-resolv.conf.dhclient.patch \ | 7 | file://dhclient-script-drop-resolv.conf.dhclient.patch \ |
8 | file://replace-ifconfig-route.patch \ | 8 | file://replace-ifconfig-route.patch \ |
9 | file://CVE-2015-8605_1.patch \ | ||
9 | file://dhcp-xen-checksum.patch \ | 10 | file://dhcp-xen-checksum.patch \ |
11 | file://CVE-2015-8605.patch \ | ||
10 | " | 12 | " |
11 | 13 | ||
12 | SRC_URI[md5sum] = "b3a42ece3c7f2cd2e74a3e12ca881d20" | 14 | SRC_URI[md5sum] = "b3a42ece3c7f2cd2e74a3e12ca881d20" |