From: <abe...@us...> - 2016-02-17 18:49:10
|
Revision: 7537 http://sourceforge.net/p/astlinux/code/7537 Author: abelbeck Date: 2016-02-17 18:49:08 +0000 (Wed, 17 Feb 2016) Log Message: ----------- eglibc toolchain, security fixes: CVE-2015-7547, CVE-2015-1472, CVE-2014-9402, CVE-2015-1781, CVE-2014-8121 and a couple important bug fixes to allow the security patches to apply cleanly Note: At this time we are not able to demonstate Google's proof-of-concept for CVE-2015-7547 with previously un-patched eglibc Modified Paths: -------------- branches/1.0/astlinux-ast11.config branches/1.0/astlinux-ast13.config branches/1.0/astlinux18.config branches/1.0/crosstool-ng-src/README branches/1.0/crosstool-ng-src/ct-ng-1.20.0-3.2-x86_64.config branches/1.0/crosstool-ng-src/ct-ng-1.20.0-3.2.config branches/1.0/initrd.config branches/1.0/runnix-iso.config branches/1.0/runnix.config branches/1.0/x86_64-configs/astlinux-ast11.config branches/1.0/x86_64-configs/astlinux-ast13.config branches/1.0/x86_64-configs/astlinux18.config branches/1.0/x86_64-configs/initrd.config Added Paths: ----------- branches/1.0/crosstool-ng-src/patches/eglibc/2_18/100-CVE-2014-8121.patch branches/1.0/crosstool-ng-src/patches/eglibc/2_18/101-CVE-2014-9402.patch branches/1.0/crosstool-ng-src/patches/eglibc/2_18/102-CVE-2015-1472.patch branches/1.0/crosstool-ng-src/patches/eglibc/2_18/103-CVE-2015-1781.patch branches/1.0/crosstool-ng-src/patches/eglibc/2_18/110-submitted-resolv-first-query-failure.patch branches/1.0/crosstool-ng-src/patches/eglibc/2_18/120-gethostbyname4-memory-leak.patch branches/1.0/crosstool-ng-src/patches/eglibc/2_18/122-resolv-reuse-fd.patch branches/1.0/crosstool-ng-src/patches/eglibc/2_18/130-CVE-2015-7547-getaddrinfo.patch Modified: branches/1.0/astlinux-ast11.config =================================================================== --- branches/1.0/astlinux-ast11.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/astlinux-ast11.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -97,7 +97,7 @@ BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y -BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2/i586-unknown-linux-gnu" +BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2p1/i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y Modified: branches/1.0/astlinux-ast13.config =================================================================== --- branches/1.0/astlinux-ast13.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/astlinux-ast13.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -97,7 +97,7 @@ BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y -BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2/i586-unknown-linux-gnu" +BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2p1/i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y Modified: branches/1.0/astlinux18.config =================================================================== --- branches/1.0/astlinux18.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/astlinux18.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -97,7 +97,7 @@ BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y -BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2/i586-unknown-linux-gnu" +BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2p1/i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y Modified: branches/1.0/crosstool-ng-src/README =================================================================== --- branches/1.0/crosstool-ng-src/README 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/crosstool-ng-src/README 2016-02-17 18:49:08 UTC (rev 7537) @@ -3,7 +3,7 @@ ## http://crosstool-ng.org ## ## Building the eglibc toolchain for AstLinux 1.x using Buildroot -## The resulting toolchain is output to $HOME/astlinux/x-tools-1.20.0-3.2 +## The resulting toolchain is output to $HOME/astlinux/x-tools-1.20.0-3.2p1 ## Make sure you have a $HOME/astlinux/ directory. ## ## Note: If "crosstool-ng-1.20.0" is already installed, jump to "## Build i586 32-bit toolchain ##" Modified: branches/1.0/crosstool-ng-src/ct-ng-1.20.0-3.2-x86_64.config =================================================================== --- branches/1.0/crosstool-ng-src/ct-ng-1.20.0-3.2-x86_64.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/crosstool-ng-src/ct-ng-1.20.0-3.2-x86_64.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -25,7 +25,7 @@ # CT_LOCAL_TARBALLS_DIR="" CT_WORK_DIR="${CT_TOP_DIR}/.build" -CT_PREFIX_DIR="${HOME}/astlinux/x-tools-1.20.0-3.2/${CT_TARGET}" +CT_PREFIX_DIR="${HOME}/astlinux/x-tools-1.20.0-3.2p1/${CT_TARGET}" CT_INSTALL_DIR="${CT_PREFIX_DIR}" CT_RM_RF_PREFIX_DIR=y CT_REMOVE_DOCS=y Modified: branches/1.0/crosstool-ng-src/ct-ng-1.20.0-3.2.config =================================================================== --- branches/1.0/crosstool-ng-src/ct-ng-1.20.0-3.2.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/crosstool-ng-src/ct-ng-1.20.0-3.2.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -25,7 +25,7 @@ # CT_LOCAL_TARBALLS_DIR="" CT_WORK_DIR="${CT_TOP_DIR}/.build" -CT_PREFIX_DIR="${HOME}/astlinux/x-tools-1.20.0-3.2/${CT_TARGET}" +CT_PREFIX_DIR="${HOME}/astlinux/x-tools-1.20.0-3.2p1/${CT_TARGET}" CT_INSTALL_DIR="${CT_PREFIX_DIR}" CT_RM_RF_PREFIX_DIR=y CT_REMOVE_DOCS=y Added: branches/1.0/crosstool-ng-src/patches/eglibc/2_18/100-CVE-2014-8121.patch =================================================================== --- branches/1.0/crosstool-ng-src/patches/eglibc/2_18/100-CVE-2014-8121.patch (rev 0) +++ branches/1.0/crosstool-ng-src/patches/eglibc/2_18/100-CVE-2014-8121.patch 2016-02-17 18:49:08 UTC (rev 7537) @@ -0,0 +1,17 @@ +2015-04-29 Florian Weimer <fw...@re...> + + [BZ #18007] + * nss/nss_files/files-XXX.c (CONCAT): Always enable stayopen. + (CVE-2014-8121) + +--- a/nss/nss_files/files-XXX.c ++++ b/nss/nss_files/files-XXX.c +@@ -134,7 +134,7 @@ CONCAT(_nss_files_set,ENTNAME) (int stayopen) + + __libc_lock_lock (lock); + +- status = internal_setent (stayopen); ++ status = internal_setent (1); + + if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) + { Added: branches/1.0/crosstool-ng-src/patches/eglibc/2_18/101-CVE-2014-9402.patch =================================================================== --- branches/1.0/crosstool-ng-src/patches/eglibc/2_18/101-CVE-2014-9402.patch (rev 0) +++ branches/1.0/crosstool-ng-src/patches/eglibc/2_18/101-CVE-2014-9402.patch 2016-02-17 18:49:08 UTC (rev 7537) @@ -0,0 +1,19 @@ +2014-12-16 Florian Weimer <fw...@re...> + + [BZ #17630] + * resolv/nss_dns/dns-network.c (getanswer_r): Iterate over alias + names. + +--- a/resolv/nss_dns/dns-network.c ++++ b/resolv/nss_dns/dns-network.c +@@ -398,8 +398,8 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result, + + case BYNAME: + { +- char **ap = result->n_aliases++; +- while (*ap != NULL) ++ char **ap; ++ for (ap = result->n_aliases; *ap != NULL; ++ap) + { + /* Check each alias name for being of the forms: + 4.3.2.1.in-addr.arpa = net 1.2.3.4 Added: branches/1.0/crosstool-ng-src/patches/eglibc/2_18/102-CVE-2015-1472.patch =================================================================== --- branches/1.0/crosstool-ng-src/patches/eglibc/2_18/102-CVE-2015-1472.patch (rev 0) +++ branches/1.0/crosstool-ng-src/patches/eglibc/2_18/102-CVE-2015-1472.patch 2016-02-17 18:49:08 UTC (rev 7537) @@ -0,0 +1,82 @@ +2015-02-05 Paul Pluzhnikov <ppl...@go...> + + [BZ #16618] + * stdio-common/tst-sscanf.c (main): Test for buffer overflow. + * stdio-common/vfscanf.c (_IO_vfscanf_internal): Compute needed + size in bytes. Store needed elements in wpmax. Use needed size + in bytes for extend_alloca. + +--- a/stdio-common/tst-sscanf.c ++++ b/stdio-common/tst-sscanf.c +@@ -232,5 +232,38 @@ + } + } + ++ /* BZ #16618 ++ The test will segfault during SSCANF if the buffer overflow ++ is not fixed. The size of `s` is such that it forces the use ++ of malloc internally and this triggers the incorrect computation. ++ Thus the value for SIZE is arbitrariy high enough that malloc ++ is used. */ ++ { ++#define SIZE 131072 ++ CHAR *s = malloc ((SIZE + 1) * sizeof (*s)); ++ if (s == NULL) ++ abort (); ++ for (size_t i = 0; i < SIZE; i++) ++ s[i] = L('0'); ++ s[SIZE] = L('\0'); ++ int i = 42; ++ /* Scan multi-digit zero into `i`. */ ++ if (SSCANF (s, L("%d"), &i) != 1) ++ { ++ printf ("FAIL: bug16618: SSCANF did not read one input item.\n"); ++ result = 1; ++ } ++ if (i != 0) ++ { ++ printf ("FAIL: bug16618: Value of `i` was not zero as expected.\n"); ++ result = 1; ++ } ++ free (s); ++ if (result != 1) ++ printf ("PASS: bug16618: Did not crash.\n"); ++#undef SIZE ++ } ++ ++ + return result; + } +--- a/stdio-common/vfscanf.c ++++ b/stdio-common/vfscanf.c +@@ -272,9 +272,10 @@ + if (__builtin_expect (wpsize == wpmax, 0)) \ + { \ + CHAR_T *old = wp; \ +- size_t newsize = (UCHAR_MAX + 1 > 2 * wpmax \ +- ? UCHAR_MAX + 1 : 2 * wpmax); \ +- if (use_malloc || !__libc_use_alloca (newsize)) \ ++ bool fits = __builtin_expect (wpmax <= SIZE_MAX / sizeof (CHAR_T) / 2, 1); \ ++ size_t wpneed = MAX (UCHAR_MAX + 1, 2 * wpmax); \ ++ size_t newsize = fits ? wpneed * sizeof (CHAR_T) : SIZE_MAX; \ ++ if (!__libc_use_alloca (newsize)) \ + { \ + wp = realloc (use_malloc ? wp : NULL, newsize); \ + if (wp == NULL) \ +@@ -286,14 +287,13 @@ + } \ + if (! use_malloc) \ + MEMCPY (wp, old, wpsize); \ +- wpmax = newsize; \ ++ wpmax = wpneed; \ + use_malloc = true; \ + } \ + else \ + { \ + size_t s = wpmax * sizeof (CHAR_T); \ +- wp = (CHAR_T *) extend_alloca (wp, s, \ +- newsize * sizeof (CHAR_T)); \ ++ wp = (CHAR_T *) extend_alloca (wp, s, newsize); \ + wpmax = s / sizeof (CHAR_T); \ + if (old != NULL) \ + MEMCPY (wp, old, wpsize); \ Added: branches/1.0/crosstool-ng-src/patches/eglibc/2_18/103-CVE-2015-1781.patch =================================================================== --- branches/1.0/crosstool-ng-src/patches/eglibc/2_18/103-CVE-2015-1781.patch (rev 0) +++ branches/1.0/crosstool-ng-src/patches/eglibc/2_18/103-CVE-2015-1781.patch 2016-02-17 18:49:08 UTC (rev 7537) @@ -0,0 +1,18 @@ +2015-04-21 Arjun Shankar <arj...@lo...> + + [BZ #18287] + * resolv/nss_dns/dns-host.c (getanswer_r): Adjust buffer length + based on padding. (CVE-2015-1781) + +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -615,7 +615,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, + int have_to_map = 0; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); + buffer += pad; +- if (__builtin_expect (buflen < sizeof (struct host_data) + pad, 0)) ++ buflen = buflen > pad ? buflen - pad : 0; ++ if (__builtin_expect (buflen < sizeof (struct host_data), 0)) + { + /* The buffer is too small. */ + too_small: Added: branches/1.0/crosstool-ng-src/patches/eglibc/2_18/110-submitted-resolv-first-query-failure.patch =================================================================== --- branches/1.0/crosstool-ng-src/patches/eglibc/2_18/110-submitted-resolv-first-query-failure.patch (rev 0) +++ branches/1.0/crosstool-ng-src/patches/eglibc/2_18/110-submitted-resolv-first-query-failure.patch 2016-02-17 18:49:08 UTC (rev 7537) @@ -0,0 +1,40 @@ +eglibc-2.13/debian/patches/any/submitted-resolv-first-query-failure.diff +@@ -0,0 +1,38 @@ +2012-02-02 Aurelien Jarno <au...@de...> + + * resolv/res_query.c(__libc_res_nsearch): succeed if the first + query fails, but the second query succeeds. + +--- + resolv/res_query.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/resolv/res_query.c ++++ b/resolv/res_query.c +@@ -378,7 +378,7 @@ + ret = __libc_res_nquerydomain(statp, name, NULL, class, type, + answer, anslen, answerp, + answerp2, nanswerp2, resplen2); +- if (ret > 0 || trailing_dot) ++ if (ret > 0 || (ret == 0 && *resplen2 > 0) || trailing_dot) + return (ret); + saved_herrno = h_errno; + tried_as_is++; +@@ -418,7 +418,7 @@ + answer, anslen, answerp, + answerp2, nanswerp2, + resplen2); +- if (ret > 0) ++ if ((ret > 0) || (ret == 0 && *resplen2 > 0)) + return (ret); + + if (answerp && *answerp != answer) { +@@ -487,7 +487,7 @@ + ret = __libc_res_nquerydomain(statp, name, NULL, class, type, + answer, anslen, answerp, + answerp2, nanswerp2, resplen2); +- if (ret > 0) ++ if ((ret > 0) || (ret == 0 && *resplen2 > 0)) + return (ret); + } + Added: branches/1.0/crosstool-ng-src/patches/eglibc/2_18/120-gethostbyname4-memory-leak.patch =================================================================== --- branches/1.0/crosstool-ng-src/patches/eglibc/2_18/120-gethostbyname4-memory-leak.patch (rev 0) +++ branches/1.0/crosstool-ng-src/patches/eglibc/2_18/120-gethostbyname4-memory-leak.patch 2016-02-17 18:49:08 UTC (rev 7537) @@ -0,0 +1,449 @@ +eglibc-2.13/debian/patches/any/cvs-gethostbyname4-memory-leak.diff +@@ -0,0 +1,447 @@ +2014-02-18 Andreas Schwab <sc...@su...> + + [BZ #16574] + * resolv/res_send.c (send_vc): Add parameter ansp2_malloced. + Store non-zero if the second buffer was newly allocated. + (send_dg): Likewise. + (__libc_res_nsend): Add parameter ansp2_malloced and pass it down + to send_vc and send_dg. + (res_nsend): Pass NULL for ansp2_malloced. + * resolv/res_query.c (__libc_res_nquery): Add parameter + answerp2_malloced and pass it down to __libc_res_nsend. + (res_nquery): Pass additional NULL to __libc_res_nquery. + (__libc_res_nsearch): Add parameter answerp2_malloced and pass it + down to __libc_res_nquery and __libc_res_nquerydomain. Deallocate + second answer buffer if answerp2_malloced was set. + (res_nsearch): Pass additional NULL to __libc_res_nsearch. + (__libc_res_nquerydomain): Add parameter + answerp2_malloced and pass it down to __libc_res_nquery. + (res_nquerydomain): Pass additional NULL to + __libc_res_nquerydomain. + * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r): Pass + additional NULL to __libc_res_nsend and __libc_res_nquery. + * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname3_r): Pass + additional NULL to __libc_res_nsearch. + (_nss_dns_gethostbyname4_r): Revert last change. Use new + parameter of __libc_res_nsearch to check for separately allocated + second buffer. + (_nss_dns_gethostbyaddr2_r): Pass additional NULL to + __libc_res_nquery. + * resolv/nss_dns/dns-canon.c (_nss_dns_getcanonname_r): Pass + additional NULL to __libc_res_nquery. + * resolv/gethnamaddr.c (gethostbyname2): Pass additional NULL to + __libc_res_nsearch. + (gethostbyaddr): Pass additional NULL to __libc_res_nquery. + * include/resolv.h: Update prototypes of __libc_res_nquery, + __libc_res_nsearch, __libc_res_nsend. + +2014-02-13 Andreas Schwab <sc...@su...> + + [BZ #16574] + * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname4_r): Free the + second answer buffer if it was separately allocated. + +--- a/include/resolv.h ++++ b/include/resolv.h +@@ -58,11 +58,11 @@ + libc_hidden_proto (__res_state) + + int __libc_res_nquery (res_state, const char *, int, int, u_char *, int, +- u_char **, u_char **, int *, int *); ++ u_char **, u_char **, int *, int *, int *); + int __libc_res_nsearch (res_state, const char *, int, int, u_char *, int, +- u_char **, u_char **, int *, int *); ++ u_char **, u_char **, int *, int *, int *); + int __libc_res_nsend (res_state, const u_char *, int, const u_char *, int, +- u_char *, int, u_char **, u_char **, int *, int *) ++ u_char *, int, u_char **, u_char **, int *, int *, int *) + attribute_hidden; + + libresolv_hidden_proto (_sethtent) +--- a/resolv/gethnamaddr.c ++++ b/resolv/gethnamaddr.c +@@ -621,7 +621,7 @@ + buf.buf = origbuf = (querybuf *) alloca (1024); + + if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024, +- &buf.ptr, NULL, NULL, NULL)) < 0) { ++ &buf.ptr, NULL, NULL, NULL, NULL)) < 0) { + if (buf.buf != origbuf) + free (buf.buf); + Dprintf("res_nsearch failed (%d)\n", n); +@@ -716,12 +716,12 @@ + buf.buf = orig_buf = (querybuf *) alloca (1024); + + n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024, +- &buf.ptr, NULL, NULL, NULL); ++ &buf.ptr, NULL, NULL, NULL, NULL); + if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) { + strcpy(qp, "ip6.int"); + n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, + buf.buf != orig_buf ? MAXPACKET : 1024, +- &buf.ptr, NULL, NULL, NULL); ++ &buf.ptr, NULL, NULL, NULL, NULL); + } + if (n < 0) { + if (buf.buf != orig_buf) +--- a/resolv/nss_dns/dns-canon.c ++++ b/resolv/nss_dns/dns-canon.c +@@ -62,7 +62,7 @@ + { + int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i], + buf, sizeof (buf), &ansp.ptr, NULL, NULL, +- NULL); ++ NULL, NULL); + if (r > 0) + { + /* We need to decode the response. Just one question record. +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -195,7 +195,7 @@ + host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024); + + n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf, +- 1024, &host_buffer.ptr, NULL, NULL, NULL); ++ 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); + if (n < 0) + { + switch (errno) +@@ -225,7 +225,7 @@ + n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf, + host_buffer.buf != orig_host_buffer + ? MAXPACKET : 1024, &host_buffer.ptr, +- NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL); + + if (n < 0) + { +@@ -308,12 +308,13 @@ + u_char *ans2p = NULL; + int nans2p = 0; + int resplen2 = 0; ++ int ans2p_malloced = 0; + + int olderr = errno; + enum nss_status status; + int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC, + host_buffer.buf->buf, 2048, &host_buffer.ptr, +- &ans2p, &nans2p, &resplen2); ++ &ans2p, &nans2p, &resplen2, &ans2p_malloced); + if (n < 0) + { + switch (errno) +@@ -340,6 +341,10 @@ + resplen2, name, pat, buffer, buflen, + errnop, herrnop, ttlp); + ++ /* Check whether ans2p was separately allocated. */ ++ if (ans2p_malloced) ++ free (ans2p); ++ + if (host_buffer.buf != orig_host_buffer) + free (host_buffer.buf); + +@@ -448,7 +453,7 @@ + strcpy (qp, "].ip6.arpa"); + n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, + host_buffer.buf->buf, 1024, &host_buffer.ptr, +- NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL); + if (n >= 0) + goto got_it_already; + } +@@ -469,14 +474,14 @@ + } + + n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, +- 1024, &host_buffer.ptr, NULL, NULL, NULL); ++ 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); + if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) + { + strcpy (qp, "ip6.int"); + n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, + host_buffer.buf != orig_host_buffer + ? MAXPACKET : 1024, &host_buffer.ptr, +- NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL); + } + if (n < 0) + { +--- a/resolv/nss_dns/dns-network.c ++++ b/resolv/nss_dns/dns-network.c +@@ -130,7 +130,7 @@ + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); + + anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, +- 1024, &net_buffer.ptr, NULL, NULL, NULL); ++ 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + if (anslen < 0) + { + /* Nothing found. */ +@@ -206,7 +206,7 @@ + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); + + anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, +- 1024, &net_buffer.ptr, NULL, NULL, NULL); ++ 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + if (anslen < 0) + { + /* Nothing found. */ +--- a/resolv/res_query.c ++++ b/resolv/res_query.c +@@ -98,7 +98,7 @@ + __libc_res_nquerydomain(res_state statp, const char *name, const char *domain, + int class, int type, u_char *answer, int anslen, + u_char **answerp, u_char **answerp2, int *nanswerp2, +- int *resplen2); ++ int *resplen2, int *answerp2_malloced); + + /* + * Formulate a normal query, send, and await answer. +@@ -119,7 +119,8 @@ + u_char **answerp, /* if buffer needs to be enlarged */ + u_char **answerp2, + int *nanswerp2, +- int *resplen2) ++ int *resplen2, ++ int *answerp2_malloced) + { + HEADER *hp = (HEADER *) answer; + HEADER *hp2; +@@ -224,7 +225,8 @@ + } + assert (answerp == NULL || (void *) *answerp == (void *) answer); + n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer, +- anslen, answerp, answerp2, nanswerp2, resplen2); ++ anslen, answerp, answerp2, nanswerp2, resplen2, ++ answerp2_malloced); + if (use_malloc) + free (buf); + if (n < 0) { +@@ -316,7 +318,7 @@ + int anslen) /* size of answer buffer */ + { + return __libc_res_nquery(statp, name, class, type, answer, anslen, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL, NULL); + } + libresolv_hidden_def (res_nquery) + +@@ -335,7 +337,8 @@ + u_char **answerp, + u_char **answerp2, + int *nanswerp2, +- int *resplen2) ++ int *resplen2, ++ int *answerp2_malloced) + { + const char *cp, * const *domain; + HEADER *hp = (HEADER *) answer; +@@ -360,7 +363,7 @@ + if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) + return (__libc_res_nquery(statp, cp, class, type, answer, + anslen, answerp, answerp2, +- nanswerp2, resplen2)); ++ nanswerp2, resplen2, answerp2_malloced)); + + #ifdef DEBUG + if (statp->options & RES_DEBUG) +@@ -377,7 +380,8 @@ + if (dots >= statp->ndots || trailing_dot) { + ret = __libc_res_nquerydomain(statp, name, NULL, class, type, + answer, anslen, answerp, +- answerp2, nanswerp2, resplen2); ++ answerp2, nanswerp2, resplen2, ++ answerp2_malloced); + if (ret > 0 || (ret == 0 && *resplen2 > 0) || trailing_dot) + return (ret); + saved_herrno = h_errno; +@@ -386,11 +390,11 @@ + answer = *answerp; + anslen = MAXPACKET; + } +- if (answerp2 +- && (*answerp2 < answer || *answerp2 >= answer + anslen)) ++ if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *answerp2 = NULL; ++ *answerp2_malloced = 0; + } + } + +@@ -417,7 +421,7 @@ + class, type, + answer, anslen, answerp, + answerp2, nanswerp2, +- resplen2); ++ resplen2, answerp2_malloced); + if ((ret > 0) || (ret == 0 && *resplen2 > 0)) + return (ret); + +@@ -425,12 +429,11 @@ + answer = *answerp; + anslen = MAXPACKET; + } +- if (answerp2 +- && (*answerp2 < answer +- || *answerp2 >= answer + anslen)) ++ if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *answerp2 = NULL; ++ *answerp2_malloced = 0; + } + + /* +@@ -486,7 +489,8 @@ + && !(tried_as_is || root_on_list)) { + ret = __libc_res_nquerydomain(statp, name, NULL, class, type, + answer, anslen, answerp, +- answerp2, nanswerp2, resplen2); ++ answerp2, nanswerp2, resplen2, ++ answerp2_malloced); + if ((ret > 0) || (ret == 0 && *resplen2 > 0)) + return (ret); + } +@@ -498,10 +502,11 @@ + * else send back meaningless H_ERRNO, that being the one from + * the last DNSRCH we did. + */ +- if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen)) ++ if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *answerp2 = NULL; ++ *answerp2_malloced = 0; + } + if (saved_herrno != -1) + RES_SET_H_ERRNO(statp, saved_herrno); +@@ -521,7 +526,7 @@ + int anslen) /* size of answer */ + { + return __libc_res_nsearch(statp, name, class, type, answer, +- anslen, NULL, NULL, NULL, NULL); ++ anslen, NULL, NULL, NULL, NULL, NULL); + } + libresolv_hidden_def (res_nsearch) + +@@ -539,7 +544,8 @@ + u_char **answerp, + u_char **answerp2, + int *nanswerp2, +- int *resplen2) ++ int *resplen2, ++ int *answerp2_malloced) + { + char nbuf[MAXDNAME]; + const char *longname = nbuf; +@@ -577,7 +583,7 @@ + } + return (__libc_res_nquery(statp, longname, class, type, answer, + anslen, answerp, answerp2, nanswerp2, +- resplen2)); ++ resplen2, answerp2_malloced)); + } + + int +@@ -589,7 +595,8 @@ + int anslen) /* size of answer */ + { + return __libc_res_nquerydomain(statp, name, domain, class, type, +- answer, anslen, NULL, NULL, NULL, NULL); ++ answer, anslen, NULL, NULL, NULL, NULL, ++ NULL); + } + libresolv_hidden_def (res_nquerydomain) + +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -186,12 +186,12 @@ + static int send_vc(res_state, const u_char *, int, + const u_char *, int, + u_char **, int *, int *, int, u_char **, +- u_char **, int *, int *); ++ u_char **, int *, int *, int *); + static int send_dg(res_state, const u_char *, int, + const u_char *, int, + u_char **, int *, int *, int, + int *, int *, u_char **, +- u_char **, int *, int *); ++ u_char **, int *, int *, int *); + #ifdef DEBUG + static void Aerror(const res_state, FILE *, const char *, int, + const struct sockaddr *); +@@ -343,7 +343,7 @@ + __libc_res_nsend(res_state statp, const u_char *buf, int buflen, + const u_char *buf2, int buflen2, + u_char *ans, int anssiz, u_char **ansp, u_char **ansp2, +- int *nansp2, int *resplen2) ++ int *nansp2, int *resplen2, int *ansp2_malloced) + { + int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; + +@@ -546,7 +546,8 @@ + try = statp->retry; + n = send_vc(statp, buf, buflen, buf2, buflen2, + &ans, &anssiz, &terrno, +- ns, ansp, ansp2, nansp2, resplen2); ++ ns, ansp, ansp2, nansp2, resplen2, ++ ansp2_malloced); + if (n < 0) + return (-1); + if (n == 0 && (buf2 == NULL || *resplen2 == 0)) +@@ -556,7 +557,7 @@ + n = send_dg(statp, buf, buflen, buf2, buflen2, + &ans, &anssiz, &terrno, + ns, &v_circuit, &gotsomewhere, ansp, +- ansp2, nansp2, resplen2); ++ ansp2, nansp2, resplen2, ansp2_malloced); + if (n < 0) + return (-1); + if (n == 0 && (buf2 == NULL || *resplen2 == 0)) +@@ -646,7 +647,7 @@ + const u_char *buf, int buflen, u_char *ans, int anssiz) + { + return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz, +- NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL, NULL); + } + libresolv_hidden_def (res_nsend) + +@@ -657,7 +658,7 @@ + const u_char *buf, int buflen, const u_char *buf2, int buflen2, + u_char **ansp, int *anssizp, + int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2, +- int *resplen2) ++ int *resplen2, int *ansp2_malloced) + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +@@ -823,6 +824,8 @@ + } + *thisanssizp = MAXPACKET; + *thisansp = newp; ++ if (thisansp == ansp2) ++ *ansp2_malloced = 1; + anhp = (HEADER *) newp; + len = rlen; + } else { +@@ -1000,7 +1003,7 @@ + const u_char *buf, int buflen, const u_char *buf2, int buflen2, + u_char **ansp, int *anssizp, + int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp, +- u_char **ansp2, int *anssizp2, int *resplen2) ++ u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced) + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +@@ -1175,6 +1178,8 @@ + if (newp != NULL) { + *anssizp = MAXPACKET; + *thisansp = ans = newp; ++ if (thisansp == ansp2) ++ *ansp2_malloced = 1; + } + } + HEADER *anhp = (HEADER *) *thisansp; Added: branches/1.0/crosstool-ng-src/patches/eglibc/2_18/122-resolv-reuse-fd.patch =================================================================== --- branches/1.0/crosstool-ng-src/patches/eglibc/2_18/122-resolv-reuse-fd.patch (rev 0) +++ branches/1.0/crosstool-ng-src/patches/eglibc/2_18/122-resolv-reuse-fd.patch 2016-02-17 18:49:08 UTC (rev 7537) @@ -0,0 +1,16 @@ +2014-06-03 Andreas Schwab <sc...@su...> + + [BZ #15946] + * resolv/res_send.c (send_dg): Reload file descriptor after + calling reopen. + +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -1410,6 +1410,7 @@ send_dg(res_state statp, + retval = reopen (statp, terrno, ns); + if (retval <= 0) + return retval; ++ pfd[0].fd = EXT(statp).nssocks[ns]; + } + } + goto wait; Added: branches/1.0/crosstool-ng-src/patches/eglibc/2_18/130-CVE-2015-7547-getaddrinfo.patch =================================================================== --- branches/1.0/crosstool-ng-src/patches/eglibc/2_18/130-CVE-2015-7547-getaddrinfo.patch (rev 0) +++ branches/1.0/crosstool-ng-src/patches/eglibc/2_18/130-CVE-2015-7547-getaddrinfo.patch 2016-02-17 18:49:08 UTC (rev 7537) @@ -0,0 +1,540 @@ +eglibc-2.13/debian/patches/any/local-CVE-2015-7547.diff +@@ -0,0 +1,538 @@ +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -1036,7 +1036,10 @@ + 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) + { +@@ -1205,7 +1208,14 @@ + /* 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; + } + + +@@ -1219,11 +1229,101 @@ + + 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 implemetnation of send_dg ++ and send_vc to see response can arrive in any order, particlarly ++ 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 +@@ -1233,8 +1333,15 @@ + &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; +--- a/resolv/res_query.c ++++ b/resolv/res_query.c +@@ -394,6 +394,7 @@ + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + } +@@ -433,6 +434,7 @@ + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + +@@ -506,6 +508,7 @@ + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + if (saved_herrno != -1) +--- 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 @@ + #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); +@@ -653,6 +672,77 @@ + + /* 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 feild 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, +@@ -662,11 +752,7 @@ + { + 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]; +@@ -742,6 +828,8 @@ + * 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: +@@ -778,33 +866,14 @@ + 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; +@@ -812,10 +881,14 @@ + 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 non-NULL and it's not ++ pointing at 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; +@@ -827,6 +900,9 @@ + if (thisansp == ansp2) + *ansp2_malloced = 1; + 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, +@@ -998,6 +1074,66 @@ + 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 feild 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, +@@ -1007,8 +1143,6 @@ + { + 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; +@@ -1040,6 +1174,8 @@ + 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; +@@ -1136,52 +1272,53 @@ + 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 non-NULL and it's not ++ pointing at the static user-supplied buffer then ++ we can reallocate it. */ ++ && (thisansp != NULL && thisansp != ansp) ++ /* Is the size too small? */ + && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0 + || *thisanssizp < *thisresplenp)) { ++ /* 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; + if (thisansp == ansp2) + *ansp2_malloced = 1; + } + } ++ /* 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); Modified: branches/1.0/initrd.config =================================================================== --- branches/1.0/initrd.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/initrd.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -97,7 +97,7 @@ BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y -BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2/i586-unknown-linux-gnu" +BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2p1/i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y Modified: branches/1.0/runnix-iso.config =================================================================== --- branches/1.0/runnix-iso.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/runnix-iso.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -97,7 +97,7 @@ BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y -BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2/i586-unknown-linux-gnu" +BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2p1/i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y Modified: branches/1.0/runnix.config =================================================================== --- branches/1.0/runnix.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/runnix.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -97,7 +97,7 @@ BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y -BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2/i586-unknown-linux-gnu" +BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2p1/i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_PREFIX="i586-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y Modified: branches/1.0/x86_64-configs/astlinux-ast11.config =================================================================== --- branches/1.0/x86_64-configs/astlinux-ast11.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/x86_64-configs/astlinux-ast11.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -78,7 +78,7 @@ BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y -BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2/x86_64-unknown-linux-gnu" +BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2p1/x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_PREFIX="x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y Modified: branches/1.0/x86_64-configs/astlinux-ast13.config =================================================================== --- branches/1.0/x86_64-configs/astlinux-ast13.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/x86_64-configs/astlinux-ast13.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -78,7 +78,7 @@ BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y -BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2/x86_64-unknown-linux-gnu" +BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2p1/x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_PREFIX="x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y Modified: branches/1.0/x86_64-configs/astlinux18.config =================================================================== --- branches/1.0/x86_64-configs/astlinux18.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/x86_64-configs/astlinux18.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -78,7 +78,7 @@ BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y -BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2/x86_64-unknown-linux-gnu" +BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2p1/x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_PREFIX="x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y Modified: branches/1.0/x86_64-configs/initrd.config =================================================================== --- branches/1.0/x86_64-configs/initrd.config 2016-02-16 22:55:38 UTC (rev 7536) +++ branches/1.0/x86_64-configs/initrd.config 2016-02-17 18:49:08 UTC (rev 7537) @@ -78,7 +78,7 @@ BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y -BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2/x86_64-unknown-linux-gnu" +BR2_TOOLCHAIN_EXTERNAL_PATH="$(HOME)/astlinux/x-tools-1.20.0-3.2p1/x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_PREFIX="x86_64-unknown-linux-gnu" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |