Browse Source

r9692@catbus: nickm | 2007-01-21 12:04:22 -0500
Detect pointer loops in DNS requests and replies; avoid infinite loop on such malformed replies. Fixes bug 380.


svn:r9378

Nick Mathewson 18 years ago
parent
commit
ff62a4d91b
2 changed files with 7 additions and 0 deletions
  1. 2 0
      ChangeLog
  2. 5 0
      src/or/eventdns.c

+ 2 - 0
ChangeLog

@@ -27,6 +27,8 @@ Changes in version 0.1.2.7-alpha - 2007-??-??
     - If our system clock jumps back in time, don't publish a negative
     - If our system clock jumps back in time, don't publish a negative
       uptime in the descriptor. Also, don't let the global rate limiting
       uptime in the descriptor. Also, don't let the global rate limiting
       buckets go absurdly negative.
       buckets go absurdly negative.
+    - Detect and reject malformed DNS responses containing circular
+      pointer loops.
 
 
   o Minor bugfixes:
   o Minor bugfixes:
     - When computing clock skew from directory HTTP headers, consider what
     - When computing clock skew from directory HTTP headers, consider what

+ 5 - 0
src/or/eventdns.c

@@ -736,6 +736,7 @@ static inline int
 name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) {
 name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) {
 	int name_end = -1;
 	int name_end = -1;
 	int j = *idx;
 	int j = *idx;
+	int ptr_count = 0;
 #define GET32(x) do { if (j + 4 > length) goto err; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while(0);
 #define GET32(x) do { if (j + 4 > length) goto err; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while(0);
 #define GET16(x) do { if (j + 2 > length) goto err; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while(0);
 #define GET16(x) do { if (j + 2 > length) goto err; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while(0);
 #define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while(0);
 #define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while(0);
@@ -759,7 +760,11 @@ name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) {
 			GET8(ptr_low);
 			GET8(ptr_low);
 			if (name_end < 0) name_end = j;
 			if (name_end < 0) name_end = j;
 			j = (((int)label_len & 0x3f) << 8) + ptr_low;
 			j = (((int)label_len & 0x3f) << 8) + ptr_low;
+			/* Make sure that the target offset is in-bounds. */
 			if (j < 0 || j >= length) return -1;
 			if (j < 0 || j >= length) return -1;
+			/* If we've jumped more times than there are characters in the
+			 * message, we must have a loop. */
+			if (++ptr_count > length) return -1;
 			continue;
 			continue;
 		}
 		}
 		if (label_len > 63) return -1;
 		if (label_len > 63) return -1;