dhcp.c: improve input validation & length checks
authorKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Mon, 13 Apr 2020 08:14:43 +0000 (09:14 +0100)
committerKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Sun, 19 Apr 2020 20:51:38 +0000 (21:51 +0100)
Improve data & structure length validation.

Addresses CVE-2020-11752

Thanks to Guido Vranken <guido@guidovranken.com> for the report who
requested credit be given to 'ForAllSecure Mayhem'.

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
dhcp.c

diff --git a/dhcp.c b/dhcp.c
index aefe34fd80e6c5ab8fe5bc19581e12954e0e782a..4dbdece5ac0144dfaa2b19ea8fb2217b8e48bf09 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -88,8 +88,9 @@ parse_dhcp_options(struct relayd_host *host, struct dhcp_header *dhcp, int len)
        struct dhcp_option *opt = (void *)dhcp->option_data;
        static const uint8_t dest[4] = { 0, 0, 0, 0 };
 
-       while((uint8_t *) opt < end) {
-               if ((uint8_t *) opt + opt->len > end)
+       while((uint8_t *) opt  + sizeof(*opt) < end) {
+               if ((uint8_t *) opt + opt->len > end ||
+                   (uint8_t *) opt + sizeof(*opt) > end )
                        break;
 
                opt = (void *) &opt->data[opt->len];
@@ -136,6 +137,9 @@ bool relayd_handle_dhcp_packet(struct relayd_interface *rif, void *data, int len
        udp = (void *) ((char *) &pkt->iph + (pkt->iph.ihl << 2));
        dhcp = (void *) (udp + 1);
 
+       if ((uint8_t *)udp + sizeof(*udp) > (uint8_t *)data + len )
+               return false;
+
        udplen = ntohs(udp->len);
        if (udplen > len - ((char *) udp - (char *) data))
                return false;