diff options
author | Patrik Flykt <patrik.flykt@linux.intel.com> | 2012-05-03 16:28:40 +0300 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2012-05-04 12:53:14 +0300 |
commit | 1d1a22fe586a455935483708fbe8eaeada79df7f (patch) | |
tree | af62888249abb19a68ea75b277199985e23d6ccb /gdhcp | |
parent | a5f540db7354b76bcabd0a05d8eb8ba2bff4e911 (diff) | |
download | connman-1d1a22fe586a455935483708fbe8eaeada79df7f.tar.gz connman-1d1a22fe586a455935483708fbe8eaeada79df7f.tar.bz2 connman-1d1a22fe586a455935483708fbe8eaeada79df7f.zip |
gdhcp: Fix packet length checking
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.
Diffstat (limited to 'gdhcp')
-rw-r--r-- | gdhcp/common.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/gdhcp/common.c b/gdhcp/common.c index 91c428c1..8d5c284b 100644 --- a/gdhcp/common.c +++ b/gdhcp/common.c @@ -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, |