All of lore.kernel.org
 help / color / mirror / Atom feed
* [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180
@ 2017-11-15 20:36 George McCollister
  2017-11-15 20:36 ` [morty][PATCH v2 2/2] glibc: Fix CVE-2017-1000366 George McCollister
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: George McCollister @ 2017-11-15 20:36 UTC (permalink / raw)
  To: openembedded-core

Add backported patch to fix CVE-2015-5180 from the upstream
release/2.24/master branch.

Signed-off-by: George McCollister <george.mccollister@gmail.com>
---

Changes in v2:
 - Fix commit message

 ...80-resolv-Fix-crash-with-internal-QTYPE-B.patch | 357 +++++++++++++++++++++
 meta/recipes-core/glibc/glibc_2.24.bb              |   1 +
 2 files changed, 358 insertions(+)
 create mode 100644 meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch

diff --git a/meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch b/meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch
new file mode 100644
index 0000000000..ba0bebe488
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch
@@ -0,0 +1,357 @@
+From ff9b7c4fb73295cd2de2d2ccfbbf4f6d50883d47 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Sat, 31 Dec 2016 20:22:09 +0100
+Subject: [PATCH] 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.
+
+(cherry picked from commit fc82b0a2dfe7dbd35671c10510a8da1043d746a5)
+
+Upstream-Status: Backport
+https://sourceware.org/git/?p=glibc.git;a=patch;h=b3b37f1a5559a7620e31c8053ed1b44f798f2b6d
+
+CVE: CVE-2015-5180
+
+Signed-off-by: George McCollister <george.mccollister@gmail.com>
+---
+ ChangeLog                     |  14 ++++
+ NEWS                          |   6 ++
+ include/arpa/nameser_compat.h |   6 +-
+ resolv/Makefile               |   5 ++
+ 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, 221 insertions(+), 7 deletions(-)
+ create mode 100644 resolv/tst-resolv-qtypes.c
+
+diff --git a/ChangeLog b/ChangeLog
+index 893262de11..2bdaf69e43 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,17 @@
++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-10-26  Carlos O'Donell  <carlos@redhat.com>
+ 
+ 	* include/atomic.h
+diff --git a/NEWS b/NEWS
+index 3002773c16..4b1ca3cb65 100644
+--- a/NEWS
++++ b/NEWS
+@@ -11,6 +11,12 @@ using `glibc' in the "product" field.
+   printers show various pthread variables in human-readable form when read
+   using the 'print' or 'display' commands in gdb.
+ 
++* 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)
++
+ Version 2.24
+ 
+ * The minimum Linux kernel version that this version of the GNU C Library
+diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h
+index 2e735ede4c..7c0deed9ae 100644
+--- a/include/arpa/nameser_compat.h
++++ b/include/arpa/nameser_compat.h
+@@ -1,8 +1,8 @@
+ #ifndef _ARPA_NAMESER_COMPAT_
+ #include <resolv/arpa/nameser_compat.h>
+ 
+-/* 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
+diff --git a/resolv/Makefile b/resolv/Makefile
+index 8be41d3ae1..a4c86b9762 100644
+--- a/resolv/Makefile
++++ b/resolv/Makefile
+@@ -40,6 +40,9 @@ ifeq ($(have-thread-library),yes)
+ extra-libs += libanl
+ routines += gai_sigqueue
+ tests += tst-res_hconf_reorder
++
++# This test sends millions of packets and is rather slow.
++xtests += tst-resolv-qtypes
+ endif
+ extra-libs-others = $(extra-libs)
+ libresolv-routines := gethnamaddr res_comp res_debug	\
+@@ -117,3 +120,5 @@ tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
+ $(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
+ 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \
+ 	$(evaluate-test)
++
++$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
+diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
+index 5f9e35701b..d16fa4b8ed 100644
+--- a/resolv/nss_dns/dns-host.c
++++ b/resolv/nss_dns/dns-host.c
+@@ -323,7 +323,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 12f9730199..d80b5318e5 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 944d1a90f5..07dc6f6583 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 0000000000..b3e60c693b
+--- /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>
+-- 
+2.15.0
+
diff --git a/meta/recipes-core/glibc/glibc_2.24.bb b/meta/recipes-core/glibc/glibc_2.24.bb
index e723e03dcf..4c7d901149 100644
--- a/meta/recipes-core/glibc/glibc_2.24.bb
+++ b/meta/recipes-core/glibc/glibc_2.24.bb
@@ -45,6 +45,7 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
            file://0004-New-condvar-implementation-that-provides-stronger-or.patch \
            file://0005-Remove-__ASSUME_REQUEUE_PI.patch \
            file://0006-Fix-atomic_fetch_xor_release.patch \
+           file://0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch \
 "
 
 SRC_URI += "\
-- 
2.15.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [morty][PATCH v2 2/2] glibc: Fix CVE-2017-1000366
  2017-11-15 20:36 [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180 George McCollister
@ 2017-11-15 20:36 ` George McCollister
  2017-11-16  3:12   ` Khem Raj
  2017-11-16  3:11 ` [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180 Khem Raj
  2017-11-16 18:45 ` akuster808
  2 siblings, 1 reply; 7+ messages in thread
From: George McCollister @ 2017-11-15 20:36 UTC (permalink / raw)
  To: openembedded-core

Add backported patches from the upstream release/2.24/master branch to
fix CVE-2017-1000366

Signed-off-by: George McCollister <george.mccollister@gmail.com>
---

Changes in v2:
 - Fix commit message

 ...00366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch |  71 +++++++
 ...ject-overly-long-LD_PRELOAD-path-elements.patch | 145 +++++++++++++
 ...Reject-overly-long-LD_AUDIT-path-elements.patch | 231 +++++++++++++++++++++
 meta/recipes-core/glibc/glibc_2.24.bb              |   3 +
 4 files changed, 450 insertions(+)
 create mode 100644 meta/recipes-core/glibc/glibc/0001-CVE-2017-1000366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch
 create mode 100644 meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch
 create mode 100644 meta/recipes-core/glibc/glibc/0003-ld.so-Reject-overly-long-LD_AUDIT-path-elements.patch

diff --git a/meta/recipes-core/glibc/glibc/0001-CVE-2017-1000366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch b/meta/recipes-core/glibc/glibc/0001-CVE-2017-1000366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch
new file mode 100644
index 0000000000..78e9ea9e65
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0001-CVE-2017-1000366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch
@@ -0,0 +1,71 @@
+From 400f170750a4b2c94a2670ca44de166cc5dd6e3b Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 19 Jun 2017 18:33:26 +0200
+Subject: [PATCH] CVE-2017-1000366: Ignore LD_LIBRARY_PATH for AT_SECURE=1
+ programs [BZ #21624]
+
+LD_LIBRARY_PATH can only be used to reorder system search paths, which
+is not useful functionality.
+
+This makes an exploitable unbounded alloca in _dl_init_paths unreachable
+for AT_SECURE=1 programs.
+
+(cherry picked from commit f6110a8fee2ca36f8e2d2abecf3cba9fa7b8ea7d)
+
+Upstream-Status: Backport
+https://sourceware.org/git/?p=glibc.git;a=commit;h=87bd4186da10371f46e2f1a7bf7c0a45bb04f1ac
+https://anonscm.debian.org/cgit/pkg-glibc/glibc.git/commit/?h=stretch&id=2755c57269f24e9d59c22c49788f92515346c1bb
+
+CVE: CVE-2017-1000366
+
+Signed-off-by: George McCollister <george.mccollister@gmail.com>
+---
+ ChangeLog  | 7 +++++++
+ NEWS       | 1 +
+ elf/rtld.c | 3 ++-
+ 3 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index 2bdaf69e43..7a999802dd 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2017-06-19  Florian Weimer  <fweimer@redhat.com>
++
++	[BZ #21624]
++	CVE-2017-1000366
++	* elf/rtld.c (process_envvars): Ignore LD_LIBRARY_PATH for
++	__libc_enable_secure.
++
+ 2016-12-31  Florian Weimer  <fweimer@redhat.com>
+ 
+ 	[BZ #18784]
+diff --git a/NEWS b/NEWS
+index 4b1ca3cb65..66b49dbbc0 100644
+--- a/NEWS
++++ b/NEWS
+@@ -17,6 +17,7 @@ using `glibc' in the "product" field.
+   question type which is outside the range of valid question type values.
+   (CVE-2015-5180)
+ 
++  [21624] Unsafe alloca allows local attackers to alias stack and heap (CVE-2017-1000366)
+ Version 2.24
+ 
+ * The minimum Linux kernel version that this version of the GNU C Library
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 647661ca45..215a9aec8f 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -2437,7 +2437,8 @@ process_envvars (enum mode *modep)
+ 
+ 	case 12:
+ 	  /* The library search path.  */
+-	  if (memcmp (envline, "LIBRARY_PATH", 12) == 0)
++	  if (!__libc_enable_secure
++	      && memcmp (envline, "LIBRARY_PATH", 12) == 0)
+ 	    {
+ 	      library_path = &envline[13];
+ 	      break;
+-- 
+2.15.0
+
diff --git a/meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch b/meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch
new file mode 100644
index 0000000000..7f81ed1566
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch
@@ -0,0 +1,145 @@
+From 6d49272e6d6741496e3456f2cc22ebc2b9f7f989 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 19 Jun 2017 22:31:04 +0200
+Subject: [PATCH] ld.so: Reject overly long LD_PRELOAD path elements
+
+(cherry picked from commit 6d0ba622891bed9d8394eef1935add53003b12e8)
+
+Upstream-Status: Backport
+https://sourceware.org/git/?p=glibc.git;a=commit;h=aab04ca5d359150e17631e6a9b44b65e93bdc467
+https://anonscm.debian.org/cgit/pkg-glibc/glibc.git/commit/?h=stretch&id=2755c57269f24e9d59c22c49788f92515346c1bb
+
+CVE: CVE-2017-1000366
+
+Signed-off-by: George McCollister <george.mccollister@gmail.com>
+---
+ ChangeLog  |  7 ++++++
+ elf/rtld.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
+ 2 files changed, 73 insertions(+), 16 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index 7a999802dd..ea5ecd4a1e 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2017-06-19  Florian Weimer  <fweimer@redhat.com>
++
++	* elf/rtld.c (SECURE_NAME_LIMIT, SECURE_PATH_LIMIT): Define.
++	(dso_name_valid_for_suid): New function.
++	(handle_ld_preload): Likewise.
++	(dl_main): Call it.  Remove alloca.
++
+ 2017-06-19  Florian Weimer  <fweimer@redhat.com>
+ 
+ 	[BZ #21624]
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 215a9aec8f..1d8eab9fe2 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -99,6 +99,35 @@ uintptr_t __pointer_chk_guard_local
+ strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
+ #endif
+ 
++/* Length limits for names and paths, to protect the dynamic linker,
++   particularly when __libc_enable_secure is active.  */
++#ifdef NAME_MAX
++# define SECURE_NAME_LIMIT NAME_MAX
++#else
++# define SECURE_NAME_LIMIT 255
++#endif
++#ifdef PATH_MAX
++# define SECURE_PATH_LIMIT PATH_MAX
++#else
++# define SECURE_PATH_LIMIT 1024
++#endif
++
++/* Check that AT_SECURE=0, or that the passed name does not contain
++   directories and is not overly long.  Reject empty names
++   unconditionally.  */
++static bool
++dso_name_valid_for_suid (const char *p)
++{
++  if (__glibc_unlikely (__libc_enable_secure))
++    {
++      /* Ignore pathnames with directories for AT_SECURE=1
++	 programs, and also skip overlong names.  */
++      size_t len = strlen (p);
++      if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL)
++	return false;
++    }
++  return *p != '\0';
++}
+ 
+ /* List of auditing DSOs.  */
+ static struct audit_list
+@@ -730,6 +759,42 @@ static const char *preloadlist attribute_relro;
+ /* Nonzero if information about versions has to be printed.  */
+ static int version_info attribute_relro;
+ 
++/* The LD_PRELOAD environment variable gives list of libraries
++   separated by white space or colons that are loaded before the
++   executable's dependencies and prepended to the global scope list.
++   (If the binary is running setuid all elements containing a '/' are
++   ignored since it is insecure.)  Return the number of preloads
++   performed.  */
++unsigned int
++handle_ld_preload (const char *preloadlist, struct link_map *main_map)
++{
++  unsigned int npreloads = 0;
++  const char *p = preloadlist;
++  char fname[SECURE_PATH_LIMIT];
++
++  while (*p != '\0')
++    {
++      /* Split preload list at space/colon.  */
++      size_t len = strcspn (p, " :");
++      if (len > 0 && len < sizeof (fname))
++	{
++	  memcpy (fname, p, len);
++	  fname[len] = '\0';
++	}
++      else
++	fname[0] = '\0';
++
++      /* Skip over the substring and the following delimiter.  */
++      p += len;
++      if (*p != '\0')
++	++p;
++
++      if (dso_name_valid_for_suid (fname))
++	npreloads += do_preload (fname, main_map, "LD_PRELOAD");
++    }
++  return npreloads;
++}
++
+ static void
+ dl_main (const ElfW(Phdr) *phdr,
+ 	 ElfW(Word) phnum,
+@@ -1481,23 +1546,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+ 
+   if (__glibc_unlikely (preloadlist != NULL))
+     {
+-      /* The LD_PRELOAD environment variable gives list of libraries
+-	 separated by white space or colons that are loaded before the
+-	 executable's dependencies and prepended to the global scope
+-	 list.  If the binary is running setuid all elements
+-	 containing a '/' are ignored since it is insecure.  */
+-      char *list = strdupa (preloadlist);
+-      char *p;
+-
+       HP_TIMING_NOW (start);
+-
+-      /* Prevent optimizing strsep.  Speed is not important here.  */
+-      while ((p = (strsep) (&list, " :")) != NULL)
+-	if (p[0] != '\0'
+-	    && (__builtin_expect (! __libc_enable_secure, 1)
+-		|| strchr (p, '/') == NULL))
+-	  npreloads += do_preload (p, main_map, "LD_PRELOAD");
+-
++      npreloads += handle_ld_preload (preloadlist, main_map);
+       HP_TIMING_NOW (stop);
+       HP_TIMING_DIFF (diff, start, stop);
+       HP_TIMING_ACCUM_NT (load_time, diff);
+-- 
+2.15.0
+
diff --git a/meta/recipes-core/glibc/glibc/0003-ld.so-Reject-overly-long-LD_AUDIT-path-elements.patch b/meta/recipes-core/glibc/glibc/0003-ld.so-Reject-overly-long-LD_AUDIT-path-elements.patch
new file mode 100644
index 0000000000..b52b8a1fa7
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0003-ld.so-Reject-overly-long-LD_AUDIT-path-elements.patch
@@ -0,0 +1,231 @@
+From c0b25407def32718147530da72959a034cd1318d Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 19 Jun 2017 22:32:12 +0200
+Subject: [PATCH] ld.so: Reject overly long LD_AUDIT path elements
+
+Also only process the last LD_AUDIT entry.
+
+(cherry picked from commit 81b82fb966ffbd94353f793ad17116c6088dedd9)
+
+Upstream-Status: Backport
+https://sourceware.org/git/?p=glibc.git;a=commit;h=2febff860b31df3666bef5ade0d0744c93f76a74
+https://anonscm.debian.org/cgit/pkg-glibc/glibc.git/commit/?h=stretch&id=2755c57269f24e9d59c22c49788f92515346c1bb
+
+CVE: CVE-2017-1000366
+
+Signed-off-by: George McCollister <george.mccollister@gmail.com>
+---
+ ChangeLog  |  11 +++++++
+ elf/rtld.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
+ 2 files changed, 106 insertions(+), 15 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index ea5ecd4a1e..638cb632b1 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,14 @@
++2017-06-19  Florian Weimer  <fweimer@redhat.com>
++
++	* elf/rtld.c (audit_list_string): New variable.
++	(audit_list): Update comment.
++	(struct audit_list_iter): Define.
++	(audit_list_iter_init, audit_list_iter_next): New function.
++	(dl_main): Use struct audit_list_iter to process audit modules.
++	(process_dl_audit): Call dso_name_valid_for_suid.
++	(process_envvars): Set audit_list_string instead of calling
++	process_dl_audit.
++
+ 2017-06-19  Florian Weimer  <fweimer@redhat.com>
+ 
+ 	* elf/rtld.c (SECURE_NAME_LIMIT, SECURE_PATH_LIMIT): Define.
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 1d8eab9fe2..302bb63620 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -129,13 +129,91 @@ dso_name_valid_for_suid (const char *p)
+   return *p != '\0';
+ }
+ 
+-/* List of auditing DSOs.  */
++/* LD_AUDIT variable contents.  Must be processed before the
++   audit_list below.  */
++const char *audit_list_string;
++
++/* Cyclic list of auditing DSOs.  audit_list->next is the first
++   element.  */
+ static struct audit_list
+ {
+   const char *name;
+   struct audit_list *next;
+ } *audit_list;
+ 
++/* Iterator for audit_list_string followed by audit_list.  */
++struct audit_list_iter
++{
++  /* Tail of audit_list_string still needing processing, or NULL.  */
++  const char *audit_list_tail;
++
++  /* The list element returned in the previous iteration.  NULL before
++     the first element.  */
++  struct audit_list *previous;
++
++  /* Scratch buffer for returning a name which is part of
++     audit_list_string.  */
++  char fname[SECURE_NAME_LIMIT];
++};
++
++/* Initialize an audit list iterator.  */
++static void
++audit_list_iter_init (struct audit_list_iter *iter)
++{
++  iter->audit_list_tail = audit_list_string;
++  iter->previous = NULL;
++}
++
++/* Iterate through both audit_list_string and audit_list.  */
++static const char *
++audit_list_iter_next (struct audit_list_iter *iter)
++{
++  if (iter->audit_list_tail != NULL)
++    {
++      /* First iterate over audit_list_string.  */
++      while (*iter->audit_list_tail != '\0')
++	{
++	  /* Split audit list at colon.  */
++	  size_t len = strcspn (iter->audit_list_tail, ":");
++	  if (len > 0 && len < sizeof (iter->fname))
++	    {
++	      memcpy (iter->fname, iter->audit_list_tail, len);
++	      iter->fname[len] = '\0';
++	    }
++	  else
++	    /* Do not return this name to the caller.  */
++	    iter->fname[0] = '\0';
++
++	  /* Skip over the substring and the following delimiter.  */
++	  iter->audit_list_tail += len;
++	  if (*iter->audit_list_tail == ':')
++	    ++iter->audit_list_tail;
++
++	  /* If the name is valid, return it.  */
++	  if (dso_name_valid_for_suid (iter->fname))
++	    return iter->fname;
++	  /* Otherwise, wrap around and try the next name.  */
++	}
++      /* Fall through to the procesing of audit_list.  */
++    }
++
++  if (iter->previous == NULL)
++    {
++      if (audit_list == NULL)
++	/* No pre-parsed audit list.  */
++	return NULL;
++      /* Start of audit list.  The first list element is at
++	 audit_list->next (cyclic list).  */
++      iter->previous = audit_list->next;
++      return iter->previous->name;
++    }
++  if (iter->previous == audit_list)
++    /* Cyclic list wrap-around.  */
++    return NULL;
++  iter->previous = iter->previous->next;
++  return iter->previous->name;
++}
++
+ #ifndef HAVE_INLINED_SYSCALLS
+ /* Set nonzero during loading and initialization of executable and
+    libraries, cleared before the executable's entry point runs.  This
+@@ -1322,11 +1400,13 @@ of this helper program; chances are you did not intend to run this program.\n\
+     GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
+ 
+   /* If we have auditing DSOs to load, do it now.  */
+-  if (__glibc_unlikely (audit_list != NULL))
++  bool need_security_init = true;
++  if (__glibc_unlikely (audit_list != NULL)
++      || __glibc_unlikely (audit_list_string != NULL))
+     {
+-      /* Iterate over all entries in the list.  The order is important.  */
+       struct audit_ifaces *last_audit = NULL;
+-      struct audit_list *al = audit_list->next;
++      struct audit_list_iter al_iter;
++      audit_list_iter_init (&al_iter);
+ 
+       /* Since we start using the auditing DSOs right away we need to
+ 	 initialize the data structures now.  */
+@@ -1337,9 +1417,14 @@ of this helper program; chances are you did not intend to run this program.\n\
+ 	 use different values (especially the pointer guard) and will
+ 	 fail later on.  */
+       security_init ();
++      need_security_init = false;
+ 
+-      do
++      while (true)
+ 	{
++	  const char *name = audit_list_iter_next (&al_iter);
++	  if (name == NULL)
++	    break;
++
+ 	  int tls_idx = GL(dl_tls_max_dtv_idx);
+ 
+ 	  /* Now it is time to determine the layout of the static TLS
+@@ -1348,7 +1433,7 @@ of this helper program; chances are you did not intend to run this program.\n\
+ 	     no DF_STATIC_TLS bit is set.  The reason is that we know
+ 	     glibc will use the static model.  */
+ 	  struct dlmopen_args dlmargs;
+-	  dlmargs.fname = al->name;
++	  dlmargs.fname = name;
+ 	  dlmargs.map = NULL;
+ 
+ 	  const char *objname;
+@@ -1361,7 +1446,7 @@ of this helper program; chances are you did not intend to run this program.\n\
+ 	    not_loaded:
+ 	      _dl_error_printf ("\
+ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+-				al->name, err_str);
++				name, err_str);
+ 	      if (malloced)
+ 		free ((char *) err_str);
+ 	    }
+@@ -1465,10 +1550,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+ 		  goto not_loaded;
+ 		}
+ 	    }
+-
+-	  al = al->next;
+ 	}
+-      while (al != audit_list->next);
+ 
+       /* If we have any auditing modules, announce that we already
+ 	 have two objects loaded.  */
+@@ -1732,7 +1814,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+   if (tcbp == NULL)
+     tcbp = init_tls ();
+ 
+-  if (__glibc_likely (audit_list == NULL))
++  if (__glibc_likely (need_security_init))
+     /* Initialize security features.  But only if we have not done it
+        earlier.  */
+     security_init ();
+@@ -2363,9 +2445,7 @@ process_dl_audit (char *str)
+   char *p;
+ 
+   while ((p = (strsep) (&str, ":")) != NULL)
+-    if (p[0] != '\0'
+-	&& (__builtin_expect (! __libc_enable_secure, 1)
+-	    || strchr (p, '/') == NULL))
++    if (dso_name_valid_for_suid (p))
+       {
+ 	/* This is using the local malloc, not the system malloc.  The
+ 	   memory can never be freed.  */
+@@ -2429,7 +2509,7 @@ process_envvars (enum mode *modep)
+ 	      break;
+ 	    }
+ 	  if (memcmp (envline, "AUDIT", 5) == 0)
+-	    process_dl_audit (&envline[6]);
++	    audit_list_string = &envline[6];
+ 	  break;
+ 
+ 	case 7:
+-- 
+2.15.0
+
diff --git a/meta/recipes-core/glibc/glibc_2.24.bb b/meta/recipes-core/glibc/glibc_2.24.bb
index 4c7d901149..4eba6aceb6 100644
--- a/meta/recipes-core/glibc/glibc_2.24.bb
+++ b/meta/recipes-core/glibc/glibc_2.24.bb
@@ -46,6 +46,9 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
            file://0005-Remove-__ASSUME_REQUEUE_PI.patch \
            file://0006-Fix-atomic_fetch_xor_release.patch \
            file://0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch \
