CRUX-ARM : Home

Home :: Documentation :: Download :: Development :: Community :: Ports :: Packages :: Bugs :: Links :: About :: Donors
openssl: updated to 1.0.2k
[ports/core-arm.git] / glibc / CVE-2015-7547.patch
CommitLineData
51db6920
VM
1Index: b/resolv/nss_dns/dns-host.c
2===================================================================
3--- a/resolv/nss_dns/dns-host.c
4+++ b/resolv/nss_dns/dns-host.c
5@@ -1031,7 +1031,10 @@ gaih_getanswer_slice (const querybuf *an
6 int h_namelen = 0;
7
8 if (ancount == 0)
9- return NSS_STATUS_NOTFOUND;
10+ {
11+ *h_errnop = HOST_NOT_FOUND;
12+ return NSS_STATUS_NOTFOUND;
13+ }
14
15 while (ancount-- > 0 && cp < end_of_message && had_error == 0)
16 {
17@@ -1208,7 +1211,14 @@ gaih_getanswer_slice (const querybuf *an
18 /* Special case here: if the resolver sent a result but it only
19 contains a CNAME while we are looking for a T_A or T_AAAA record,
20 we fail with NOTFOUND instead of TRYAGAIN. */
21- return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
22+ if (canon != NULL)
23+ {
24+ *h_errnop = HOST_NOT_FOUND;
25+ return NSS_STATUS_NOTFOUND;
26+ }
27+
28+ *h_errnop = NETDB_INTERNAL;
29+ return NSS_STATUS_TRYAGAIN;
30 }
31
32
33@@ -1222,11 +1232,101 @@ gaih_getanswer (const querybuf *answer1,
34
35 enum nss_status status = NSS_STATUS_NOTFOUND;
36
37+ /* Combining the NSS status of two distinct queries requires some
38+ compromise and attention to symmetry (A or AAAA queries can be
39+ returned in any order). What follows is a breakdown of how this
40+ code is expected to work and why. We discuss only SUCCESS,
41+ TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
42+ that apply (though RETURN and MERGE exist). We make a distinction
43+ between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
44+ A recoverable TRYAGAIN is almost always due to buffer size issues
45+ and returns ERANGE in errno and the caller is expected to retry
46+ with a larger buffer.
47+
48+ Lastly, you may be tempted to make significant changes to the
49+ conditions in this code to bring about symmetry between responses.
50+ Please don't change anything without due consideration for
51+ expected application behaviour. Some of the synthesized responses
52+ aren't very well thought out and sometimes appear to imply that
53+ IPv4 responses are always answer 1, and IPv6 responses are always
54+ answer 2, but that's not true (see the implemetnation of send_dg
55+ and send_vc to see response can arrive in any order, particlarly
56+ for UDP). However, we expect it holds roughly enough of the time
57+ that this code works, but certainly needs to be fixed to make this
58+ a more robust implementation.
59+
60+ ----------------------------------------------
61+ | Answer 1 Status / | Synthesized | Reason |
62+ | Answer 2 Status | Status | |
63+ |--------------------------------------------|
64+ | SUCCESS/SUCCESS | SUCCESS | [1] |
65+ | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
66+ | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
67+ | SUCCESS/NOTFOUND | SUCCESS | [1] |
68+ | SUCCESS/UNAVAIL | SUCCESS | [1] |
69+ | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
70+ | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
71+ | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
72+ | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
73+ | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
74+ | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
75+ | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
76+ | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
77+ | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
78+ | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
79+ | NOTFOUND/SUCCESS | SUCCESS | [3] |
80+ | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
81+ | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
82+ | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
83+ | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
84+ | UNAVAIL/SUCCESS | UNAVAIL | [4] |
85+ | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
86+ | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
87+ | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
88+ | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
89+ ----------------------------------------------
90+
91+ [1] If the first response is a success we return success.
92+ This ignores the state of the second answer and in fact
93+ incorrectly sets errno and h_errno to that of the second
94+ answer. However because the response is a success we ignore
95+ *errnop and *h_errnop (though that means you touched errno on
96+ success). We are being conservative here and returning the
97+ likely IPv4 response in the first answer as a success.
98+
99+ [2] If the first response is a recoverable TRYAGAIN we return
100+ that instead of looking at the second response. The
101+ expectation here is that we have failed to get an IPv4 response
102+ and should retry both queries.
103+
104+ [3] If the first response was not a SUCCESS and the second
105+ response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
106+ or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
107+ result from the second response, otherwise the first responses
108+ status is used. Again we have some odd side-effects when the
109+ second response is NOTFOUND because we overwrite *errnop and
110+ *h_errnop that means that a first answer of NOTFOUND might see
111+ its *errnop and *h_errnop values altered. Whether it matters
112+ in practice that a first response NOTFOUND has the wrong
113+ *errnop and *h_errnop is undecided.
114+
115+ [4] If the first response is UNAVAIL we return that instead of
116+ looking at the second response. The expectation here is that
117+ it will have failed similarly e.g. configuration failure.
118+
119+ [5] Testing this code is complicated by the fact that truncated
120+ second response buffers might be returned as SUCCESS if the
121+ first answer is a SUCCESS. To fix this we add symmetry to
122+ TRYAGAIN with the second response. If the second response
123+ is a recoverable error we now return TRYAGIN even if the first
124+ response was SUCCESS. */
125+
126 if (anslen1 > 0)
127 status = gaih_getanswer_slice(answer1, anslen1, qname,
128 &pat, &buffer, &buflen,
129 errnop, h_errnop, ttlp,
130 &first);
131+
132 if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
133 || (status == NSS_STATUS_TRYAGAIN
134 /* We want to look at the second answer in case of an
135@@ -1242,8 +1342,15 @@ gaih_getanswer (const querybuf *answer1,
136 &pat, &buffer, &buflen,
137 errnop, h_errnop, ttlp,
138 &first);
139+ /* Use the second response status in some cases. */
140 if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
141 status = status2;
142+ /* Do not return a truncated second response (unless it was
143+ unavoidable e.g. unrecoverable TRYAGAIN). */
144+ if (status == NSS_STATUS_SUCCESS
145+ && (status2 == NSS_STATUS_TRYAGAIN
146+ && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
147+ status = NSS_STATUS_TRYAGAIN;
148 }
149
150 return status;
151Index: b/resolv/res_query.c
152===================================================================
153--- a/resolv/res_query.c
154+++ b/resolv/res_query.c
155@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp,
156 {
157 free (*answerp2);
158 *answerp2 = NULL;
159+ *nanswerp2 = 0;
160 *answerp2_malloced = 0;
161 }
162 }
163@@ -447,6 +448,7 @@ __libc_res_nsearch(res_state statp,
164 {
165 free (*answerp2);
166 *answerp2 = NULL;
167+ *nanswerp2 = 0;
168 *answerp2_malloced = 0;
169 }
170
171@@ -521,6 +523,7 @@ __libc_res_nsearch(res_state statp,
172 {
173 free (*answerp2);
174 *answerp2 = NULL;
175+ *nanswerp2 = 0;
176 *answerp2_malloced = 0;
177 }
178 if (saved_herrno != -1)
179Index: b/resolv/res_send.c
180===================================================================
181--- a/resolv/res_send.c
182+++ b/resolv/res_send.c
183@@ -1,3 +1,20 @@
184+/* Copyright (C) 2016 Free Software Foundation, Inc.
185+ This file is part of the GNU C Library.
186+
187+ The GNU C Library is free software; you can redistribute it and/or
188+ modify it under the terms of the GNU Lesser General Public
189+ License as published by the Free Software Foundation; either
190+ version 2.1 of the License, or (at your option) any later version.
191+
192+ The GNU C Library is distributed in the hope that it will be useful,
193+ but WITHOUT ANY WARRANTY; without even the implied warranty of
194+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
195+ Lesser General Public License for more details.
196+
197+ You should have received a copy of the GNU Lesser General Public
198+ License along with the GNU C Library; if not, see
199+ <http://www.gnu.org/licenses/>. */
200+
201 /*
202 * Copyright (c) 1985, 1989, 1993
203 * The Regents of the University of California. All rights reserved.
204@@ -361,6 +378,8 @@ __libc_res_nsend(res_state statp, const
205 #ifdef USE_HOOKS
206 if (__glibc_unlikely (statp->qhook || statp->rhook)) {
207 if (anssiz < MAXPACKET && ansp) {
208+ /* Always allocate MAXPACKET, callers expect
209+ this specific size. */
210 u_char *buf = malloc (MAXPACKET);
211 if (buf == NULL)
212 return (-1);
213@@ -660,6 +679,77 @@ libresolv_hidden_def (res_nsend)
214
215 /* Private */
216
217+/* The send_vc function is responsible for sending a DNS query over TCP
218+ to the nameserver numbered NS from the res_state STATP i.e.
219+ EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
220+ IPv6 queries at the same serially on the same socket.
221+
222+ Please note that for TCP there is no way to disable sending both
223+ queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP
224+ and sends the queries serially and waits for the result after each
225+ sent query. This implemetnation should be corrected to honour these
226+ options.
227+
228+ Please also note that for TCP we send both queries over the same
229+ socket one after another. This technically violates best practice
230+ since the server is allowed to read the first query, respond, and
231+ then close the socket (to service another client). If the server
232+ does this, then the remaining second query in the socket data buffer
233+ will cause the server to send the client an RST which will arrive
234+ asynchronously and the client's OS will likely tear down the socket
235+ receive buffer resulting in a potentially short read and lost
236+ response data. This will force the client to retry the query again,
237+ and this process may repeat until all servers and connection resets
238+ are exhausted and then the query will fail. It's not known if this
239+ happens with any frequency in real DNS server implementations. This
240+ implementation should be corrected to use two sockets by default for
241+ parallel queries.
242+
243+ The query stored in BUF of BUFLEN length is sent first followed by
244+ the query stored in BUF2 of BUFLEN2 length. Queries are sent
245+ serially on the same socket.
246+
247+ Answers to the query are stored firstly in *ANSP up to a max of
248+ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
249+ is non-NULL (to indicate that modifying the answer buffer is allowed)
250+ then malloc is used to allocate a new response buffer and ANSCP and
251+ ANSP will both point to the new buffer. If more than *ANSSIZP bytes
252+ are needed but ANSCP is NULL, then as much of the response as
253+ possible is read into the buffer, but the results will be truncated.
254+ When truncation happens because of a small answer buffer the DNS
255+ packets header feild TC will bet set to 1, indicating a truncated
256+ message and the rest of the socket data will be read and discarded.
257+
258+ Answers to the query are stored secondly in *ANSP2 up to a max of
259+ *ANSSIZP2 bytes, with the actual response length stored in
260+ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
261+ is non-NULL (required for a second query) then malloc is used to
262+ allocate a new response buffer, *ANSSIZP2 is set to the new buffer
263+ size and *ANSP2_MALLOCED is set to 1.
264+
265+ The ANSP2_MALLOCED argument will eventually be removed as the
266+ change in buffer pointer can be used to detect the buffer has
267+ changed and that the caller should use free on the new buffer.
268+
269+ Note that the answers may arrive in any order from the server and
270+ therefore the first and second answer buffers may not correspond to
271+ the first and second queries.
272+
273+ It is not supported to call this function with a non-NULL ANSP2
274+ but a NULL ANSCP. Put another way, you can call send_vc with a
275+ single unmodifiable buffer or two modifiable buffers, but no other
276+ combination is supported.
277+
278+ It is the caller's responsibility to free the malloc allocated
279+ buffers by detecting that the pointers have changed from their
280+ original values i.e. *ANSCP or *ANSP2 has changed.
281+
282+ If errors are encountered then *TERRNO is set to an appropriate
283+ errno value and a zero result is returned for a recoverable error,
284+ and a less-than zero result is returned for a non-recoverable error.
285+
286+ If no errors are encountered then *TERRNO is left unmodified and
287+ a the length of the first response in bytes is returned. */
288 static int
289 send_vc(res_state statp,
290 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
291@@ -669,11 +759,7 @@ send_vc(res_state statp,
292 {
293 const HEADER *hp = (HEADER *) buf;
294 const HEADER *hp2 = (HEADER *) buf2;
295- u_char *ans = *ansp;
296- int orig_anssizp = *anssizp;
297- // XXX REMOVE
298- // int anssiz = *anssizp;
299- HEADER *anhp = (HEADER *) ans;
300+ HEADER *anhp = (HEADER *) *ansp;
301 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
302 int truncating, connreset, n;
303 /* On some architectures compiler might emit a warning indicating
304@@ -766,6 +852,8 @@ send_vc(res_state statp,
305 * Receive length & response
306 */
307 int recvresp1 = 0;
308+ /* Skip the second response if there is no second query.
309+ To do that we mark the second response as received. */
310 int recvresp2 = buf2 == NULL;
311 uint16_t rlen16;
312 read_len:
313@@ -802,40 +890,14 @@ send_vc(res_state statp,
314 u_char **thisansp;
315 int *thisresplenp;
316 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
317+ /* We have not received any responses
318+ yet or we only have one response to
319+ receive. */
320 thisanssizp = anssizp;
321 thisansp = anscp ?: ansp;
322 assert (anscp != NULL || ansp2 == NULL);
323 thisresplenp = &resplen;
324 } else {
325- if (*anssizp != MAXPACKET) {
326- /* No buffer allocated for the first
327- reply. We can try to use the rest
328- of the user-provided buffer. */
329-#if __GNUC_PREREQ (4, 7)
330- DIAG_PUSH_NEEDS_COMMENT;
331- DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
332-#endif
333-#if _STRING_ARCH_unaligned
334- *anssizp2 = orig_anssizp - resplen;
335- *ansp2 = *ansp + resplen;
336-#else
337- int aligned_resplen
338- = ((resplen + __alignof__ (HEADER) - 1)
339- & ~(__alignof__ (HEADER) - 1));
340- *anssizp2 = orig_anssizp - aligned_resplen;
341- *ansp2 = *ansp + aligned_resplen;
342-#endif
343-#if __GNUC_PREREQ (4, 7)
344- DIAG_POP_NEEDS_COMMENT;
345-#endif
346- } else {
347- /* The first reply did not fit into the
348- user-provided buffer. Maybe the second
349- answer will. */
350- *anssizp2 = orig_anssizp;
351- *ansp2 = *ansp;
352- }
353-
354 thisanssizp = anssizp2;
355 thisansp = ansp2;
356 thisresplenp = resplen2;
357@@ -843,10 +905,14 @@ send_vc(res_state statp,
358 anhp = (HEADER *) *thisansp;
359
360 *thisresplenp = rlen;
361- if (rlen > *thisanssizp) {
362- /* Yes, we test ANSCP here. If we have two buffers
363- both will be allocatable. */
364- if (__glibc_likely (anscp != NULL)) {
365+ /* Is the answer buffer too small? */
366+ if (*thisanssizp < rlen) {
367+ /* If the current buffer is non-NULL and it's not
368+ pointing at the static user-supplied buffer then
369+ we can reallocate it. */
370+ if (thisansp != NULL && thisansp != ansp) {
371+ /* Always allocate MAXPACKET, callers expect
372+ this specific size. */
373 u_char *newp = malloc (MAXPACKET);
374 if (newp == NULL) {
375 *terrno = ENOMEM;
376@@ -858,6 +924,9 @@ send_vc(res_state statp,
377 if (thisansp == ansp2)
378 *ansp2_malloced = 1;
379 anhp = (HEADER *) newp;
380+ /* A uint16_t can't be larger than MAXPACKET
381+ thus it's safe to allocate MAXPACKET but
382+ read RLEN bytes instead. */
383 len = rlen;
384 } else {
385 Dprint(statp->options & RES_DEBUG,
386@@ -1021,6 +1090,66 @@ reopen (res_state statp, int *terrno, in
387 return 1;
388 }
389
390+/* The send_dg function is responsible for sending a DNS query over UDP
391+ to the nameserver numbered NS from the res_state STATP i.e.
392+ EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries
393+ along with the ability to send the query in parallel for both stacks
394+ (default) or serially (RES_SINGLKUP). It also supports serial lookup
395+ with a close and reopen of the socket used to talk to the server
396+ (RES_SNGLKUPREOP) to work around broken name servers.
397+
398+ The query stored in BUF of BUFLEN length is sent first followed by
399+ the query stored in BUF2 of BUFLEN2 length. Queries are sent
400+ in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP).
401+
402+ Answers to the query are stored firstly in *ANSP up to a max of
403+ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
404+ is non-NULL (to indicate that modifying the answer buffer is allowed)
405+ then malloc is used to allocate a new response buffer and ANSCP and
406+ ANSP will both point to the new buffer. If more than *ANSSIZP bytes
407+ are needed but ANSCP is NULL, then as much of the response as
408+ possible is read into the buffer, but the results will be truncated.
409+ When truncation happens because of a small answer buffer the DNS
410+ packets header feild TC will bet set to 1, indicating a truncated
411+ message, while the rest of the UDP packet is discarded.
412+
413+ Answers to the query are stored secondly in *ANSP2 up to a max of
414+ *ANSSIZP2 bytes, with the actual response length stored in
415+ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
416+ is non-NULL (required for a second query) then malloc is used to
417+ allocate a new response buffer, *ANSSIZP2 is set to the new buffer
418+ size and *ANSP2_MALLOCED is set to 1.
419+
420+ The ANSP2_MALLOCED argument will eventually be removed as the
421+ change in buffer pointer can be used to detect the buffer has
422+ changed and that the caller should use free on the new buffer.
423+
424+ Note that the answers may arrive in any order from the server and
425+ therefore the first and second answer buffers may not correspond to
426+ the first and second queries.
427+
428+ It is not supported to call this function with a non-NULL ANSP2
429+ but a NULL ANSCP. Put another way, you can call send_vc with a
430+ single unmodifiable buffer or two modifiable buffers, but no other
431+ combination is supported.
432+
433+ It is the caller's responsibility to free the malloc allocated
434+ buffers by detecting that the pointers have changed from their
435+ original values i.e. *ANSCP or *ANSP2 has changed.
436+
437+ If an answer is truncated because of UDP datagram DNS limits then
438+ *V_CIRCUIT is set to 1 and the return value non-zero to indicate to
439+ the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1
440+ if any progress was made reading a response from the nameserver and
441+ is used by the caller to distinguish between ECONNREFUSED and
442+ ETIMEDOUT (the latter if *GOTSOMEWHERE is 1).
443+
444+ If errors are encountered then *TERRNO is set to an appropriate
445+ errno value and a zero result is returned for a recoverable error,
446+ and a less-than zero result is returned for a non-recoverable error.
447+
448+ If no errors are encountered then *TERRNO is left unmodified and
449+ a the length of the first response in bytes is returned. */
450 static int
451 send_dg(res_state statp,
452 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
453@@ -1030,8 +1159,6 @@ send_dg(res_state statp,
454 {
455 const HEADER *hp = (HEADER *) buf;
456 const HEADER *hp2 = (HEADER *) buf2;
457- u_char *ans = *ansp;
458- int orig_anssizp = *anssizp;
459 struct timespec now, timeout, finish;
460 struct pollfd pfd[1];
461 int ptimeout;
462@@ -1064,6 +1191,8 @@ send_dg(res_state statp,
463 int need_recompute = 0;
464 int nwritten = 0;
465 int recvresp1 = 0;
466+ /* Skip the second response if there is no second query.
467+ To do that we mark the second response as received. */
468 int recvresp2 = buf2 == NULL;
469 pfd[0].fd = EXT(statp).nssocks[ns];
470 pfd[0].events = POLLOUT;
471@@ -1227,55 +1356,56 @@ send_dg(res_state statp,
472 int *thisresplenp;
473
474 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
475+ /* We have not received any responses
476+ yet or we only have one response to
477+ receive. */
478 thisanssizp = anssizp;
479 thisansp = anscp ?: ansp;
480 assert (anscp != NULL || ansp2 == NULL);
481 thisresplenp = &resplen;
482 } else {
483- if (*anssizp != MAXPACKET) {
484- /* No buffer allocated for the first
485- reply. We can try to use the rest
486- of the user-provided buffer. */
487-#if _STRING_ARCH_unaligned
488- *anssizp2 = orig_anssizp - resplen;
489- *ansp2 = *ansp + resplen;
490-#else
491- int aligned_resplen
492- = ((resplen + __alignof__ (HEADER) - 1)
493- & ~(__alignof__ (HEADER) - 1));
494- *anssizp2 = orig_anssizp - aligned_resplen;
495- *ansp2 = *ansp + aligned_resplen;
496-#endif
497- } else {
498- /* The first reply did not fit into the
499- user-provided buffer. Maybe the second
500- answer will. */
501- *anssizp2 = orig_anssizp;
502- *ansp2 = *ansp;
503- }
504-
505 thisanssizp = anssizp2;
506 thisansp = ansp2;
507 thisresplenp = resplen2;
508 }
509
510 if (*thisanssizp < MAXPACKET
511- /* Yes, we test ANSCP here. If we have two buffers
512- both will be allocatable. */
513- && anscp
514+ /* If the current buffer is non-NULL and it's not
515+ pointing at the static user-supplied buffer then
516+ we can reallocate it. */
517+ && (thisansp != NULL && thisansp != ansp)
518 #ifdef FIONREAD
519+ /* Is the size too small? */
520 && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
521 || *thisanssizp < *thisresplenp)
522 #endif
523 ) {
524+ /* Always allocate MAXPACKET, callers expect
525+ this specific size. */
526 u_char *newp = malloc (MAXPACKET);
527 if (newp != NULL) {
528- *anssizp = MAXPACKET;
529- *thisansp = ans = newp;
530+ *thisanssizp = MAXPACKET;
531+ *thisansp = newp;
532 if (thisansp == ansp2)
533 *ansp2_malloced = 1;
534 }
535 }
536+ /* We could end up with truncation if anscp was NULL
537+ (not allowed to change caller's buffer) and the
538+ response buffer size is too small. This isn't a
539+ reliable way to detect truncation because the ioctl
540+ may be an inaccurate report of the UDP message size.
541+ Therefore we use this only to issue debug output.
542+ To do truncation accurately with UDP we need
543+ MSG_TRUNC which is only available on Linux. We
544+ can abstract out the Linux-specific feature in the
545+ future to detect truncation. */
546+ if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
547+ Dprint(statp->options & RES_DEBUG,
548+ (stdout, ";; response may be truncated (UDP)\n")
549+ );
550+ }
551+
552 HEADER *anhp = (HEADER *) *thisansp;
553 socklen_t fromlen = sizeof(struct sockaddr_in6);
554 assert (sizeof(from) <= fromlen);
555