This is an important fix. Looks good to me On Apr 6, 2016 5:35 AM, "Javier Viguera" <[email protected]> wrote:
> CVE-2015-7547: getaddrinfo() stack-based buffer overflow > > Backport patch from GLIBC-2.20 to EGLIBC-2.19. > > Signed-off-by: Javier Viguera <[email protected]> > --- > .../eglibc/eglibc-2.19/CVE-2015-7547.patch | 585 > +++++++++++++++++++++ > meta/recipes-core/eglibc/eglibc_2.19.bb | 1 + > 2 files changed, 586 insertions(+) > create mode 100644 > meta/recipes-core/eglibc/eglibc-2.19/CVE-2015-7547.patch > > diff --git a/meta/recipes-core/eglibc/eglibc-2.19/CVE-2015-7547.patch > b/meta/recipes-core/eglibc/eglibc-2.19/CVE-2015-7547.patch > new file mode 100644 > index 000000000000..2a52e56cb7f4 > --- /dev/null > +++ b/meta/recipes-core/eglibc/eglibc-2.19/CVE-2015-7547.patch > @@ -0,0 +1,585 @@ > +From: Carlos O'Donell <[email protected]> > +Date: Tue, 16 Feb 2016 21:26:37 -0500 > +Subject: [PATCH] CVE-2015-7547: getaddrinfo() stack-based buffer overflow > (Bug > + 18665). > + > +* A stack-based buffer overflow was found in libresolv when invoked from > + libnss_dns, allowing specially crafted DNS responses to seize control > + of execution flow in the DNS client. The buffer overflow occurs in > + the functions send_dg (send datagram) and send_vc (send TCP) for the > + NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC > + family. The use of AF_UNSPEC triggers the low-level resolver code to > + send out two parallel queries for A and AAAA. A mismanagement of the > + buffers used for those queries could result in the response of a query > + writing beyond the alloca allocated buffer created by > + _nss_dns_gethostbyname4_r. Buffer management is simplified to remove > + the overflow. Thanks to the Google Security Team and Red Hat for > + reporting the security impact of this issue, and Robert Holiday of > + Ciena for reporting the related bug 18665. (CVE-2015-7547) > + > +See also: > +https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html > +https://sourceware.org/ml/libc-alpha/2016-02/msg00418.html > + > +Upstream-Status: Backport > +CVE: CVE-2015-7547 > + > +Upstream commit: > + > https://sourceware.org/git/?p=glibc.git;a=commit;h=16d0a0ce7613552301786bf05d7eba8784b5732c > + > +Tweaks: > +* Adapted from GLIBC-2.20 to EGLIBC-2.19 > +* Removed changes to ChangeLog and NEWS files > + > +Signed-off-by: Javier Viguera <[email protected]> > +--- > + resolv/nss_dns/dns-host.c | 111 +++++++++++++++++++- > + resolv/res_query.c | 3 + > + resolv/res_send.c | 257 > +++++++++++++++++++++++++++++++++++----------- > + 3 files changed, 309 insertions(+), 62 deletions(-) > + > +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c > +index f8f192e5afb5..e7e2c7137a50 100644 > +--- a/resolv/nss_dns/dns-host.c > ++++ b/resolv/nss_dns/dns-host.c > +@@ -1049,7 +1049,10 @@ gaih_getanswer_slice (const querybuf *answer, int > anslen, const char *qname, > + int h_namelen = 0; > + > + if (ancount == 0) > +- return NSS_STATUS_NOTFOUND; > ++ { > ++ *h_errnop = HOST_NOT_FOUND; > ++ return NSS_STATUS_NOTFOUND; > ++ } > + > + while (ancount-- > 0 && cp < end_of_message && had_error == 0) > + { > +@@ -1226,7 +1229,14 @@ gaih_getanswer_slice (const querybuf *answer, int > anslen, const char *qname, > + /* Special case here: if the resolver sent a result but it only > + contains a CNAME while we are looking for a T_A or T_AAAA record, > + we fail with NOTFOUND instead of TRYAGAIN. */ > +- return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND; > ++ if (canon != NULL) > ++ { > ++ *h_errnop = HOST_NOT_FOUND; > ++ return NSS_STATUS_NOTFOUND; > ++ } > ++ > ++ *h_errnop = NETDB_INTERNAL; > ++ return NSS_STATUS_TRYAGAIN; > + } > + > + > +@@ -1240,11 +1250,101 @@ gaih_getanswer (const querybuf *answer1, int > anslen1, const querybuf *answer2, > + > + enum nss_status status = NSS_STATUS_NOTFOUND; > + > ++ /* Combining the NSS status of two distinct queries requires some > ++ compromise and attention to symmetry (A or AAAA queries can be > ++ returned in any order). What follows is a breakdown of how this > ++ code is expected to work and why. We discuss only SUCCESS, > ++ TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns > ++ that apply (though RETURN and MERGE exist). We make a distinction > ++ between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable). > ++ A recoverable TRYAGAIN is almost always due to buffer size issues > ++ and returns ERANGE in errno and the caller is expected to retry > ++ with a larger buffer. > ++ > ++ Lastly, you may be tempted to make significant changes to the > ++ conditions in this code to bring about symmetry between responses. > ++ Please don't change anything without due consideration for > ++ expected application behaviour. Some of the synthesized responses > ++ aren't very well thought out and sometimes appear to imply that > ++ IPv4 responses are always answer 1, and IPv6 responses are always > ++ answer 2, but that's not true (see the implementation of send_dg > ++ and send_vc to see response can arrive in any order, particularly > ++ for UDP). However, we expect it holds roughly enough of the time > ++ that this code works, but certainly needs to be fixed to make this > ++ a more robust implementation. > ++ > ++ ---------------------------------------------- > ++ | Answer 1 Status / | Synthesized | Reason | > ++ | Answer 2 Status | Status | | > ++ |--------------------------------------------| > ++ | SUCCESS/SUCCESS | SUCCESS | [1] | > ++ | SUCCESS/TRYAGAIN | TRYAGAIN | [5] | > ++ | SUCCESS/TRYAGAIN' | SUCCESS | [1] | > ++ | SUCCESS/NOTFOUND | SUCCESS | [1] | > ++ | SUCCESS/UNAVAIL | SUCCESS | [1] | > ++ | TRYAGAIN/SUCCESS | TRYAGAIN | [2] | > ++ | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] | > ++ | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] | > ++ | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] | > ++ | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] | > ++ | TRYAGAIN'/SUCCESS | SUCCESS | [3] | > ++ | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] | > ++ | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] | > ++ | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] | > ++ | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] | > ++ | NOTFOUND/SUCCESS | SUCCESS | [3] | > ++ | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] | > ++ | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] | > ++ | NOTFOUND/NOTFOUND | NOTFOUND | [3] | > ++ | NOTFOUND/UNAVAIL | UNAVAIL | [3] | > ++ | UNAVAIL/SUCCESS | UNAVAIL | [4] | > ++ | UNAVAIL/TRYAGAIN | UNAVAIL | [4] | > ++ | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] | > ++ | UNAVAIL/NOTFOUND | UNAVAIL | [4] | > ++ | UNAVAIL/UNAVAIL | UNAVAIL | [4] | > ++ ---------------------------------------------- > ++ > ++ [1] If the first response is a success we return success. > ++ This ignores the state of the second answer and in fact > ++ incorrectly sets errno and h_errno to that of the second > ++ answer. However because the response is a success we ignore > ++ *errnop and *h_errnop (though that means you touched errno on > ++ success). We are being conservative here and returning the > ++ likely IPv4 response in the first answer as a success. > ++ > ++ [2] If the first response is a recoverable TRYAGAIN we return > ++ that instead of looking at the second response. The > ++ expectation here is that we have failed to get an IPv4 response > ++ and should retry both queries. > ++ > ++ [3] If the first response was not a SUCCESS and the second > ++ response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN, > ++ or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the > ++ result from the second response, otherwise the first responses > ++ status is used. Again we have some odd side-effects when the > ++ second response is NOTFOUND because we overwrite *errnop and > ++ *h_errnop that means that a first answer of NOTFOUND might see > ++ its *errnop and *h_errnop values altered. Whether it matters > ++ in practice that a first response NOTFOUND has the wrong > ++ *errnop and *h_errnop is undecided. > ++ > ++ [4] If the first response is UNAVAIL we return that instead of > ++ looking at the second response. The expectation here is that > ++ it will have failed similarly e.g. configuration failure. > ++ > ++ [5] Testing this code is complicated by the fact that truncated > ++ second response buffers might be returned as SUCCESS if the > ++ first answer is a SUCCESS. To fix this we add symmetry to > ++ TRYAGAIN with the second response. If the second response > ++ is a recoverable error we now return TRYAGIN even if the first > ++ response was SUCCESS. */ > ++ > + if (anslen1 > 0) > + status = gaih_getanswer_slice(answer1, anslen1, qname, > + &pat, &buffer, &buflen, > + errnop, h_errnop, ttlp, > + &first); > ++ > + if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND > + || (status == NSS_STATUS_TRYAGAIN > + /* We want to look at the second answer in case of an > +@@ -1260,8 +1360,15 @@ gaih_getanswer (const querybuf *answer1, int > anslen1, const querybuf *answer2, > + &pat, &buffer, > &buflen, > + errnop, h_errnop, > ttlp, > + &first); > ++ /* Use the second response status in some cases. */ > + if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND) > + status = status2; > ++ /* Do not return a truncated second response (unless it was > ++ unavoidable e.g. unrecoverable TRYAGAIN). */ > ++ if (status == NSS_STATUS_SUCCESS > ++ && (status2 == NSS_STATUS_TRYAGAIN > ++ && *errnop == ERANGE && *h_errnop != NO_RECOVERY)) > ++ status = NSS_STATUS_TRYAGAIN; > + } > + > + return status; > +diff --git a/resolv/res_query.c b/resolv/res_query.c > +index 1325f9772ddc..dd87e097c461 100644 > +--- a/resolv/res_query.c > ++++ b/resolv/res_query.c > +@@ -391,6 +391,7 @@ __libc_res_nsearch(res_state statp, > + { > + free (*answerp2); > + *answerp2 = NULL; > ++ *nanswerp2 = 0; > + } > + } > + > +@@ -431,6 +432,7 @@ __libc_res_nsearch(res_state statp, > + { > + free (*answerp2); > + *answerp2 = NULL; > ++ *nanswerp2 = 0; > + } > + > + /* > +@@ -502,6 +504,7 @@ __libc_res_nsearch(res_state statp, > + { > + free (*answerp2); > + *answerp2 = NULL; > ++ *nanswerp2 = 0; > + } > + if (saved_herrno != -1) > + RES_SET_H_ERRNO(statp, saved_herrno); > +diff --git a/resolv/res_send.c b/resolv/res_send.c > +index 7f2e85f3240e..5940b0c7ebf7 100644 > +--- a/resolv/res_send.c > ++++ b/resolv/res_send.c > +@@ -1,3 +1,20 @@ > ++/* Copyright (C) 2016 Free Software Foundation, Inc. > ++ This file is part of the GNU C Library. > ++ > ++ The GNU C Library is free software; you can redistribute it and/or > ++ modify it under the terms of the GNU Lesser General Public > ++ License as published by the Free Software Foundation; either > ++ version 2.1 of the License, or (at your option) any later version. > ++ > ++ The GNU C Library is distributed in the hope that it will be useful, > ++ but WITHOUT ANY WARRANTY; without even the implied warranty of > ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > ++ Lesser General Public License for more details. > ++ > ++ You should have received a copy of the GNU Lesser General Public > ++ License along with the GNU C Library; if not, see > ++ <http://www.gnu.org/licenses/>. */ > ++ > + /* > + * Copyright (c) 1985, 1989, 1993 > + * The Regents of the University of California. All rights reserved. > +@@ -360,6 +377,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, > int buflen, > + #ifdef USE_HOOKS > + if (__builtin_expect (statp->qhook || statp->rhook, 0)) { > + if (anssiz < MAXPACKET && ansp) { > ++ /* Always allocate MAXPACKET, callers expect > ++ this specific size. */ > + u_char *buf = malloc (MAXPACKET); > + if (buf == NULL) > + return (-1); > +@@ -652,6 +671,77 @@ libresolv_hidden_def (res_nsend) > + > + /* Private */ > + > ++/* The send_vc function is responsible for sending a DNS query over TCP > ++ to the nameserver numbered NS from the res_state STATP i.e. > ++ EXT(statp).nssocks[ns]. The function supports sending both IPv4 and > ++ IPv6 queries at the same serially on the same socket. > ++ > ++ Please note that for TCP there is no way to disable sending both > ++ queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP > ++ and sends the queries serially and waits for the result after each > ++ sent query. This implemetnation should be corrected to honour these > ++ options. > ++ > ++ Please also note that for TCP we send both queries over the same > ++ socket one after another. This technically violates best practice > ++ since the server is allowed to read the first query, respond, and > ++ then close the socket (to service another client). If the server > ++ does this, then the remaining second query in the socket data buffer > ++ will cause the server to send the client an RST which will arrive > ++ asynchronously and the client's OS will likely tear down the socket > ++ receive buffer resulting in a potentially short read and lost > ++ response data. This will force the client to retry the query again, > ++ and this process may repeat until all servers and connection resets > ++ are exhausted and then the query will fail. It's not known if this > ++ happens with any frequency in real DNS server implementations. This > ++ implementation should be corrected to use two sockets by default for > ++ parallel queries. > ++ > ++ The query stored in BUF of BUFLEN length is sent first followed by > ++ the query stored in BUF2 of BUFLEN2 length. Queries are sent > ++ serially on the same socket. > ++ > ++ Answers to the query are stored firstly in *ANSP up to a max of > ++ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP > ++ is non-NULL (to indicate that modifying the answer buffer is allowed) > ++ then malloc is used to allocate a new response buffer and ANSCP and > ++ ANSP will both point to the new buffer. If more than *ANSSIZP bytes > ++ are needed but ANSCP is NULL, then as much of the response as > ++ possible is read into the buffer, but the results will be truncated. > ++ When truncation happens because of a small answer buffer the DNS > ++ packets header field TC will bet set to 1, indicating a truncated > ++ message and the rest of the socket data will be read and discarded. > ++ > ++ Answers to the query are stored secondly in *ANSP2 up to a max of > ++ *ANSSIZP2 bytes, with the actual response length stored in > ++ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 > ++ is non-NULL (required for a second query) then malloc is used to > ++ allocate a new response buffer, *ANSSIZP2 is set to the new buffer > ++ size and *ANSP2_MALLOCED is set to 1. > ++ > ++ The ANSP2_MALLOCED argument will eventually be removed as the > ++ change in buffer pointer can be used to detect the buffer has > ++ changed and that the caller should use free on the new buffer. > ++ > ++ Note that the answers may arrive in any order from the server and > ++ therefore the first and second answer buffers may not correspond to > ++ the first and second queries. > ++ > ++ It is not supported to call this function with a non-NULL ANSP2 > ++ but a NULL ANSCP. Put another way, you can call send_vc with a > ++ single unmodifiable buffer or two modifiable buffers, but no other > ++ combination is supported. > ++ > ++ It is the caller's responsibility to free the malloc allocated > ++ buffers by detecting that the pointers have changed from their > ++ original values i.e. *ANSCP or *ANSP2 has changed. > ++ > ++ If errors are encountered then *TERRNO is set to an appropriate > ++ errno value and a zero result is returned for a recoverable error, > ++ and a less-than zero result is returned for a non-recoverable error. > ++ > ++ If no errors are encountered then *TERRNO is left unmodified and > ++ a the length of the first response in bytes is returned. */ > + static int > + send_vc(res_state statp, > + const u_char *buf, int buflen, const u_char *buf2, int buflen2, > +@@ -661,11 +751,7 @@ send_vc(res_state statp, > + { > + const HEADER *hp = (HEADER *) buf; > + const HEADER *hp2 = (HEADER *) buf2; > +- u_char *ans = *ansp; > +- int orig_anssizp = *anssizp; > +- // XXX REMOVE > +- // int anssiz = *anssizp; > +- HEADER *anhp = (HEADER *) ans; > ++ HEADER *anhp = (HEADER *) *ansp; > + struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns]; > + int truncating, connreset, resplen, n; > + struct iovec iov[4]; > +@@ -741,6 +827,8 @@ send_vc(res_state statp, > + * Receive length & response > + */ > + int recvresp1 = 0; > ++ /* Skip the second response if there is no second query. > ++ To do that we mark the second response as received. */ > + int recvresp2 = buf2 == NULL; > + uint16_t rlen16; > + read_len: > +@@ -777,33 +865,14 @@ send_vc(res_state statp, > + u_char **thisansp; > + int *thisresplenp; > + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { > ++ /* We have not received any responses > ++ yet or we only have one response to > ++ receive. */ > + thisanssizp = anssizp; > + thisansp = anscp ?: ansp; > + assert (anscp != NULL || ansp2 == NULL); > + thisresplenp = &resplen; > + } else { > +- if (*anssizp != MAXPACKET) { > +- /* No buffer allocated for the first > +- reply. We can try to use the rest > +- of the user-provided buffer. */ > +-#ifdef _STRING_ARCH_unaligned > +- *anssizp2 = orig_anssizp - resplen; > +- *ansp2 = *ansp + resplen; > +-#else > +- int aligned_resplen > +- = ((resplen + __alignof__ (HEADER) - 1) > +- & ~(__alignof__ (HEADER) - 1)); > +- *anssizp2 = orig_anssizp - aligned_resplen; > +- *ansp2 = *ansp + aligned_resplen; > +-#endif > +- } else { > +- /* The first reply did not fit into the > +- user-provided buffer. Maybe the second > +- answer will. */ > +- *anssizp2 = orig_anssizp; > +- *ansp2 = *ansp; > +- } > +- > + thisanssizp = anssizp2; > + thisansp = ansp2; > + thisresplenp = resplen2; > +@@ -811,10 +880,14 @@ send_vc(res_state statp, > + anhp = (HEADER *) *thisansp; > + > + *thisresplenp = rlen; > +- if (rlen > *thisanssizp) { > +- /* Yes, we test ANSCP here. If we have two buffers > +- both will be allocatable. */ > +- if (__builtin_expect (anscp != NULL, 1)) { > ++ /* Is the answer buffer too small? */ > ++ if (*thisanssizp < rlen) { > ++ /* If the current buffer is not the the static > ++ user-supplied buffer then we can reallocate > ++ it. */ > ++ if (thisansp != NULL && thisansp != ansp) { > ++ /* Always allocate MAXPACKET, callers expect > ++ this specific size. */ > + u_char *newp = malloc (MAXPACKET); > + if (newp == NULL) { > + *terrno = ENOMEM; > +@@ -824,6 +897,9 @@ send_vc(res_state statp, > + *thisanssizp = MAXPACKET; > + *thisansp = newp; > + anhp = (HEADER *) newp; > ++ /* A uint16_t can't be larger than MAXPACKET > ++ thus it's safe to allocate MAXPACKET but > ++ read RLEN bytes instead. */ > + len = rlen; > + } else { > + Dprint(statp->options & RES_DEBUG, > +@@ -987,6 +1063,66 @@ reopen (res_state statp, int *terrno, int ns) > + return 1; > + } > + > ++/* The send_dg function is responsible for sending a DNS query over UDP > ++ to the nameserver numbered NS from the res_state STATP i.e. > ++ EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries > ++ along with the ability to send the query in parallel for both stacks > ++ (default) or serially (RES_SINGLKUP). It also supports serial lookup > ++ with a close and reopen of the socket used to talk to the server > ++ (RES_SNGLKUPREOP) to work around broken name servers. > ++ > ++ The query stored in BUF of BUFLEN length is sent first followed by > ++ the query stored in BUF2 of BUFLEN2 length. Queries are sent > ++ in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP). > ++ > ++ Answers to the query are stored firstly in *ANSP up to a max of > ++ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP > ++ is non-NULL (to indicate that modifying the answer buffer is allowed) > ++ then malloc is used to allocate a new response buffer and ANSCP and > ++ ANSP will both point to the new buffer. If more than *ANSSIZP bytes > ++ are needed but ANSCP is NULL, then as much of the response as > ++ possible is read into the buffer, but the results will be truncated. > ++ When truncation happens because of a small answer buffer the DNS > ++ packets header field TC will bet set to 1, indicating a truncated > ++ message, while the rest of the UDP packet is discarded. > ++ > ++ Answers to the query are stored secondly in *ANSP2 up to a max of > ++ *ANSSIZP2 bytes, with the actual response length stored in > ++ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 > ++ is non-NULL (required for a second query) then malloc is used to > ++ allocate a new response buffer, *ANSSIZP2 is set to the new buffer > ++ size and *ANSP2_MALLOCED is set to 1. > ++ > ++ The ANSP2_MALLOCED argument will eventually be removed as the > ++ change in buffer pointer can be used to detect the buffer has > ++ changed and that the caller should use free on the new buffer. > ++ > ++ Note that the answers may arrive in any order from the server and > ++ therefore the first and second answer buffers may not correspond to > ++ the first and second queries. > ++ > ++ It is not supported to call this function with a non-NULL ANSP2 > ++ but a NULL ANSCP. Put another way, you can call send_vc with a > ++ single unmodifiable buffer or two modifiable buffers, but no other > ++ combination is supported. > ++ > ++ It is the caller's responsibility to free the malloc allocated > ++ buffers by detecting that the pointers have changed from their > ++ original values i.e. *ANSCP or *ANSP2 has changed. > ++ > ++ If an answer is truncated because of UDP datagram DNS limits then > ++ *V_CIRCUIT is set to 1 and the return value non-zero to indicate to > ++ the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1 > ++ if any progress was made reading a response from the nameserver and > ++ is used by the caller to distinguish between ECONNREFUSED and > ++ ETIMEDOUT (the latter if *GOTSOMEWHERE is 1). > ++ > ++ If errors are encountered then *TERRNO is set to an appropriate > ++ errno value and a zero result is returned for a recoverable error, > ++ and a less-than zero result is returned for a non-recoverable error. > ++ > ++ If no errors are encountered then *TERRNO is left unmodified and > ++ a the length of the first response in bytes is returned. */ > + static int > + send_dg(res_state statp, > + const u_char *buf, int buflen, const u_char *buf2, int buflen2, > +@@ -996,8 +1132,6 @@ send_dg(res_state statp, > + { > + const HEADER *hp = (HEADER *) buf; > + const HEADER *hp2 = (HEADER *) buf2; > +- u_char *ans = *ansp; > +- int orig_anssizp = *anssizp; > + struct timespec now, timeout, finish; > + struct pollfd pfd[1]; > + int ptimeout; > +@@ -1030,6 +1164,8 @@ send_dg(res_state statp, > + int need_recompute = 0; > + int nwritten = 0; > + int recvresp1 = 0; > ++ /* Skip the second response if there is no second query. > ++ To do that we mark the second response as received. */ > + int recvresp2 = buf2 == NULL; > + pfd[0].fd = EXT(statp).nssocks[ns]; > + pfd[0].events = POLLOUT; > +@@ -1193,53 +1329,54 @@ send_dg(res_state statp, > + int *thisresplenp; > + > + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { > ++ /* We have not received any responses > ++ yet or we only have one response to > ++ receive. */ > + thisanssizp = anssizp; > + thisansp = anscp ?: ansp; > + assert (anscp != NULL || ansp2 == NULL); > + thisresplenp = &resplen; > + } else { > +- if (*anssizp != MAXPACKET) { > +- /* No buffer allocated for the first > +- reply. We can try to use the rest > +- of the user-provided buffer. */ > +-#ifdef _STRING_ARCH_unaligned > +- *anssizp2 = orig_anssizp - resplen; > +- *ansp2 = *ansp + resplen; > +-#else > +- int aligned_resplen > +- = ((resplen + __alignof__ (HEADER) - 1) > +- & ~(__alignof__ (HEADER) - 1)); > +- *anssizp2 = orig_anssizp - aligned_resplen; > +- *ansp2 = *ansp + aligned_resplen; > +-#endif > +- } else { > +- /* The first reply did not fit into the > +- user-provided buffer. Maybe the second > +- answer will. */ > +- *anssizp2 = orig_anssizp; > +- *ansp2 = *ansp; > +- } > +- > + thisanssizp = anssizp2; > + thisansp = ansp2; > + thisresplenp = resplen2; > + } > + > + if (*thisanssizp < MAXPACKET > +- /* Yes, we test ANSCP here. If we have two buffers > +- both will be allocatable. */ > +- && anscp > ++ /* If the current buffer is not the the static > ++ user-supplied buffer then we can reallocate > ++ it. */ > ++ && (thisansp != NULL && thisansp != ansp) > + #ifdef FIONREAD > ++ /* Is the size too small? */ > + && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0 > + || *thisanssizp < *thisresplenp) > + #endif > + ) { > ++ /* Always allocate MAXPACKET, callers expect > ++ this specific size. */ > + u_char *newp = malloc (MAXPACKET); > + if (newp != NULL) { > +- *anssizp = MAXPACKET; > +- *thisansp = ans = newp; > ++ *thisanssizp = MAXPACKET; > ++ *thisansp = newp; > + } > + } > ++ /* We could end up with truncation if anscp was NULL > ++ (not allowed to change caller's buffer) and the > ++ response buffer size is too small. This isn't a > ++ reliable way to detect truncation because the ioctl > ++ may be an inaccurate report of the UDP message size. > ++ Therefore we use this only to issue debug output. > ++ To do truncation accurately with UDP we need > ++ MSG_TRUNC which is only available on Linux. We > ++ can abstract out the Linux-specific feature in the > ++ future to detect truncation. */ > ++ if (__glibc_unlikely (*thisanssizp < *thisresplenp)) { > ++ Dprint(statp->options & RES_DEBUG, > ++ (stdout, ";; response may be truncated > (UDP)\n") > ++ ); > ++ } > ++ > + HEADER *anhp = (HEADER *) *thisansp; > + socklen_t fromlen = sizeof(struct sockaddr_in6); > + assert (sizeof(from) <= fromlen); > diff --git a/meta/recipes-core/eglibc/eglibc_2.19.bb > b/meta/recipes-core/eglibc/eglibc_2.19.bb > index a15573c4d19b..66ccedced2d8 100644 > --- a/meta/recipes-core/eglibc/eglibc_2.19.bb > +++ b/meta/recipes-core/eglibc/eglibc_2.19.bb > @@ -29,6 +29,7 @@ SRC_URI = " > http://downloads.yoctoproject.org/releases/eglibc/eglibc-${PV}-svnr25 > file://CVE-2014-5119.patch \ > file://CVE-2014-7817-wordexp-fails-to-honour-WRDE_NOCMD.patch \ > file://CVE-2012-3406-Stack-overflow-in-vfprintf-BZ-16617.patch > \ > + file://CVE-2015-7547.patch \ > " > SRC_URI[md5sum] = "197836c2ba42fb146e971222647198dd" > SRC_URI[sha256sum] = > "baaa030531fc308f7820c46acdf8e1b2f8e3c1f40bcd28b6e440d1c95d170d4c" > -- > _______________________________________________ > Openembedded-core mailing list > [email protected] > http://lists.openembedded.org/mailman/listinfo/openembedded-core >
-- _______________________________________________ Openembedded-core mailing list [email protected] http://lists.openembedded.org/mailman/listinfo/openembedded-core