+           file://0001-CVE-2017-1000366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch \
+           file://0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch \
+           file://0003-ld.so-Reject-overly-long-LD_AUDIT-path-elements.patch \
 "
 
 SRC_URI += "\
-- 
2.15.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180
  2017-11-15 20:36 [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180 George McCollister
  2017-11-15 20:36 ` [morty][PATCH v2 2/2] glibc: Fix CVE-2017-1000366 George McCollister
@ 2017-11-16  3:11 ` Khem Raj
  2017-11-16 18:45 ` akuster808
  2 siblings, 0 replies; 7+ messages in thread
From: Khem Raj @ 2017-11-16  3:11 UTC (permalink / raw)
  To: Armin Kuster, George McCollister; +Cc: openembedded-core

[-- Attachment #1: Type: text/plain, Size: 16028 bytes --]

On Wed, Nov 15, 2017 at 12:36 PM George McCollister <
george.mccollister@gmail.com> wrote:

> Add backported patch to fix CVE-2015-5180 from the upstream
> release/2.24/master branch.
>

This is ok

>
> Signed-off-by: George McCollister <george.mccollister@gmail.com>
> ---
>
> Changes in v2:
>  - Fix commit message
>
>  ...80-resolv-Fix-crash-with-internal-QTYPE-B.patch | 357
> +++++++++++++++++++++
>  meta/recipes-core/glibc/glibc_2.24.bb              |   1 +
>  2 files changed, 358 insertions(+)
>  create mode 100644
> meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch
>
> diff --git
> a/meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch
> b/meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch
> new file mode 100644
> index 0000000000..ba0bebe488
> --- /dev/null
> +++
> b/meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch
> @@ -0,0 +1,357 @@
> +From ff9b7c4fb73295cd2de2d2ccfbbf4f6d50883d47 Mon Sep 17 00:00:00 2001
> +From: Florian Weimer <fweimer@redhat.com>
> +Date: Sat, 31 Dec 2016 20:22:09 +0100
> +Subject: [PATCH] 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.
> +
> +(cherry picked from commit fc82b0a2dfe7dbd35671c10510a8da1043d746a5)
> +
> +Upstream-Status: Backport
> +
> https://sourceware.org/git/?p=glibc.git;a=patch;h=b3b37f1a5559a7620e31c8053ed1b44f798f2b6d
> +
> +CVE: CVE-2015-5180
> +
> +Signed-off-by: George McCollister <george.mccollister@gmail.com>
> +---
> + ChangeLog                     |  14 ++++
> + NEWS                          |   6 ++
> + include/arpa/nameser_compat.h |   6 +-
> + resolv/Makefile               |   5 ++
> + 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, 221 insertions(+), 7 deletions(-)
> + create mode 100644 resolv/tst-resolv-qtypes.c
> +
> +diff --git a/ChangeLog b/ChangeLog
> +index 893262de11..2bdaf69e43 100644
> +--- a/ChangeLog
> ++++ b/ChangeLog
> +@@ -1,3 +1,17 @@
> ++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-10-26  Carlos O'Donell  <carlos@redhat.com>
> +
> +       * include/atomic.h
> +diff --git a/NEWS b/NEWS
> +index 3002773c16..4b1ca3cb65 100644
> +--- a/NEWS
> ++++ b/NEWS
> +@@ -11,6 +11,12 @@ using `glibc' in the "product" field.
> +   printers show various pthread variables in human-readable form when
> read
> +   using the 'print' or 'display' commands in gdb.
> +
> ++* 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)
> ++
> + Version 2.24
> +
> + * The minimum Linux kernel version that this version of the GNU C Library
> +diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h
> +index 2e735ede4c..7c0deed9ae 100644
> +--- a/include/arpa/nameser_compat.h
> ++++ b/include/arpa/nameser_compat.h
> +@@ -1,8 +1,8 @@
> + #ifndef _ARPA_NAMESER_COMPAT_
> + #include <resolv/arpa/nameser_compat.h>
> +
> +-/* 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
> +diff --git a/resolv/Makefile b/resolv/Makefile
> +index 8be41d3ae1..a4c86b9762 100644
> +--- a/resolv/Makefile
> ++++ b/resolv/Makefile
> +@@ -40,6 +40,9 @@ ifeq ($(have-thread-library),yes)
> + extra-libs += libanl
> + routines += gai_sigqueue
> + tests += tst-res_hconf_reorder
> ++
> ++# This test sends millions of packets and is rather slow.
> ++xtests += tst-resolv-qtypes
> + endif
> + extra-libs-others = $(extra-libs)
> + libresolv-routines := gethnamaddr res_comp res_debug  \
> +@@ -117,3 +120,5 @@ tst-leaks2-ENV =
> MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
> + $(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
> +       $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \
> +       $(evaluate-test)
> ++
> ++$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so
> $(shared-thread-library)
> +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
> +index 5f9e35701b..d16fa4b8ed 100644
> +--- a/resolv/nss_dns/dns-host.c
> ++++ b/resolv/nss_dns/dns-host.c
> +@@ -323,7 +323,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 12f9730199..d80b5318e5 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 944d1a90f5..07dc6f6583 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 0000000000..b3e60c693b
> +--- /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>
> +--
> +2.15.0
> +
> diff --git a/meta/recipes-core/glibc/glibc_2.24.bb
> b/meta/recipes-core/glibc/glibc_2.24.bb
> index e723e03dcf..4c7d901149 100644
> --- a/meta/recipes-core/glibc/glibc_2.24.bb
> +++ b/meta/recipes-core/glibc/glibc_2.24.bb
> @@ -45,6 +45,7 @@ SRC_URI =
> "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
>
> file://0004-New-condvar-implementation-that-provides-stronger-or.patch \
>             file://0005-Remove-__ASSUME_REQUEUE_PI.patch \
>             file://0006-Fix-atomic_fetch_xor_release.patch \
> +
>  file://0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch \
>  "
>
>  SRC_URI += "\
> --
> 2.15.0
>
> --
> _______________________________________________
> Openembedded-core mailing list
> Openembedded-core@lists.openembedded.org
> http://lists.openembedded.org/mailman/listinfo/openembedded-core
>

[-- Attachment #2: Type: text/html, Size: 19664 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [morty][PATCH v2 2/2] glibc: Fix CVE-2017-1000366
  2017-11-15 20:36 ` [morty][PATCH v2 2/2] glibc: Fix CVE-2017-1000366 George McCollister
@ 2017-11-16  3:12   ` Khem Raj
  0 siblings, 0 replies; 7+ messages in thread
From: Khem Raj @ 2017-11-16  3:12 UTC (permalink / raw)
  To: Armin Kuster, George McCollister; +Cc: openembedded-core

[-- Attachment #1: Type: text/plain, Size: 20071 bytes --]

On Wed, Nov 15, 2017 at 12:36 PM George McCollister <
george.mccollister@gmail.com> wrote:

> Add backported patches from the upstream release/2.24/master branch to
> fix CVE-2017-1000366
>

This seems fine for morty

>
> Signed-off-by: George McCollister <george.mccollister@gmail.com>
> ---
>
> Changes in v2:
>  - Fix commit message
>
>  ...00366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch |  71 +++++++
>  ...ject-overly-long-LD_PRELOAD-path-elements.patch | 145 +++++++++++++
>  ...Reject-overly-long-LD_AUDIT-path-elements.patch | 231
> +++++++++++++++++++++
>  meta/recipes-core/glibc/glibc_2.24.bb              |   3 +
>  4 files changed, 450 insertions(+)
>  create mode 100644
> meta/recipes-core/glibc/glibc/0001-CVE-2017-1000366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch
>  create mode 100644
> meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch
>  create mode 100644
> meta/recipes-core/glibc/glibc/0003-ld.so-Reject-overly-long-LD_AUDIT-path-elements.patch
>
> diff --git
> a/meta/recipes-core/glibc/glibc/0001-CVE-2017-1000366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch
> b/meta/recipes-core/glibc/glibc/0001-CVE-2017-1000366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch
> new file mode 100644
> index 0000000000..78e9ea9e65
> --- /dev/null
> +++
> b/meta/recipes-core/glibc/glibc/0001-CVE-2017-1000366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch
> @@ -0,0 +1,71 @@
> +From 400f170750a4b2c94a2670ca44de166cc5dd6e3b Mon Sep 17 00:00:00 2001
> +From: Florian Weimer <fweimer@redhat.com>
> +Date: Mon, 19 Jun 2017 18:33:26 +0200
> +Subject: [PATCH] CVE-2017-1000366: Ignore LD_LIBRARY_PATH for AT_SECURE=1
> + programs [BZ #21624]
> +
> +LD_LIBRARY_PATH can only be used to reorder system search paths, which
> +is not useful functionality.
> +
> +This makes an exploitable unbounded alloca in _dl_init_paths unreachable
> +for AT_SECURE=1 programs.
> +
> +(cherry picked from commit f6110a8fee2ca36f8e2d2abecf3cba9fa7b8ea7d)
> +
> +Upstream-Status: Backport
> +
> https://sourceware.org/git/?p=glibc.git;a=commit;h=87bd4186da10371f46e2f1a7bf7c0a45bb04f1ac
> +
> https://anonscm.debian.org/cgit/pkg-glibc/glibc.git/commit/?h=stretch&id=2755c57269f24e9d59c22c49788f92515346c1bb
> +
> +CVE: CVE-2017-1000366
> +
> +Signed-off-by: George McCollister <george.mccollister@gmail.com>
> +---
> + ChangeLog  | 7 +++++++
> + NEWS       | 1 +
> + elf/rtld.c | 3 ++-
> + 3 files changed, 10 insertions(+), 1 deletion(-)
> +
> +diff --git a/ChangeLog b/ChangeLog
> +index 2bdaf69e43..7a999802dd 100644
> +--- a/ChangeLog
> ++++ b/ChangeLog
> +@@ -1,3 +1,10 @@
> ++2017-06-19  Florian Weimer  <fweimer@redhat.com>
> ++
> ++      [BZ #21624]
> ++      CVE-2017-1000366
> ++      * elf/rtld.c (process_envvars): Ignore LD_LIBRARY_PATH for
> ++      __libc_enable_secure.
> ++
> + 2016-12-31  Florian Weimer  <fweimer@redhat.com>
> +
> +       [BZ #18784]
> +diff --git a/NEWS b/NEWS
> +index 4b1ca3cb65..66b49dbbc0 100644
> +--- a/NEWS
> ++++ b/NEWS
> +@@ -17,6 +17,7 @@ using `glibc' in the "product" field.
> +   question type which is outside the range of valid question type values.
> +   (CVE-2015-5180)
> +
> ++  [21624] Unsafe alloca allows local attackers to alias stack and heap
> (CVE-2017-1000366)
> + Version 2.24
> +
> + * The minimum Linux kernel version that this version of the GNU C Library
> +diff --git a/elf/rtld.c b/elf/rtld.c
> +index 647661ca45..215a9aec8f 100644
> +--- a/elf/rtld.c
> ++++ b/elf/rtld.c
> +@@ -2437,7 +2437,8 @@ process_envvars (enum mode *modep)
> +
> +       case 12:
> +         /* The library search path.  */
> +-        if (memcmp (envline, "LIBRARY_PATH", 12) == 0)
> ++        if (!__libc_enable_secure
> ++            && memcmp (envline, "LIBRARY_PATH", 12) == 0)
> +           {
> +             library_path = &envline[13];
> +             break;
> +--
> +2.15.0
> +
> diff --git
> a/meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch
> b/meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch
> new file mode 100644
> index 0000000000..7f81ed1566
> --- /dev/null
> +++
> b/meta/recipes-core/glibc/glibc/0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch
> @@ -0,0 +1,145 @@
> +From 6d49272e6d6741496e3456f2cc22ebc2b9f7f989 Mon Sep 17 00:00:00 2001
> +From: Florian Weimer <fweimer@redhat.com>
> +Date: Mon, 19 Jun 2017 22:31:04 +0200
> +Subject: [PATCH] ld.so: Reject overly long LD_PRELOAD path elements
> +
> +(cherry picked from commit 6d0ba622891bed9d8394eef1935add53003b12e8)
> +
> +Upstream-Status: Backport
> +
> https://sourceware.org/git/?p=glibc.git;a=commit;h=aab04ca5d359150e17631e6a9b44b65e93bdc467
> +
> https://anonscm.debian.org/cgit/pkg-glibc/glibc.git/commit/?h=stretch&id=2755c57269f24e9d59c22c49788f92515346c1bb
> +
> +CVE: CVE-2017-1000366
> +
> +Signed-off-by: George McCollister <george.mccollister@gmail.com>
> +---
> + ChangeLog  |  7 ++++++
> + elf/rtld.c | 82
> ++++++++++++++++++++++++++++++++++++++++++++++++++------------
> + 2 files changed, 73 insertions(+), 16 deletions(-)
> +
> +diff --git a/ChangeLog b/ChangeLog
> +index 7a999802dd..ea5ecd4a1e 100644
> +--- a/ChangeLog
> ++++ b/ChangeLog
> +@@ -1,3 +1,10 @@
> ++2017-06-19  Florian Weimer  <fweimer@redhat.com>
> ++
> ++      * elf/rtld.c (SECURE_NAME_LIMIT, SECURE_PATH_LIMIT): Define.
> ++      (dso_name_valid_for_suid): New function.
> ++      (handle_ld_preload): Likewise.
> ++      (dl_main): Call it.  Remove alloca.
> ++
> + 2017-06-19  Florian Weimer  <fweimer@redhat.com>
> +
> +       [BZ #21624]
> +diff --git a/elf/rtld.c b/elf/rtld.c
> +index 215a9aec8f..1d8eab9fe2 100644
> +--- a/elf/rtld.c
> ++++ b/elf/rtld.c
> +@@ -99,6 +99,35 @@ uintptr_t __pointer_chk_guard_local
> + strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
> + #endif
> +
> ++/* Length limits for names and paths, to protect the dynamic linker,
> ++   particularly when __libc_enable_secure is active.  */
> ++#ifdef NAME_MAX
> ++# define SECURE_NAME_LIMIT NAME_MAX
> ++#else
> ++# define SECURE_NAME_LIMIT 255
> ++#endif
> ++#ifdef PATH_MAX
> ++# define SECURE_PATH_LIMIT PATH_MAX
> ++#else
> ++# define SECURE_PATH_LIMIT 1024
> ++#endif
> ++
> ++/* Check that AT_SECURE=0, or that the passed name does not contain
> ++   directories and is not overly long.  Reject empty names
> ++   unconditionally.  */
> ++static bool
> ++dso_name_valid_for_suid (const char *p)
> ++{
> ++  if (__glibc_unlikely (__libc_enable_secure))
> ++    {
> ++      /* Ignore pathnames with directories for AT_SECURE=1
> ++       programs, and also skip overlong names.  */
> ++      size_t len = strlen (p);
> ++      if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL)
> ++      return false;
> ++    }
> ++  return *p != '\0';
> ++}
> +
> + /* List of auditing DSOs.  */
> + static struct audit_list
> +@@ -730,6 +759,42 @@ static const char *preloadlist attribute_relro;
> + /* Nonzero if information about versions has to be printed.  */
> + static int version_info attribute_relro;
> +
> ++/* The LD_PRELOAD environment variable gives list of libraries
> ++   separated by white space or colons that are loaded before the
> ++   executable's dependencies and prepended to the global scope list.
> ++   (If the binary is running setuid all elements containing a '/' are
> ++   ignored since it is insecure.)  Return the number of preloads
> ++   performed.  */
> ++unsigned int
> ++handle_ld_preload (const char *preloadlist, struct link_map *main_map)
> ++{
> ++  unsigned int npreloads = 0;
> ++  const char *p = preloadlist;
> ++  char fname[SECURE_PATH_LIMIT];
> ++
> ++  while (*p != '\0')
> ++    {
> ++      /* Split preload list at space/colon.  */
> ++      size_t len = strcspn (p, " :");
> ++      if (len > 0 && len < sizeof (fname))
> ++      {
> ++        memcpy (fname, p, len);
> ++        fname[len] = '\0';
> ++      }
> ++      else
> ++      fname[0] = '\0';
> ++
> ++      /* Skip over the substring and the following delimiter.  */
> ++      p += len;
> ++      if (*p != '\0')
> ++      ++p;
> ++
> ++      if (dso_name_valid_for_suid (fname))
> ++      npreloads += do_preload (fname, main_map, "LD_PRELOAD");
> ++    }
> ++  return npreloads;
> ++}
> ++
> + static void
> + dl_main (const ElfW(Phdr) *phdr,
> +        ElfW(Word) phnum,
> +@@ -1481,23 +1546,8 @@ ERROR: ld.so: object '%s' cannot be loaded as
> audit interface: %s; ignored.\n",
> +
> +   if (__glibc_unlikely (preloadlist != NULL))
> +     {
> +-      /* The LD_PRELOAD environment variable gives list of libraries
> +-       separated by white space or colons that are loaded before the
> +-       executable's dependencies and prepended to the global scope
> +-       list.  If the binary is running setuid all elements
> +-       containing a '/' are ignored since it is insecure.  */
> +-      char *list = strdupa (preloadlist);
> +-      char *p;
> +-
> +       HP_TIMING_NOW (start);
> +-
> +-      /* Prevent optimizing strsep.  Speed is not important here.  */
> +-      while ((p = (strsep) (&list, " :")) != NULL)
> +-      if (p[0] != '\0'
> +-          && (__builtin_expect (! __libc_enable_secure, 1)
> +-              || strchr (p, '/') == NULL))
> +-        npreloads += do_preload (p, main_map, "LD_PRELOAD");
> +-
> ++      npreloads += handle_ld_preload (preloadlist, main_map);
> +       HP_TIMING_NOW (stop);
> +       HP_TIMING_DIFF (diff, start, stop);
> +       HP_TIMING_ACCUM_NT (load_time, diff);
> +--
> +2.15.0
> +
> diff --git
> a/meta/recipes-core/glibc/glibc/0003-ld.so-Reject-overly-long-LD_AUDIT-path-elements.patch
> b/meta/recipes-core/glibc/glibc/0003-ld.so-Reject-overly-long-LD_AUDIT-path-elements.patch
> new file mode 100644
> index 0000000000..b52b8a1fa7
> --- /dev/null
> +++
> b/meta/recipes-core/glibc/glibc/0003-ld.so-Reject-overly-long-LD_AUDIT-path-elements.patch
> @@ -0,0 +1,231 @@
> +From c0b25407def32718147530da72959a034cd1318d Mon Sep 17 00:00:00 2001
> +From: Florian Weimer <fweimer@redhat.com>
> +Date: Mon, 19 Jun 2017 22:32:12 +0200
> +Subject: [PATCH] ld.so: Reject overly long LD_AUDIT path elements
> +
> +Also only process the last LD_AUDIT entry.
> +
> +(cherry picked from commit 81b82fb966ffbd94353f793ad17116c6088dedd9)
> +
> +Upstream-Status: Backport
> +
> https://sourceware.org/git/?p=glibc.git;a=commit;h=2febff860b31df3666bef5ade0d0744c93f76a74
> +
> https://anonscm.debian.org/cgit/pkg-glibc/glibc.git/commit/?h=stretch&id=2755c57269f24e9d59c22c49788f92515346c1bb
> +
> +CVE: CVE-2017-1000366
> +
> +Signed-off-by: George McCollister <george.mccollister@gmail.com>
> +---
> + ChangeLog  |  11 +++++++
> + elf/rtld.c | 110
> ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
> + 2 files changed, 106 insertions(+), 15 deletions(-)
> +
> +diff --git a/ChangeLog b/ChangeLog
> +index ea5ecd4a1e..638cb632b1 100644
> +--- a/ChangeLog
> ++++ b/ChangeLog
> +@@ -1,3 +1,14 @@
> ++2017-06-19  Florian Weimer  <fweimer@redhat.com>
> ++
> ++      * elf/rtld.c (audit_list_string): New variable.
> ++      (audit_list): Update comment.
> ++      (struct audit_list_iter): Define.
> ++      (audit_list_iter_init, audit_list_iter_next): New function.
> ++      (dl_main): Use struct audit_list_iter to process audit modules.
> ++      (process_dl_audit): Call dso_name_valid_for_suid.
> ++      (process_envvars): Set audit_list_string instead of calling
> ++      process_dl_audit.
> ++
> + 2017-06-19  Florian Weimer  <fweimer@redhat.com>
> +
> +       * elf/rtld.c (SECURE_NAME_LIMIT, SECURE_PATH_LIMIT): Define.
> +diff --git a/elf/rtld.c b/elf/rtld.c
> +index 1d8eab9fe2..302bb63620 100644
> +--- a/elf/rtld.c
> ++++ b/elf/rtld.c
> +@@ -129,13 +129,91 @@ dso_name_valid_for_suid (const char *p)
> +   return *p != '\0';
> + }
> +
> +-/* List of auditing DSOs.  */
> ++/* LD_AUDIT variable contents.  Must be processed before the
> ++   audit_list below.  */
> ++const char *audit_list_string;
> ++
> ++/* Cyclic list of auditing DSOs.  audit_list->next is the first
> ++   element.  */
> + static struct audit_list
> + {
> +   const char *name;
> +   struct audit_list *next;
> + } *audit_list;
> +
> ++/* Iterator for audit_list_string followed by audit_list.  */
> ++struct audit_list_iter
> ++{
> ++  /* Tail of audit_list_string still needing processing, or NULL.  */
> ++  const char *audit_list_tail;
> ++
> ++  /* The list element returned in the previous iteration.  NULL before
> ++     the first element.  */
> ++  struct audit_list *previous;
> ++
> ++  /* Scratch buffer for returning a name which is part of
> ++     audit_list_string.  */
> ++  char fname[SECURE_NAME_LIMIT];
> ++};
> ++
> ++/* Initialize an audit list iterator.  */
> ++static void
> ++audit_list_iter_init (struct audit_list_iter *iter)
> ++{
> ++  iter->audit_list_tail = audit_list_string;
> ++  iter->previous = NULL;
> ++}
> ++
> ++/* Iterate through both audit_list_string and audit_list.  */
> ++static const char *
> ++audit_list_iter_next (struct audit_list_iter *iter)
> ++{
> ++  if (iter->audit_list_tail != NULL)
> ++    {
> ++      /* First iterate over audit_list_string.  */
> ++      while (*iter->audit_list_tail != '\0')
> ++      {
> ++        /* Split audit list at colon.  */
> ++        size_t len = strcspn (iter->audit_list_tail, ":");
> ++        if (len > 0 && len < sizeof (iter->fname))
> ++          {
> ++            memcpy (iter->fname, iter->audit_list_tail, len);
> ++            iter->fname[len] = '\0';
> ++          }
> ++        else
> ++          /* Do not return this name to the caller.  */
> ++          iter->fname[0] = '\0';
> ++
> ++        /* Skip over the substring and the following delimiter.  */
> ++        iter->audit_list_tail += len;
> ++        if (*iter->audit_list_tail == ':')
> ++          ++iter->audit_list_tail;
> ++
> ++        /* If the name is valid, return it.  */
> ++        if (dso_name_valid_for_suid (iter->fname))
> ++          return iter->fname;
> ++        /* Otherwise, wrap around and try the next name.  */
> ++      }
> ++      /* Fall through to the procesing of audit_list.  */
> ++    }
> ++
> ++  if (iter->previous == NULL)
> ++    {
> ++      if (audit_list == NULL)
> ++      /* No pre-parsed audit list.  */
> ++      return NULL;
> ++      /* Start of audit list.  The first list element is at
> ++       audit_list->next (cyclic list).  */
> ++      iter->previous = audit_list->next;
> ++      return iter->previous->name;
> ++    }
> ++  if (iter->previous == audit_list)
> ++    /* Cyclic list wrap-around.  */
> ++    return NULL;
> ++  iter->previous = iter->previous->next;
> ++  return iter->previous->name;
> ++}
> ++
> + #ifndef HAVE_INLINED_SYSCALLS
> + /* Set nonzero during loading and initialization of executable and
> +    libraries, cleared before the executable's entry point runs.  This
> +@@ -1322,11 +1400,13 @@ of this helper program; chances are you did not
> intend to run this program.\n\
> +     GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
> +
> +   /* If we have auditing DSOs to load, do it now.  */
> +-  if (__glibc_unlikely (audit_list != NULL))
> ++  bool need_security_init = true;
> ++  if (__glibc_unlikely (audit_list != NULL)
> ++      || __glibc_unlikely (audit_list_string != NULL))
> +     {
> +-      /* Iterate over all entries in the list.  The order is important.
> */
> +       struct audit_ifaces *last_audit = NULL;
> +-      struct audit_list *al = audit_list->next;
> ++      struct audit_list_iter al_iter;
> ++      audit_list_iter_init (&al_iter);
> +
> +       /* Since we start using the auditing DSOs right away we need to
> +        initialize the data structures now.  */
> +@@ -1337,9 +1417,14 @@ of this helper program; chances are you did not
> intend to run this program.\n\
> +        use different values (especially the pointer guard) and will
> +        fail later on.  */
> +       security_init ();
> ++      need_security_init = false;
> +
> +-      do
> ++      while (true)
> +       {
> ++        const char *name = audit_list_iter_next (&al_iter);
> ++        if (name == NULL)
> ++          break;
> ++
> +         int tls_idx = GL(dl_tls_max_dtv_idx);
> +
> +         /* Now it is time to determine the layout of the static TLS
> +@@ -1348,7 +1433,7 @@ of this helper program; chances are you did not
> intend to run this program.\n\
> +            no DF_STATIC_TLS bit is set.  The reason is that we know
> +            glibc will use the static model.  */
> +         struct dlmopen_args dlmargs;
> +-        dlmargs.fname = al->name;
> ++        dlmargs.fname = name;
> +         dlmargs.map = NULL;
> +
> +         const char *objname;
> +@@ -1361,7 +1446,7 @@ of this helper program; chances are you did not
> intend to run this program.\n\
> +           not_loaded:
> +             _dl_error_printf ("\
> + ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s;
> ignored.\n",
> +-                              al->name, err_str);
> ++                              name, err_str);
> +             if (malloced)
> +               free ((char *) err_str);
> +           }
> +@@ -1465,10 +1550,7 @@ ERROR: ld.so: object '%s' cannot be loaded as
> audit interface: %s; ignored.\n",
> +                 goto not_loaded;
> +               }
> +           }
> +-
> +-        al = al->next;
> +       }
> +-      while (al != audit_list->next);
> +
> +       /* If we have any auditing modules, announce that we already
> +        have two objects loaded.  */
> +@@ -1732,7 +1814,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit
> interface: %s; ignored.\n",
> +   if (tcbp == NULL)
> +     tcbp = init_tls ();
> +
> +-  if (__glibc_likely (audit_list == NULL))
> ++  if (__glibc_likely (need_security_init))
> +     /* Initialize security features.  But only if we have not done it
> +        earlier.  */
> +     security_init ();
> +@@ -2363,9 +2445,7 @@ process_dl_audit (char *str)
> +   char *p;
> +
> +   while ((p = (strsep) (&str, ":")) != NULL)
> +-    if (p[0] != '\0'
> +-      && (__builtin_expect (! __libc_enable_secure, 1)
> +-          || strchr (p, '/') == NULL))
> ++    if (dso_name_valid_for_suid (p))
> +       {
> +       /* This is using the local malloc, not the system malloc.  The
> +          memory can never be freed.  */
> +@@ -2429,7 +2509,7 @@ process_envvars (enum mode *modep)
> +             break;
> +           }
> +         if (memcmp (envline, "AUDIT", 5) == 0)
> +-          process_dl_audit (&envline[6]);
> ++          audit_list_string = &envline[6];
> +         break;
> +
> +       case 7:
> +--
> +2.15.0
> +
> diff --git a/meta/recipes-core/glibc/glibc_2.24.bb
> b/meta/recipes-core/glibc/glibc_2.24.bb
> index 4c7d901149..4eba6aceb6 100644
> --- a/meta/recipes-core/glibc/glibc_2.24.bb
> +++ b/meta/recipes-core/glibc/glibc_2.24.bb
> @@ -46,6 +46,9 @@ SRC_URI =
> "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
>             file://0005-Remove-__ASSUME_REQUEUE_PI.patch \
>             file://0006-Fix-atomic_fetch_xor_release.patch \
>
> file://0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch \
> +
>  file://0001-CVE-2017-1000366-Ignore-LD_LIBRARY_PATH-for-AT_SECUR.patch \
> +
>  file://0002-ld.so-Reject-overly-long-LD_PRELOAD-path-elements.patch \
> +
>  file://0003-ld.so-Reject-overly-long-LD_AUDIT-path-elements.patch \
>  "
>
>  SRC_URI += "\
> --
> 2.15.0
>
> --
> _______________________________________________
> Openembedded-core mailing list
> Openembedded-core@lists.openembedded.org
> http://lists.openembedded.org/mailman/listinfo/openembedded-core
>

