BUG: dns: Fix off-by-one write in dns_validate_dns_response()
The maximum number of bytes in a DNS name is indeed 255, but we
need to allocate one more byte for the NULL-terminating byte.
Otherwise dns_read_name() might return 255 for a very long name,
causing dns_validate_dns_response() to write a NULL value one
byte after the end of the buffer:
dns_answer_record->name[len] = 0;
The next fields in the struct being filled from the content of the
query, it might have been possible to fill them with non-0 values,
causing for example a strlen() of the name to read past the end of
the struct and access unintended parts of the memory, possibly
leading to a crash.
To be backported to 1.8, probably also 1.7.
diff --git a/include/types/dns.h b/include/types/dns.h
index 0ebe380..3d022d4 100644
--- a/include/types/dns.h
+++ b/include/types/dns.h
@@ -115,9 +115,9 @@
/* NOTE: big endian structure */
struct dns_query_item {
- char name[DNS_MAX_NAME_SIZE]; /* query name */
- unsigned short type; /* question type */
- unsigned short class; /* query class */
+ char name[DNS_MAX_NAME_SIZE+1]; /* query name */
+ unsigned short type; /* question type */
+ unsigned short class; /* query class */
struct list list;
};
@@ -138,17 +138,17 @@
/* NOTE: big endian structure */
struct dns_answer_item {
/*For SRV type, name also includes service and protocol value */
- char name[DNS_MAX_NAME_SIZE]; /* answer name */
- int16_t type; /* question type */
- int16_t class; /* query class */
- int32_t ttl; /* response TTL */
- int16_t priority; /* SRV type priority */
- uint16_t weight; /* SRV type weight */
- int16_t port; /* SRV type port */
- uint16_t data_len; /* number of bytes in target below */
- struct sockaddr address; /* IPv4 or IPv6, network format */
- char target[DNS_MAX_NAME_SIZE]; /* Response data: SRV or CNAME type target */
- time_t last_seen; /* When was the answer was last seen */
+ char name[DNS_MAX_NAME_SIZE+1]; /* answer name */
+ int16_t type; /* question type */
+ int16_t class; /* query class */
+ int32_t ttl; /* response TTL */
+ int16_t priority; /* SRV type priority */
+ uint16_t weight; /* SRV type weight */
+ int16_t port; /* SRV type port */
+ uint16_t data_len; /* number of bytes in target below */
+ struct sockaddr address; /* IPv4 or IPv6, network format */
+ char target[DNS_MAX_NAME_SIZE+1]; /* Response data: SRV or CNAME type target */
+ time_t last_seen; /* When was the answer was last seen */
struct list list;
};