@@ -20,30 +20,49 @@ namespace {
20
20
constexpr unsigned int RECORD_PTR = 12 ;
21
21
}
22
22
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) {
24
25
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 ) {
28
29
// pointer
30
+ if (it + 1 > buf + buf_size) {
31
+ return frg::null_opt;
32
+ }
33
+
29
34
uint8_t offset = ((code & 0x3F ) << 8 ) | *it++;
35
+ if (offset >= buf_size) {
36
+ return frg::null_opt;
37
+ }
38
+
30
39
auto offset_it = buf + offset;
31
- return res + read_dns_name (buf, offset_it);
32
- } else if (!(code & 0xC0 )) {
33
- if (!code)
34
- break ;
40
+ auto sub_name = read_dns_name (buf, buf_size, offset_it);
41
+ if (!sub_name) {
42
+ return frg::null_opt;
43
+ }
44
+
45
+ return res + *sub_name;
46
+ } else if (!(code & 0xC0 )) {
47
+ if (!code) {
48
+ return res;
49
+ } else if (it + code > buf + buf_size) {
50
+ return frg::null_opt;
51
+ }
35
52
36
- for (int i = 0 ; i < code; i++)
53
+ for (int i = 0 ; i < code; i++) {
37
54
res += (*it++);
55
+ }
38
56
39
- if (*it)
57
+ if (it < buf + buf_size && *it) {
40
58
res += ' .' ;
59
+ }
41
60
} else {
42
- break ;
61
+ return frg::null_opt ;
43
62
}
44
63
}
45
64
46
- return res ;
65
+ return frg::null_opt ;
47
66
}
48
67
49
68
int lookup_name_dns (struct lookup_result &buf, const char *name,
@@ -105,10 +124,10 @@ int lookup_name_dns(struct lookup_result &buf, const char *name,
105
124
return -EAI_SYSTEM;
106
125
}
107
126
108
- char response[256 ];
127
+ uint8_t response[1500 ];
109
128
ssize_t rlen;
110
129
int num_ans = 0 ;
111
- while ((rlen = recvfrom (fd, response, 256 , 0 , NULL , NULL )) >= 0 ) {
130
+ while ((rlen = recvfrom (fd, response, sizeof (response) , 0 , NULL , NULL )) >= 0 ) {
112
131
if ((size_t )rlen < sizeof (struct dns_header ))
113
132
continue ;
114
133
auto response_header = reinterpret_cast <struct dns_header *>(response);
@@ -117,33 +136,48 @@ int lookup_name_dns(struct lookup_result &buf, const char *name,
117
136
118
137
auto it = response + sizeof (struct dns_header );
119
138
for (int i = 0 ; i < ntohs (response_header->no_q ); i++) {
120
- auto dns_name = read_dns_name (response, it);
121
- (void ) dns_name;
139
+ auto dns_name = read_dns_name (response, sizeof (response), it);
140
+ if (!dns_name) {
141
+ return -EAI_FAIL;
142
+ }
122
143
it += 4 ;
123
144
}
124
145
125
146
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);
147
+ auto dns_name = read_dns_name (response, sizeof (response), it);
148
+ if (!dns_name) {
149
+ return -EAI_FAIL;
150
+ } else if (it + 10 > response + rlen) {
151
+ return -EAI_FAIL;
152
+ }
128
153
129
154
uint16_t rr_type = (it[0 ] << 8 ) | it[1 ];
130
155
uint16_t rr_class = (it[2 ] << 8 ) | it[3 ];
131
156
uint16_t rr_length = (it[8 ] << 8 ) | it[9 ];
132
157
it += 10 ;
133
158
(void )rr_class;
159
+ if (it + rr_length > response + rlen) {
160
+ return -EAI_FAIL;
161
+ }
134
162
163
+ struct dns_addr_buf buffer;
135
164
switch (rr_type) {
136
165
case RECORD_A:
137
166
memcpy (buffer.addr , it, rr_length);
138
167
it += rr_length;
139
168
buffer.family = AF_INET;
140
- buffer.name = std::move (dns_name);
169
+ buffer.name = std::move (* dns_name);
141
170
buf.buf .push (std::move (buffer));
142
171
break ;
143
- case RECORD_CNAME:
144
- canon_name = read_dns_name (response, it);
145
- buf.aliases .push (std::move (dns_name));
172
+ case RECORD_CNAME: {
173
+ auto cname = read_dns_name (response, sizeof (response), it);
174
+ if (!cname) {
175
+ return -EAI_FAIL;
176
+ }
177
+ canon_name = std::move (*cname);
178
+ buf.aliases .push (std::move (*dns_name));
146
179
break ;
180
+ }
147
181
default :
148
182
mlibc::infoLogger () << " lookup_name_dns: unknown rr type "
149
183
<< rr_type << frg::endlog;
@@ -234,10 +268,10 @@ int lookup_addr_dns(frg::span<char> name, frg::array<uint8_t, 16> &addr, int fam
234
268
return -EAI_SYSTEM;
235
269
}
236
270
237
- char response[256 ];
271
+ uint8_t response[1500 ];
238
272
ssize_t rlen;
239
273
int num_ans = 0 ;
240
- while ((rlen = recvfrom (fd, response, 256 , 0 , NULL , NULL )) >= 0 ) {
274
+ while ((rlen = recvfrom (fd, response, sizeof (response) , 0 , NULL , NULL )) >= 0 ) {
241
275
if ((size_t )rlen < sizeof (struct dns_header ))
242
276
continue ;
243
277
auto response_header = reinterpret_cast <struct dns_header *>(response);
@@ -246,31 +280,41 @@ int lookup_addr_dns(frg::span<char> name, frg::array<uint8_t, 16> &addr, int fam
246
280
247
281
auto it = response + sizeof (struct dns_header );
248
282
for (int i = 0 ; i < ntohs (response_header->no_q ); i++) {
249
- auto dns_name = read_dns_name (response, it);
250
- (void ) dns_name;
283
+ auto dns_name = read_dns_name (response, sizeof (response), it);
284
+ if (!dns_name) {
285
+ return -EAI_FAIL;
286
+ }
251
287
it += 4 ;
252
288
}
253
289
254
290
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);
291
+ auto dns_name = read_dns_name (response, sizeof (response), it);
292
+ if (!dns_name) {
293
+ return -EAI_FAIL;
294
+ } else if (it + 10 > response + rlen) {
295
+ return -EAI_FAIL;
296
+ }
257
297
258
298
uint16_t rr_type = (it[0 ] << 8 ) | it[1 ];
259
299
uint16_t rr_class = (it[2 ] << 8 ) | it[3 ];
260
300
uint16_t rr_length = (it[8 ] << 8 ) | it[9 ];
261
301
it += 10 ;
262
302
(void )rr_class;
263
- ( void ) rr_length;
264
-
265
- ( void )dns_name;
303
+ if (it + rr_length > response + rlen) {
304
+ return -EAI_FAIL;
305
+ }
266
306
307
+ struct dns_addr_buf buffer;
267
308
switch (rr_type) {
268
309
case RECORD_PTR: {
269
- auto ptr_name = read_dns_name (response, it);
270
- if (ptr_name.size () >= name.size ())
310
+ auto ptr_name = read_dns_name (response, sizeof (response), it);
311
+ if (!ptr_name) {
312
+ return -EAI_FAIL;
313
+ } else if (ptr_name->size () >= name.size ()) {
271
314
return -EAI_OVERFLOW;
272
- std::copy (ptr_name.begin (), ptr_name.end (), name.data ());
273
- name.data ()[ptr_name.size ()] = ' \0 ' ;
315
+ }
316
+ std::copy (ptr_name->begin (), ptr_name->end (), name.data ());
317
+ name.data ()[ptr_name->size ()] = ' \0 ' ;
274
318
return 1 ;
275
319
}
276
320
default :
0 commit comments