[-- Attachment #2: Type: text/html, Size: 25088 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180
  2017-11-15 20:36 [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180 George McCollister
  2017-11-15 20:36 ` [morty][PATCH v2 2/2] glibc: Fix CVE-2017-1000366 George McCollister
  2017-11-16  3:11 ` [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180 Khem Raj
@ 2017-11-16 18:45 ` akuster808
  2017-11-16 22:46   ` George McCollister
  2 siblings, 1 reply; 7+ messages in thread
From: akuster808 @ 2017-11-16 18:45 UTC (permalink / raw)
  To: George McCollister, openembedded-core



On 11/15/2017 12:36 PM, George McCollister wrote:
> Add backported patch to fix CVE-2015-5180 from the upstream
> release/2.24/master branch.
>
> Signed-off-by: George McCollister <george.mccollister@gmail.com>

Thanks for this series. I will have to wait until I address this in Pyro.

- armin
> ---
>
> Changes in v2:
>  - Fix commit message
>
>  ...80-resolv-Fix-crash-with-internal-QTYPE-B.patch | 357 +++++++++++++++++++++
>  meta/recipes-core/glibc/glibc_2.24.bb              |   1 +
>  2 files changed, 358 insertions(+)
>  create mode 100644 meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch
>
> diff --git a/meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch b/meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch
> new file mode 100644
> index 0000000000..ba0bebe488
> --- /dev/null
> +++ b/meta/recipes-core/glibc/glibc/0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch
> @@ -0,0 +1,357 @@
> +From ff9b7c4fb73295cd2de2d2ccfbbf4f6d50883d47 Mon Sep 17 00:00:00 2001
> +From: Florian Weimer <fweimer@redhat.com>
> +Date: Sat, 31 Dec 2016 20:22:09 +0100
> +Subject: [PATCH] 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.
> +
> +(cherry picked from commit fc82b0a2dfe7dbd35671c10510a8da1043d746a5)
> +
> +Upstream-Status: Backport
> +https://sourceware.org/git/?p=glibc.git;a=patch;h=b3b37f1a5559a7620e31c8053ed1b44f798f2b6d
> +
> +CVE: CVE-2015-5180
> +
> +Signed-off-by: George McCollister <george.mccollister@gmail.com>
> +---
> + ChangeLog                     |  14 ++++
> + NEWS                          |   6 ++
> + include/arpa/nameser_compat.h |   6 +-
> + resolv/Makefile               |   5 ++
> + 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, 221 insertions(+), 7 deletions(-)
> + create mode 100644 resolv/tst-resolv-qtypes.c
> +
> +diff --git a/ChangeLog b/ChangeLog
> +index 893262de11..2bdaf69e43 100644
> +--- a/ChangeLog
> ++++ b/ChangeLog
> +@@ -1,3 +1,17 @@
> ++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-10-26  Carlos O'Donell  <carlos@redhat.com>
> + 
> + 	* include/atomic.h
> +diff --git a/NEWS b/NEWS
> +index 3002773c16..4b1ca3cb65 100644
> +--- a/NEWS
> ++++ b/NEWS
> +@@ -11,6 +11,12 @@ using `glibc' in the "product" field.
> +   printers show various pthread variables in human-readable form when read
> +   using the 'print' or 'display' commands in gdb.
> + 
> ++* 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)
> ++
> + Version 2.24
> + 
> + * The minimum Linux kernel version that this version of the GNU C Library
> +diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h
> +index 2e735ede4c..7c0deed9ae 100644
> +--- a/include/arpa/nameser_compat.h
> ++++ b/include/arpa/nameser_compat.h
> +@@ -1,8 +1,8 @@
> + #ifndef _ARPA_NAMESER_COMPAT_
> + #include <resolv/arpa/nameser_compat.h>
> + 
> +-/* 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
> +diff --git a/resolv/Makefile b/resolv/Makefile
> +index 8be41d3ae1..a4c86b9762 100644
> +--- a/resolv/Makefile
> ++++ b/resolv/Makefile
> +@@ -40,6 +40,9 @@ ifeq ($(have-thread-library),yes)
> + extra-libs += libanl
> + routines += gai_sigqueue
> + tests += tst-res_hconf_reorder
> ++
> ++# This test sends millions of packets and is rather slow.
> ++xtests += tst-resolv-qtypes
> + endif
> + extra-libs-others = $(extra-libs)
> + libresolv-routines := gethnamaddr res_comp res_debug	\
> +@@ -117,3 +120,5 @@ tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
> + $(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
> + 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \
> + 	$(evaluate-test)
> ++
> ++$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
> +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
> +index 5f9e35701b..d16fa4b8ed 100644
> +--- a/resolv/nss_dns/dns-host.c
> ++++ b/resolv/nss_dns/dns-host.c
> +@@ -323,7 +323,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 12f9730199..d80b5318e5 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 944d1a90f5..07dc6f6583 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 0000000000..b3e60c693b
> +--- /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>
> +-- 
> +2.15.0
> +
> diff --git a/meta/recipes-core/glibc/glibc_2.24.bb b/meta/recipes-core/glibc/glibc_2.24.bb
> index e723e03dcf..4c7d901149 100644
> --- a/meta/recipes-core/glibc/glibc_2.24.bb
> +++ b/meta/recipes-core/glibc/glibc_2.24.bb
> @@ -45,6 +45,7 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
>             file://0004-New-condvar-implementation-that-provides-stronger-or.patch \
>             file://0005-Remove-__ASSUME_REQUEUE_PI.patch \
>             file://0006-Fix-atomic_fetch_xor_release.patch \
> +           file://0001-CVE-2015-5180-resolv-Fix-crash-with-internal-QTYPE-B.patch \
>  "
>  
>  SRC_URI += "\



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180
  2017-11-16 18:45 ` akuster808
@ 2017-11-16 22:46   ` George McCollister
  2017-11-20 18:56     ` akuster808
  0 siblings, 1 reply; 7+ messages in thread
From: George McCollister @ 2017-11-16 22:46 UTC (permalink / raw)
  To: akuster808; +Cc: OE-core

On Thu, Nov 16, 2017 at 12:45 PM, akuster808 <akuster808@gmail.com> wrote:
>
>
> On 11/15/2017 12:36 PM, George McCollister wrote:
>> Add backported patch to fix CVE-2015-5180 from the upstream
>> release/2.24/master branch.
>>
>> Signed-off-by: George McCollister <george.mccollister@gmail.com>
>
> Thanks for this series. I will have to wait until I address this in Pyro.

CVE-2015-5180 should not be an issue in glibc 2.25.

The CVE-2017-1000366 commits backported to glibc 2.25 are here:
https://sourceware.org/git/?p=glibc.git;a=commit;h=3c7cd21290cabdadd72984fb69bc51e64ff1002d
https://sourceware.org/git/?p=glibc.git;a=commit;h=46703a3995aa3ca2b816814aa4ad05ed524194dd
https://sourceware.org/git/?p=glibc.git;a=commit;h=c69d4a0f680a24fdbe323764a50382ad324041e9

Would it help if I sent Pyro patches for these?

>
> - armin


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180
  2017-11-16 22:46   ` George McCollister
@ 2017-11-20 18:56     ` akuster808
  0 siblings, 0 replies; 7+ messages in thread
From: akuster808 @ 2017-11-20 18:56 UTC (permalink / raw)
  To: George McCollister; +Cc: OE-core



On 11/16/2017 02:46 PM, George McCollister wrote:
> On Thu, Nov 16, 2017 at 12:45 PM, akuster808 <akuster808@gmail.com> wrote:
>>
>> On 11/15/2017 12:36 PM, George McCollister wrote:
>>> Add backported patch to fix CVE-2015-5180 from the upstream
>>> release/2.24/master branch.
>>>
>>> Signed-off-by: George McCollister <george.mccollister@gmail.com>
>> Thanks for this series. I will have to wait until I address this in Pyro.
> CVE-2015-5180 should not be an issue in glibc 2.25.
>
> The CVE-2017-1000366 commits backported to glibc 2.25 are here:
> https://sourceware.org/git/?p=glibc.git;a=commit;h=3c7cd21290cabdadd72984fb69bc51e64ff1002d
> https://sourceware.org/git/?p=glibc.git;a=commit;h=46703a3995aa3ca2b816814aa4ad05ed524194dd
> https://sourceware.org/git/?p=glibc.git;a=commit;h=c69d4a0f680a24fdbe323764a50382ad324041e9
>
> Would it help if I sent Pyro patches for these?
yes it would help.

thanks,
Armin
>
>> - armin



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-11-20 18:56 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-15 20:36 [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180 George McCollister
2017-11-15 20:36 ` [morty][PATCH v2 2/2] glibc: Fix CVE-2017-1000366 George McCollister
2017-11-16  3:12   ` Khem Raj
2017-11-16  3:11 ` [morty][PATCH v2 1/2] glibc: Fix CVE-2015-5180 Khem Raj
2017-11-16 18:45 ` akuster808
2017-11-16 22:46   ` George McCollister
2017-11-20 18:56     ` akuster808

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.