@@ -20,30 +20,43 @@ namespace {
2020 constexpr unsigned int RECORD_PTR = 12 ;
2121}
2222
23- static frg::string<MemoryAllocator> read_dns_name (char *buf, char *&it) {
23+ static frg::optional<frg::string<MemoryAllocator>> read_dns_name (uint8_t *buf,
24+ size_t buf_size, uint8_t *&it) {
2425 frg::string<MemoryAllocator> res{getAllocator ()};
25- while ( true ) {
26- char code = *it++;
27- if ((code & 0xC0 ) == 0xC0 ) {
26+ while (it < buf + buf_size ) {
27+ uint8_t code = *it++;
28+ if ((code & 0xC0 ) == 0xC0 ) {
2829 // pointer
30+ if (it + 1 > buf + buf_size)
31+ return frg::null_opt;
32+
2933 uint8_t offset = ((code & 0x3F ) << 8 ) | *it++;
34+ if (offset >= buf_size)
35+ return frg::null_opt;
36+
3037 auto offset_it = buf + offset;
31- return res + read_dns_name (buf, offset_it);
32- } else if (!(code & 0xC0 )) {
38+ auto sub_name = read_dns_name (buf, buf_size, offset_it);
39+ if (!sub_name)
40+ return frg::null_opt;
41+
42+ return res + *sub_name;
43+ } else if (!(code & 0xC0 )) {
3344 if (!code)
34- break ;
45+ return res;
46+ else if (it + code > buf + buf_size)
47+ return frg::null_opt;
3548
3649 for (int i = 0 ; i < code; i++)
3750 res += (*it++);
3851
39- if (*it)
52+ if (it < buf + buf_size && *it)
4053 res += ' .' ;
4154 } else {
42- break ;
55+ return frg::null_opt ;
4356 }
4457 }
4558
46- return res ;
59+ return frg::null_opt ;
4760}
4861
4962int lookup_name_dns (struct lookup_result &buf, const char *name,
@@ -105,10 +118,10 @@ int lookup_name_dns(struct lookup_result &buf, const char *name,
105118 return -EAI_SYSTEM;
106119 }
107120
108- char response[256 ];
121+ uint8_t response[1500 ];
109122 ssize_t rlen;
110123 int num_ans = 0 ;
111- while ((rlen = recvfrom (fd, response, 256 , 0 , NULL , NULL )) >= 0 ) {
124+ while ((rlen = recvfrom (fd, response, sizeof (response) , 0 , NULL , NULL )) >= 0 ) {
112125 if ((size_t )rlen < sizeof (struct dns_header ))
113126 continue ;
114127 auto response_header = reinterpret_cast <struct dns_header *>(response);
@@ -117,33 +130,44 @@ int lookup_name_dns(struct lookup_result &buf, const char *name,
117130
118131 auto it = response + sizeof (struct dns_header );
119132 for (int i = 0 ; i < ntohs (response_header->no_q ); i++) {
120- auto dns_name = read_dns_name (response, it);
121- (void ) dns_name;
133+ auto dns_name = read_dns_name (response, sizeof (response), it);
134+ if (!dns_name)
135+ return -EAI_FAIL;
122136 it += 4 ;
123137 }
124138
125139 for (int i = 0 ; i < ntohs (response_header->no_ans ); i++) {
126- struct dns_addr_buf buffer;
127- auto dns_name = read_dns_name (response, it);
140+ auto dns_name = read_dns_name (response, sizeof (response), it);
141+ if (!dns_name)
142+ return -EAI_FAIL;
143+ if (it + 10 > response + rlen)
144+ return -EAI_FAIL;
128145
129146 uint16_t rr_type = (it[0 ] << 8 ) | it[1 ];
130147 uint16_t rr_class = (it[2 ] << 8 ) | it[3 ];
131148 uint16_t rr_length = (it[8 ] << 8 ) | it[9 ];
132149 it += 10 ;
133150 (void )rr_class;
151+ if (it + rr_length > response + rlen)
152+ return -EAI_FAIL;
134153
154+ struct dns_addr_buf buffer;
135155 switch (rr_type) {
136156 case RECORD_A:
137157 memcpy (buffer.addr , it, rr_length);
138158 it += rr_length;
139159 buffer.family = AF_INET;
140- buffer.name = std::move (dns_name);
160+ buffer.name = std::move (* dns_name);
141161 buf.buf .push (std::move (buffer));
142162 break ;
143- case RECORD_CNAME:
144- canon_name = read_dns_name (response, it);
145- buf.aliases .push (std::move (dns_name));
163+ case RECORD_CNAME: {
164+ auto cname = read_dns_name (response, sizeof (response), it);
165+ if (!cname)
166+ return -EAI_FAIL;
167+ canon_name = std::move (*cname);
168+ buf.aliases .push (std::move (*dns_name));
146169 break ;
170+ }
147171 default :
148172 mlibc::infoLogger () << " lookup_name_dns: unknown rr type "
149173 << rr_type << frg::endlog;
@@ -234,10 +258,10 @@ int lookup_addr_dns(frg::span<char> name, frg::array<uint8_t, 16> &addr, int fam
234258 return -EAI_SYSTEM;
235259 }
236260
237- char response[256 ];
261+ uint8_t response[1500 ];
238262 ssize_t rlen;
239263 int num_ans = 0 ;
240- while ((rlen = recvfrom (fd, response, 256 , 0 , NULL , NULL )) >= 0 ) {
264+ while ((rlen = recvfrom (fd, response, sizeof (response) , 0 , NULL , NULL )) >= 0 ) {
241265 if ((size_t )rlen < sizeof (struct dns_header ))
242266 continue ;
243267 auto response_header = reinterpret_cast <struct dns_header *>(response);
@@ -246,31 +270,38 @@ int lookup_addr_dns(frg::span<char> name, frg::array<uint8_t, 16> &addr, int fam
246270
247271 auto it = response + sizeof (struct dns_header );
248272 for (int i = 0 ; i < ntohs (response_header->no_q ); i++) {
249- auto dns_name = read_dns_name (response, it);
250- (void ) dns_name;
273+ auto dns_name = read_dns_name (response, sizeof (response), it);
274+ if (!dns_name)
275+ return -EAI_FAIL;
251276 it += 4 ;
252277 }
253278
254279 for (int i = 0 ; i < ntohs (response_header->no_ans ); i++) {
255- struct dns_addr_buf buffer;
256- auto dns_name = read_dns_name (response, it);
280+ auto dns_name = read_dns_name (response, sizeof (response), it);
281+ if (!dns_name)
282+ return -EAI_FAIL;
283+ if (it + 10 > response + rlen)
284+ return -EAI_FAIL;
257285
258286 uint16_t rr_type = (it[0 ] << 8 ) | it[1 ];
259287 uint16_t rr_class = (it[2 ] << 8 ) | it[3 ];
260288 uint16_t rr_length = (it[8 ] << 8 ) | it[9 ];
261289 it += 10 ;
262290 (void )rr_class;
263- (void )rr_length;
264291
265- (void )dns_name;
292+ if (it + rr_length > response + rlen)
293+ return -EAI_FAIL;
266294
295+ struct dns_addr_buf buffer;
267296 switch (rr_type) {
268297 case RECORD_PTR: {
269- auto ptr_name = read_dns_name (response, it);
270- if (ptr_name.size () >= name.size ())
298+ auto ptr_name = read_dns_name (response, sizeof (response), it);
299+ if (!ptr_name)
300+ return -EAI_FAIL;
301+ else if (ptr_name->size () >= name.size ())
271302 return -EAI_OVERFLOW;
272- std::copy (ptr_name. begin (), ptr_name. end (), name.data ());
273- name.data ()[ptr_name. size ()] = ' \0 ' ;
303+ std::copy (ptr_name-> begin (), ptr_name-> end (), name.data ());
304+ name.data ()[ptr_name-> size ()] = ' \0 ' ;
274305 return 1 ;
275306 }
276307 default :
0 commit comments