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