dns.c: improve input validation
authorKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Sun, 12 Apr 2020 16:53:05 +0000 (17:53 +0100)
committerKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Sun, 19 Apr 2020 20:49:08 +0000 (21:49 +0100)
dns.c scan_name() add more input validation
parse_answer() add remaining length check
dns_handle_packet() add remaining length check

Addresses CVE-2020-11750

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>
dns.c

diff --git a/dns.c b/dns.c
index 86e5ea3aaa6c7f44cc4d52d4082b8ec9580046e0..c64f3b1be3d3e73fa4453a0158d850b958ce110e 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -222,6 +222,7 @@ scan_name(const uint8_t *buffer, int len)
                if (IS_COMPRESSED(l))
                        return offset + 2;
 
+               if (l + 1 > len) return -1;
                len -= l + 1;
                offset += l + 1;
                buffer += l + 1;
@@ -317,7 +318,7 @@ static int parse_answer(struct interface *iface, struct sockaddr *from,
        struct dns_answer *a;
        uint8_t *rdata;
 
-       if (!name) {
+       if (!name || rlen < 0) {
                fprintf(stderr, "dropping: bad question\n");
                return -1;
        }
@@ -421,7 +422,7 @@ dns_handle_packet(struct interface *iface, struct sockaddr *from, uint16_t port,
                char *name = dns_consume_name(buffer, len, &b, &rlen);
                struct dns_question *q;
 
-               if (!name) {
+               if (!name || rlen < 0) {
                        fprintf(stderr, "dropping: bad name\n");
                        return;
                }