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 | |
| parent | a5f540db7354b76bcabd0a05d8eb8ba2bff4e911 (diff) | |
| download | connman-1d1a22fe586a455935483708fbe8eaeada79df7f.tar.gz | |
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.
| -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 91c428c13..8d5c284bc 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, |
