2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-30 13:57:50 +00:00

[master] Clean up packet handling

This commit is contained in:
Shawn Routhier
2015-12-16 16:30:02 -08:00
parent c88dfebddd
commit 4ce21cb630
2 changed files with 41 additions and 13 deletions

View File

@@ -125,6 +125,11 @@ by Eric Young (eay@cryptsoft.com).
in the same packet, see RFC7550 for some discussion.
[ISC-Bugs #40190]
- Update the bounds checking when receiving a packet.
Thanks to Sebastian Poehn from Sophos for the bug report and a suggested
patch.
[ISC-Bugs #41267]
Changes since 4.3.3b1
- None

View File

@@ -220,7 +220,28 @@ ssize_t decode_hw_header (interface, buf, bufix, from)
}
}
/* UDP header and IP header decoded together for convenience. */
/*!
*
* \brief UDP header and IP header decoded together for convenience.
*
* Attempt to decode the UDP and IP headers and, if necessary, checksum
* the packet.
*
* \param inteface - the interface on which the packet was recevied
* \param buf - a pointer to the buffer for the received packet
* \param bufix - where to start processing the buffer, previous
* routines may have processed parts of the buffer already
* \param from - space to return the address of the packet sender
* \param buflen - remaining length of the buffer, this will have been
* decremented by bufix by the caller
* \param rbuflen - space to return the length of the payload from the udp
* header
* \param csum_ready - indication if the checksum is valid for use
* non-zero indicates the checksum should be validated
*
* \return - the index to the first byte of the udp payload (that is the
* start of the DHCP packet
*/
ssize_t
decode_udp_ip_header(struct interface_info *interface,
@@ -231,7 +252,7 @@ decode_udp_ip_header(struct interface_info *interface,
unsigned char *data;
struct ip ip;
struct udphdr udp;
unsigned char *upp, *endbuf;
unsigned char *upp;
u_int32_t ip_len, ulen, pkt_len;
static unsigned int ip_packets_seen = 0;
static unsigned int ip_packets_bad_checksum = 0;
@@ -241,11 +262,8 @@ decode_udp_ip_header(struct interface_info *interface,
static unsigned int udp_packets_length_overflow = 0;
unsigned len;
/* Designate the end of the input buffer for bounds checks. */
endbuf = buf + bufix + buflen;
/* Assure there is at least an IP header there. */
if ((buf + bufix + sizeof(ip)) > endbuf)
if (sizeof(ip) > buflen)
return -1;
/* Copy the IP header into a stack aligned structure for inspection.
@@ -257,13 +275,17 @@ decode_udp_ip_header(struct interface_info *interface,
ip_len = (*upp & 0x0f) << 2;
upp += ip_len;
/* Check the IP packet length. */
/* Check packet lengths are within the buffer:
* first the ip header (ip_len)
* then the packet length from the ip header (pkt_len)
* then the udp header (ip_len + sizeof(udp)
* We are liberal in what we accept, the udp payload should fit within
* pkt_len, but we only check against the full buffer size.
*/
pkt_len = ntohs(ip.ip_len);
if (pkt_len > buflen)
return -1;
/* Assure after ip_len bytes that there is enough room for a UDP header. */
if ((upp + sizeof(udp)) > endbuf)
if ((ip_len > buflen) ||
(pkt_len > buflen) ||
((ip_len + sizeof(udp)) > buflen))
return -1;
/* Copy the UDP header into a stack aligned structure for inspection. */
@@ -284,7 +306,8 @@ decode_udp_ip_header(struct interface_info *interface,
return -1;
udp_packets_length_checked++;
if ((upp + ulen) > endbuf) {
/* verify that the payload length from the udp packet fits in the buffer */
if ((ip_len + ulen) > buflen) {
udp_packets_length_overflow++;
if (((udp_packets_length_checked > 4) &&
(udp_packets_length_overflow != 0)) &&