Magellan Linux

Annotation of /trunk/glibc/patches/glibc-2.22-CVE-2015-7547.patch

Parent Directory Parent Directory | Revision Log Revision Log


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