]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: rr - don't read past end of RR when parsing NSEC(3)
authorTom Gundersen <teg@jklm.no>
Thu, 23 Jul 2015 11:13:43 +0000 (13:13 +0200)
committerTom Gundersen <teg@jklm.no>
Thu, 23 Jul 2015 16:06:50 +0000 (18:06 +0200)
We can never read past the end of the packet, so this seems impossible
to exploit, but let's error out early as reading past the end of the
current RR is clearly an error.

Found by Lennart, based on patch by Daniel.

src/resolve/resolved-dns-packet.c

index af219ce4ff453cfd088f421f795af527f8c139d9..25035ed7ee241856cb4d3c289b58b80dfc1588c6 100644 (file)
@@ -1233,6 +1233,38 @@ fail:
         return r;
 }
 
+static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
+        size_t saved_rindex;
+        int r;
+
+        saved_rindex = p->rindex;
+
+        while (p->rindex < saved_rindex + size) {
+                r = dns_packet_read_type_window(p, types, NULL);
+                if (r < 0)
+                        goto fail;
+
+                /* don't read past end of current RR */
+                if (p->rindex > saved_rindex + size) {
+                        r = -EBADMSG;
+                        goto fail;
+                }
+        }
+
+        if (p->rindex != saved_rindex + size) {
+                r = -EBADMSG;
+                goto fail;
+        }
+
+        if (start)
+                *start = saved_rindex;
+
+        return 0;
+fail:
+        dns_packet_rewind(p, saved_rindex);
+        return r;
+}
+
 int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
         _cleanup_free_ char *name = NULL;
         uint16_t class, type;
@@ -1634,11 +1666,12 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
                 if (r < 0)
                         goto fail;
 
-                while (p->rindex != offset + rdlength) {
-                        r = dns_packet_read_type_window(p, &rr->nsec.types, NULL);
-                        if (r < 0)
-                                goto fail;
-                }
+                r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
+                if (r < 0)
+                        goto fail;
+
+                /* NSEC RRs with empty bitmpas makes no sense, but the RFC does not explicitly forbid them
+                   so we allow it */
 
                 break;