chiark / gitweb /
resolve: fix redirection loops in compressed RR
authorStanisław Pitucha <viraptor@gmail.com>
Tue, 18 Nov 2014 05:25:20 +0000 (16:25 +1100)
committerDavid Herrmann <dh.herrmann@gmail.com>
Thu, 27 Nov 2014 15:35:56 +0000 (16:35 +0100)
Loops in RR compression were only detected for the first entry.
Multiple redirections should be allowed, each one checking for an
infinite loop on its own starting point.
Also update the pointer on each redirection to avoid longer loops of
labels and redirections, in names like:
(start) [len=1] "A", [ptr to start]

(David: rename variable to "jump_barrier" and add reference to RFC)

src/resolve/resolved-dns-packet.c

index e5d07b3b1ff06666e4be428fd4f78ac31ec62b48..2afb8d05da7dc666872ea4f2f92e60d27bbca179 100644 (file)
@@ -860,7 +860,7 @@ fail:
 
 int dns_packet_read_name(DnsPacket *p, char **_ret,
                          bool allow_compression, size_t *start) {
 
 int dns_packet_read_name(DnsPacket *p, char **_ret,
                          bool allow_compression, size_t *start) {
-        size_t saved_rindex, after_rindex = 0;
+        size_t saved_rindex, after_rindex = 0, jump_barrier;
         _cleanup_free_ char *ret = NULL;
         size_t n = 0, allocated = 0;
         bool first = true;
         _cleanup_free_ char *ret = NULL;
         size_t n = 0, allocated = 0;
         bool first = true;
@@ -870,6 +870,7 @@ int dns_packet_read_name(DnsPacket *p, char **_ret,
         assert(_ret);
 
         saved_rindex = p->rindex;
         assert(_ret);
 
         saved_rindex = p->rindex;
+        jump_barrier = p->rindex;
 
         for (;;) {
                 uint8_t c, d;
 
         for (;;) {
                 uint8_t c, d;
@@ -916,7 +917,7 @@ int dns_packet_read_name(DnsPacket *p, char **_ret,
                                 goto fail;
 
                         ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
                                 goto fail;
 
                         ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
-                        if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
+                        if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
                                 r = -EBADMSG;
                                 goto fail;
                         }
                                 r = -EBADMSG;
                                 goto fail;
                         }
@@ -924,6 +925,8 @@ int dns_packet_read_name(DnsPacket *p, char **_ret,
                         if (after_rindex == 0)
                                 after_rindex = p->rindex;
 
                         if (after_rindex == 0)
                                 after_rindex = p->rindex;
 
+                        /* Jumps are limited to a "prior occurence" (RFC-1035 4.1.4) */
+                        jump_barrier = ptr;
                         p->rindex = ptr;
                 } else
                         goto fail;
                         p->rindex = ptr;
                 } else
                         goto fail;