[sr-dev] git:master:20752cf9: core: resolve - early safety checks to deal faster with broken dns responses

Daniel-Constantin Mierla miconda at gmail.com
Sat Dec 30 17:51:15 CET 2017


Module: kamailio
Branch: master
Commit: 20752cf945d4ba0660d321d73efff5c93f6d20a8
URL: https://github.com/kamailio/kamailio/commit/20752cf945d4ba0660d321d73efff5c93f6d20a8

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at gmail.com>
Date: 2017-12-30T16:57:42+01:00

core: resolve - early safety checks to deal faster with broken dns responses

---

Modified: src/core/resolve.c

---

Diff:  https://github.com/kamailio/kamailio/commit/20752cf945d4ba0660d321d73efff5c93f6d20a8.diff
Patch: https://github.com/kamailio/kamailio/commit/20752cf945d4ba0660d321d73efff5c93f6d20a8.patch

---

diff --git a/src/core/resolve.c b/src/core/resolve.c
index 0daaa30910..2b1441e36d 100644
--- a/src/core/resolve.c
+++ b/src/core/resolve.c
@@ -679,13 +679,16 @@ void free_rdata_list(struct rdata* head)
 int match_search_list(const struct __res_state* res, char* name) {
 	int i;
 	for (i=0; (i<MAXDNSRCH) && (res->dnsrch[i]); i++) {
-		if (strcasecmp(name, res->dnsrch[i])==0) 
+		if (strcasecmp(name, res->dnsrch[i])==0)
 			return 1;
 	}
 	return 0;
 }
 #endif
 
+#define SR_DNS_MAX_QNO 10
+#define SR_DNS_MAX_ANO 100
+
 /** gets the DNS records for name:type
  * returns a dyn. alloc'ed struct rdata linked list with the parsed responses
  * or 0 on error
@@ -714,7 +717,7 @@ struct rdata* get_record(char* name, int type, int flags)
 	int name_len;
 	struct rdata* fullname_rd;
 	char c;
-	
+
 	name_len=strlen(name);
 
 	for (i = 0; i < name_len; i++) {
@@ -744,12 +747,21 @@ struct rdata* get_record(char* name, int type, int flags)
 	else if (unlikely(size > sizeof(buff))) size=sizeof(buff);
 	head=rd=0;
 	last=crt=&head;
-	
+
 	p=buff.buff+DNS_HDR_SIZE;
 	end=buff.buff+size;
 	if (unlikely(p>=end)) goto error_boundary;
 	qno=ntohs((unsigned short)buff.hdr.qdcount);
 
+	if(qno!=1) {
+		/* usually the query is with a single domain name */
+		LM_INFO("dns questions number is: %u\n", (uint32_t)qno);
+		if(qno>SR_DNS_MAX_QNO) {
+			/* early safe check against broken results */
+			LM_ERR("dns questions number is too high: %u\n", (uint32_t)qno);
+			goto error;
+		}
+	}
 	for (r=0; r<qno; r++){
 		/* skip the name of the question */
 		if (unlikely((p=dns_skipname(p, end))==0)) {
@@ -765,8 +777,13 @@ struct rdata* get_record(char* name, int type, int flags)
 			LM_ERR("p>=end\n");
 			goto error;
 		}
-	};
+	}
 	answers_no=ntohs((unsigned short)buff.hdr.ancount);
+	if(answers_no>SR_DNS_MAX_ANO) {
+		/* early safety check on answers number */
+		LM_ERR("dns answers number is too high: %u\n", (uint32_t)answers_no);
+		goto error;
+	}
 again:
 	for (r=0; (r<answers_no) && (p<end); r++){
 #if 0
@@ -815,7 +832,7 @@ struct rdata* get_record(char* name, int type, int flags)
 			continue;
 		}
 		/* expand the "type" record  (rdata)*/
-		
+
 		rd=(struct rdata*) local_malloc(sizeof(struct rdata)+rec_name_len+
 										1-1);
 		if (rd==0){
@@ -857,14 +874,14 @@ struct rdata* get_record(char* name, int type, int flags)
 				srv_rd= dns_srv_parser(buff.buff, end, rd_end, p);
 				rd->rdata=(void*)srv_rd;
 				if (unlikely(srv_rd==0)) goto error_parse;
-				
+
 				/* insert sorted into the list */
 				for (crt=&head; *crt; crt= &((*crt)->next)){
 					if ((*crt)->type!=T_SRV)
 						continue;
 					crt_srv=(struct srv_rdata*)(*crt)->rdata;
 					if ((srv_rd->priority <  crt_srv->priority) ||
-					   ( (srv_rd->priority == crt_srv->priority) && 
+					   ( (srv_rd->priority == crt_srv->priority) &&
 							 (srv_rd->weight > crt_srv->weight) ) ){
 						/* insert here */
 						goto skip;
@@ -926,9 +943,9 @@ struct rdata* get_record(char* name, int type, int flags)
 				*last=rd;
 				last=&(rd->next);
 		}
-		
+
 		p+=rdlength;
-		
+
 	}
 	if (flags & RES_AR){
 		flags&=~RES_AR;




More information about the sr-dev mailing list