This is the mail archive of the
glibc-cvs@sourceware.org
mailing list for the glibc project.
GNU C Library master sources branch master updated. glibc-2.24-585-gfc82b0a
- From: fw at sourceware dot org
- To: glibc-cvs at sourceware dot org
- Date: 31 Dec 2016 19:50:40 -0000
- Subject: GNU C Library master sources branch master updated. glibc-2.24-585-gfc82b0a
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".
The branch, master has been updated
via fc82b0a2dfe7dbd35671c10510a8da1043d746a5 (commit)
from 3c589b1a8a4401e258ba23a03fcbcc79b82393ab (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=fc82b0a2dfe7dbd35671c10510a8da1043d746a5
commit fc82b0a2dfe7dbd35671c10510a8da1043d746a5
Author: Florian Weimer <fweimer@redhat.com>
Date: Sat Dec 31 20:22:09 2016 +0100
CVE-2015-5180: resolv: Fix crash with internal QTYPE [BZ #18784]
Also rename T_UNSPEC because an upcoming public header file
update will use that name.
diff --git a/ChangeLog b/ChangeLog
index 01ee23b..3beacb0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
2016-12-31 Florian Weimer <fweimer@redhat.com>
+ [BZ #18784]
+ CVE-2015-5180
+ * include/arpa/nameser_compat.h (T_QUERY_A_AND_AAAA): Rename from
+ T_UNSPEC. Adjust value.
+ * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname4_r): Use it.
+ * resolv/res_query.c (__libc_res_nquery): Likewise.
+ * resolv/res_mkquery.c (res_nmkquery): Check for out-of-range
+ QTYPEs.
+ * resolv/tst-resolv-qtypes.c: New file.
+ * resolv/Makefile (xtests): Add tst-resolv-qtypes.
+ (tst-resolv-qtypes): Link against libresolv and libpthread.
+
+2016-12-31 Florian Weimer <fweimer@redhat.com>
+
* elf/dl-tunables.h (__tunables_init): Fix unused attribute.
2016-12-31 Siddhesh Poyarekar <siddhesh@sourceware.org>
diff --git a/NEWS b/NEWS
index 7ebce44..08b566d 100644
--- a/NEWS
+++ b/NEWS
@@ -191,12 +191,18 @@ Version 2.25
Security related changes:
- On ARM EABI (32-bit), generating a backtrace for execution contexts which
+* On ARM EABI (32-bit), generating a backtrace for execution contexts which
have been created with makecontext could fail to terminate due to a
missing .cantunwind annotation. This has been observed to lead to a hang
(denial of service) in some Go applications compiled with gccgo. Reported
by Andreas Schwab. (CVE-2016-6323)
+* The DNS stub resolver functions would crash due to a NULL pointer
+ dereference when processing a query with a valid DNS question type which
+ was used internally in the implementation. The stub resolver now uses a
+ question type which is outside the range of valid question type values.
+ (CVE-2015-5180)
+
The following bugs are resolved with this release:
[The release manager will add the list generated by
diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h
index 6928000..f7d0e04 100644
--- a/include/arpa/nameser_compat.h
+++ b/include/arpa/nameser_compat.h
@@ -3,9 +3,9 @@
# ifndef _ISOMAC
-/* Picksome unused number to represent lookups of IPv4 and IPv6 (i.e.,
- T_A and T_AAAA). */
-#define T_UNSPEC 62321
+/* The number is outside the 16-bit RR type range and is used
+ internally by the implementation. */
+#define T_QUERY_A_AND_AAAA 439963904
# endif /* !_ISOMAC */
#endif
diff --git a/resolv/Makefile b/resolv/Makefile
index 1e9f562..1089995 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -49,6 +49,8 @@ tests += \
tst-resolv-network \
tst-resolv-search \
+# This test sends millions of packets and is rather slow.
+xtests += tst-resolv-qtypes
endif
extra-libs-others = $(extra-libs)
libresolv-routines := res_comp res_debug \
@@ -123,6 +125,7 @@ $(objpfx)tst-bug18665: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-res_use_inet6: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
# This test case uses the deprecated RES_USE_INET6 resolver option.
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 901e037..d597faa 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -324,7 +324,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
int olderr = errno;
enum nss_status status;
- int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
+ int n = __libc_res_nsearch (&_res, name, C_IN, T_QUERY_A_AND_AAAA,
host_buffer.buf->buf, 2048, &host_buffer.ptr,
&ans2p, &nans2p, &resplen2, &ans2p_malloced);
if (n >= 0)
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
index 12f9730..d80b531 100644
--- a/resolv/res_mkquery.c
+++ b/resolv/res_mkquery.c
@@ -103,6 +103,10 @@ res_nmkquery(res_state statp,
int n;
u_char *dnptrs[20], **dpp, **lastdnptr;
+ if (class < 0 || class > 65535
+ || type < 0 || type > 65535)
+ return -1;
+
#ifdef DEBUG
if (statp->options & RES_DEBUG)
printf(";; res_nmkquery(%s, %s, %s, %s)\n",
diff --git a/resolv/res_query.c b/resolv/res_query.c
index 944d1a9..07dc6f6 100644
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -122,7 +122,7 @@ __libc_res_nquery(res_state statp,
int n, use_malloc = 0;
u_int oflags = statp->_flags;
- size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE;
+ size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE;
u_char *buf = alloca (bufsize);
u_char *query1 = buf;
int nquery1 = -1;
@@ -137,7 +137,7 @@ __libc_res_nquery(res_state statp,
printf(";; res_query(%s, %d, %d)\n", name, class, type);
#endif
- if (type == T_UNSPEC)
+ if (type == T_QUERY_A_AND_AAAA)
{
n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL,
query1, bufsize);
@@ -190,7 +190,7 @@ __libc_res_nquery(res_state statp,
if (__builtin_expect (n <= 0, 0) && !use_malloc) {
/* Retry just in case res_nmkquery failed because of too
short buffer. Shouldn't happen. */
- bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET;
+ bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET;
buf = malloc (bufsize);
if (buf != NULL) {
query1 = buf;
diff --git a/resolv/tst-resolv-qtypes.c b/resolv/tst-resolv-qtypes.c
new file mode 100644
index 0000000..b3e60c6
--- /dev/null
+++ b/resolv/tst-resolv-qtypes.c
@@ -0,0 +1,185 @@
+/* Exercise low-level query functions with different QTYPEs.
+ 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/>. */
+
+#include <resolv.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+#include <support/xmemstream.h>
+
+/* If ture, the response function will send the actual response packet
+ over TCP instead of UDP. */
+static volatile bool force_tcp;
+
+/* Send back a fake resource record matching the QTYPE. */
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ if (force_tcp && ctx->tcp)
+ {
+ resolv_response_init (b, (struct resolv_response_flags) { .tc = 1 });
+ resolv_response_add_question (b, qname, qclass, qtype);
+ return;
+ }
+
+ resolv_response_init (b, (struct resolv_response_flags) { });
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
+ resolv_response_add_data (b, &qtype, sizeof (qtype));
+ resolv_response_close_record (b);
+}
+
+static const const char *domain = "www.example.com";
+
+static int
+wrap_res_query (int type, unsigned char *answer, int answer_length)
+{
+ return res_query (domain, C_IN, type, answer, answer_length);
+}
+
+static int
+wrap_res_search (int type, unsigned char *answer, int answer_length)
+{
+ return res_query (domain, C_IN, type, answer, answer_length);
+}
+
+static int
+wrap_res_querydomain (int type, unsigned char *answer, int answer_length)
+{
+ return res_querydomain ("www", "example.com", C_IN, type,
+ answer, answer_length);
+}
+
+static int
+wrap_res_send (int type, unsigned char *answer, int answer_length)
+{
+ unsigned char buf[512];
+ int ret = res_mkquery (QUERY, domain, C_IN, type,
+ (const unsigned char *) "", 0, NULL,
+ buf, sizeof (buf));
+ if (type < 0 || type >= 65536)
+ {
+ /* res_mkquery fails for out-of-range record types. */
+ TEST_VERIFY_EXIT (ret == -1);
+ return -1;
+ }
+ TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */
+ return res_send (buf, ret, answer, answer_length);
+}
+
+static int
+wrap_res_nquery (int type, unsigned char *answer, int answer_length)
+{
+ return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
+}
+
+static int
+wrap_res_nsearch (int type, unsigned char *answer, int answer_length)
+{
+ return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
+}
+
+static int
+wrap_res_nquerydomain (int type, unsigned char *answer, int answer_length)
+{
+ return res_nquerydomain (&_res, "www", "example.com", C_IN, type,
+ answer, answer_length);
+}
+
+static int
+wrap_res_nsend (int type, unsigned char *answer, int answer_length)
+{
+ unsigned char buf[512];
+ int ret = res_nmkquery (&_res, QUERY, domain, C_IN, type,
+ (const unsigned char *) "", 0, NULL,
+ buf, sizeof (buf));
+ if (type < 0 || type >= 65536)
+ {
+ /* res_mkquery fails for out-of-range record types. */
+ TEST_VERIFY_EXIT (ret == -1);
+ return -1;
+ }
+ TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */
+ return res_nsend (&_res, buf, ret, answer, answer_length);
+}
+
+static void
+test_function (const char *fname,
+ int (*func) (int type,
+ unsigned char *answer, int answer_length))
+{
+ unsigned char buf[512];
+ for (int tcp = 0; tcp < 2; ++tcp)
+ {
+ force_tcp = tcp;
+ for (unsigned int type = 1; type <= 65535; ++type)
+ {
+ if (test_verbose)
+ printf ("info: sending QTYPE %d with %s (tcp=%d)\n",
+ type, fname, tcp);
+ int ret = func (type, buf, sizeof (buf));
+ if (ret != 47)
+ FAIL_EXIT1 ("%s tcp=%d qtype=%d return value %d",
+ fname,tcp, type, ret);
+ /* One question, one answer record. */
+ TEST_VERIFY (memcmp (buf + 4, "\0\1\0\1\0\0\0\0", 8) == 0);
+ /* Question section. */
+ static const char qname[] = "\3www\7example\3com";
+ size_t qname_length = sizeof (qname);
+ TEST_VERIFY (memcmp (buf + 12, qname, qname_length) == 0);
+ /* RDATA part of answer. */
+ uint16_t type16 = type;
+ TEST_VERIFY (memcmp (buf + ret - 2, &type16, sizeof (type16)) == 0);
+ }
+ }
+
+ TEST_VERIFY (func (-1, buf, sizeof (buf) == -1));
+ TEST_VERIFY (func (65536, buf, sizeof (buf) == -1));
+}
+
+static int
+do_test (void)
+{
+ struct resolv_redirect_config config =
+ {
+ .response_callback = response,
+ };
+ struct resolv_test *obj = resolv_test_start (config);
+
+ test_function ("res_query", &wrap_res_query);
+ test_function ("res_search", &wrap_res_search);
+ test_function ("res_querydomain", &wrap_res_querydomain);
+ test_function ("res_send", &wrap_res_send);
+
+ test_function ("res_nquery", &wrap_res_nquery);
+ test_function ("res_nsearch", &wrap_res_nsearch);
+ test_function ("res_nquerydomain", &wrap_res_nquerydomain);
+ test_function ("res_nsend", &wrap_res_nsend);
+
+ resolv_test_end (obj);
+ return 0;
+}
+
+#define TIMEOUT 300
+#include <support/test-driver.c>
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 14 +++
NEWS | 8 ++-
include/arpa/nameser_compat.h | 6 +-
resolv/Makefile | 3 +
resolv/nss_dns/dns-host.c | 2 +-
resolv/res_mkquery.c | 4 +
resolv/res_query.c | 6 +-
resolv/tst-resolv-qtypes.c | 185 +++++++++++++++++++++++++++++++++++++++++
8 files changed, 220 insertions(+), 8 deletions(-)
create mode 100644 resolv/tst-resolv-qtypes.c
hooks/post-receive
--
GNU C Library master sources