gdhcp: Fix packet length checking
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Thu, 3 May 2012 13:28:40 +0000 (16:28 +0300)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Fri, 4 May 2012 09:53:14 +0000 (12:53 +0300)
Fix packet length checking where payload length could have been zero.
Also check that we don't set the option pointer beyond the end of the
packet payload.

gdhcp/common.c

index 91c428c..8d5c284 100644 (file)
@@ -155,14 +155,16 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
        rem = pkt_len - 1 - 3;
 
        if (rem <= 0)
-               /* Bad packet */
-               return NULL;
+               goto bad_packet;
 
        while (1) {
                opt_code = optionptr[0] << 8 | optionptr[1];
                opt_len = len = optionptr[2] << 8 | optionptr[3];
                len += 2 + 2; /* skip code and len */
 
+               if (len < 4)
+                       goto bad_packet;
+
                rem -= len;
                if (rem < 0)
                        break;
@@ -170,7 +172,10 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
                if (opt_code == code) {
                        if (option_len != NULL)
                                *option_len = opt_len;
-                       found = optionptr + 2 + 2;
+                       if (rem == 0)
+                               found = NULL;
+                       else
+                               found = optionptr + 2 + 2;
                        count++;
                }
 
@@ -184,6 +189,13 @@ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
                *option_count = count;
 
        return found;
+
+bad_packet:
+       if (option_len != NULL)
+               *option_len = 0;
+       if (option_count != NULL)
+               *option_count = 0;
+       return NULL;
 }
 
 uint8_t *dhcpv6_get_sub_option(unsigned char *option, uint16_t max_len,