diff options
| author | Denys Fedoryshchenko <denys.f@collabora.com> | 2026-08-10 09:43:09 +0300 |
|---|---|---|
| committer | Denys Fedoryshchenko <denys.f@collabora.com> | 2026-08-10 09:43:09 +0300 |
| commit | 7c98f320c3ef7e863a9c7d30bb81735bb4fec46d (patch) | |
| tree | 53f8852abb971c96dcb03fb16c0eb5dd7ea2fc54 | |
| parent | b0e7444cfea168b6b283ca89e00b57494e0bced2 (diff) | |
| download | accel-ppp-7c98f320c3ef7e863a9c7d30bb81735bb4fec46d.tar.gz accel-ppp-7c98f320c3ef7e863a9c7d30bb81735bb4fec46d.zip | |
dhcpv6: read the elapsed time and preference options at their real width
print_time() read a 32 bit word out of the Elapsed Time option, which
RFC 8415 21.9 defines as exactly two octets, and clients include it in
almost every message they send. With verbose enabled that is a two byte
read past the option on every DHCPv6 transaction:
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 4 in print_time dhcpv6_packet.c:499
The value was not byte swapped either, so what got logged was not the
elapsed time. Read two octets, convert them, and copy them out rather
than dereferencing a pointer into the packet that need not be aligned.
print_uint8() has the same shape, so check the length there too before
reading the Preference octet.
| -rw-r--r-- | accel-pppd/ipv6/dhcpv6_packet.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/accel-pppd/ipv6/dhcpv6_packet.c b/accel-pppd/ipv6/dhcpv6_packet.c index 1cae30e6..c0c7bc81 100644 --- a/accel-pppd/ipv6/dhcpv6_packet.c +++ b/accel-pppd/ipv6/dhcpv6_packet.c @@ -498,12 +498,21 @@ static void print_hex_array(struct dhcpv6_option *opt, void (*print)(const char static void print_uint8(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)) { + if (ntohs(opt->hdr->len) < sizeof(uint8_t)) + return; + print(" %i", *(uint8_t *)opt->hdr->data); } static void print_time(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)) { - print(" %u", *(uint32_t *)opt->hdr->data); + uint16_t val; + + if (ntohs(opt->hdr->len) < sizeof(val)) + return; + + memcpy(&val, opt->hdr->data, sizeof(val)); + print(" %u", ntohs(val)); } static void print_ipv6addr(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)) |
