From e50bd431d65ea84d182593c19c2c45bd4069423e Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Mon, 10 Mar 2014 18:58:53 -0400 Subject: [PATCH] dhcp.c: handle_packet() calls get_(raw|cooked)_packet(), which returns a signed value where values <0 are errors and >= 0 are lengths. Convert to an unsigned length value if the return is a length. Further, there is a real bug if get_(raw|cooked)_packet() returns an error. handle_packet() should return rather than continuing to validate the packet. The packet validation will almost surely fail, and the negative values of len are constrained to [-1,-2], and the values are determined by errors that are hard to control, so it is extremely unlikely that there are any security issues with this bug. The fix is trivial; the obviously-missing return statement bails out when there's a problem fetching a packet and ndhc immediately goes back to listening for another packet. --- ndhc/dhcp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ndhc/dhcp.c b/ndhc/dhcp.c index 4d15744..b341529 100644 --- a/ndhc/dhcp.c +++ b/ndhc/dhcp.c @@ -495,7 +495,7 @@ void set_listen_none(struct client_state_t *cs) change_listen_mode(cs, LM_NONE); } -static int validate_dhcp_packet(struct client_state_t *cs, int len, +static int validate_dhcp_packet(struct client_state_t *cs, size_t len, struct dhcpmsg *packet, uint8_t *msgtype) { if (len < sizeof *packet - sizeof packet->options) { @@ -531,22 +531,22 @@ static int validate_dhcp_packet(struct client_state_t *cs, int len, void handle_packet(struct client_state_t *cs) { uint8_t msgtype; - int len; struct dhcpmsg packet; if (cs->listenMode == LM_NONE) return; - len = cs->listenMode == LM_RAW ? + int r = cs->listenMode == LM_RAW ? get_raw_packet(cs, &packet) : get_cooked_packet(&packet, cs->listenFd); - - if (len < 0) { + if (r < 0) { // Transient issue handled by packet collection functions. - if (len == -2 || (len == -1 && errno == EINTR)) + if (r == -2 || (r == -1 && errno == EINTR)) return; log_error("Error reading from listening socket: %s. Reopening.", strerror(errno)); change_listen_mode(cs, cs->listenMode); + return; } + size_t len = (size_t)r; if (!validate_dhcp_packet(cs, len, &packet, &msgtype)) return;