diff --git a/SOURCES/glibc-rh1705899-1.patch b/SOURCES/glibc-rh1705899-1.patch
new file mode 100644
index 0000000..9955c76
--- /dev/null
+++ b/SOURCES/glibc-rh1705899-1.patch
@@ -0,0 +1,466 @@
+commit 2afece36f6006844e87d7cb2fcb1ad8b220b2623
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Wed May 16 17:00:35 2018 +0200
+
+    support: Add TEST_COMPARE_BLOB, support_quote_blob
+    
+    The declaration of support_test_compare_blob uses unsigned long int,
+    to avoid including <stddef.h>.
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+(Adjusted for minor conflict in support/Makefile.)
+
+diff --git a/support/Makefile b/support/Makefile
+index 1bda81e55e519a57..fb9f4291d72156df 100644
+--- a/support/Makefile
++++ b/support/Makefile
+@@ -52,9 +52,11 @@ libsupport-routines = \
+   support_format_hostent \
+   support_format_netent \
+   support_isolate_in_subprocess \
++  support_quote_blob \
+   support_record_failure \
+   support_run_diff \
+   support_shared_allocate \
++  support_test_compare_blob \
+   support_test_compare_failure \
+   support_write_file_string \
+   support_test_main \
+@@ -150,8 +152,10 @@ tests = \
+   tst-support-namespace \
+   tst-support_capture_subprocess \
+   tst-support_format_dns_packet \
++  tst-support_quote_blob \
+   tst-support_record_failure \
+   tst-test_compare \
++  tst-test_compare_blob \
+   tst-xreadlink \
+ 
+ ifeq ($(run-built-tests),yes)
+diff --git a/support/check.h b/support/check.h
+index 2192f38941af2515..b3a4645e9255e90d 100644
+--- a/support/check.h
++++ b/support/check.h
+@@ -64,6 +64,8 @@ __BEGIN_DECLS
+         (1, __FILE__, __LINE__, #expr);                         \
+   })
+ 
++
++
+ int support_print_failure_impl (const char *file, int line,
+                                 const char *format, ...)
+   __attribute__ ((nonnull (1), format (printf, 3, 4)));
+@@ -141,6 +143,26 @@ void support_test_compare_failure (const char *file, int line,
+                                    int right_size);
+ 
+ 
++/* Compare [LEFT, LEFT + LEFT_LENGTH) with [RIGHT, RIGHT +
++   RIGHT_LENGTH) and report a test failure if the arrays are
++   different.  LEFT_LENGTH and RIGHT_LENGTH are measured in bytes.  If
++   the length is null, the corresponding pointer is ignored (i.e., it
++   can be NULL).  The blobs should be reasonably short because on
++   mismatch, both are printed.  */
++#define TEST_COMPARE_BLOB(left, left_length, right, right_length)       \
++  (support_test_compare_blob (left, left_length, right, right_length,   \
++                              __FILE__, __LINE__,                       \
++                              #left, #left_length, #right, #right_length))
++
++void support_test_compare_blob (const void *left,
++                                unsigned long int left_length,
++                                const void *right,
++                                unsigned long int right_length,
++                                const char *file, int line,
++                                const char *left_exp, const char *left_len_exp,
++                                const char *right_exp,
++                                const char *right_len_exp);
++
+ /* Internal function called by the test driver.  */
+ int support_report_failure (int status)
+   __attribute__ ((weak, warn_unused_result));
+diff --git a/support/support.h b/support/support.h
+index bc5827ed87d0d96c..b61fe0735c9204de 100644
+--- a/support/support.h
++++ b/support/support.h
+@@ -59,6 +59,12 @@ void support_shared_free (void *);
+    process on error.  */
+ void support_write_file_string (const char *path, const char *contents);
+ 
++/* Quote the contents of the byte array starting at BLOB, of LENGTH
++   bytes, in such a way that the result string can be included in a C
++   literal (in single/double quotes, without putting the quotes into
++   the result).  */
++char *support_quote_blob (const void *blob, size_t length);
++
+ /* Error-checking wrapper functions which terminate the process on
+    error.  */
+ 
+diff --git a/support/support_quote_blob.c b/support/support_quote_blob.c
+new file mode 100644
+index 0000000000000000..d6a678d8d69160a8
+--- /dev/null
++++ b/support/support_quote_blob.c
+@@ -0,0 +1,83 @@
++/* Quote a blob so that it can be used in C literals.
++   Copyright (C) 2018 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 <support/support.h>
++#include <support/xmemstream.h>
++
++char *
++support_quote_blob (const void *blob, size_t length)
++{
++  struct xmemstream out;
++  xopen_memstream (&out);
++
++  const unsigned char *p = blob;
++  for (size_t i = 0; i < length; ++i)
++    {
++      unsigned char ch = p[i];
++
++      /* Use C backslash escapes for those control characters for
++         which they are defined.  */
++      switch (ch)
++        {
++          case '\a':
++            putc_unlocked ('\\', out.out);
++            putc_unlocked ('a', out.out);
++            break;
++          case '\b':
++            putc_unlocked ('\\', out.out);
++            putc_unlocked ('b', out.out);
++            break;
++          case '\f':
++            putc_unlocked ('\\', out.out);
++            putc_unlocked ('f', out.out);
++            break;
++          case '\n':
++            putc_unlocked ('\\', out.out);
++            putc_unlocked ('n', out.out);
++            break;
++          case '\r':
++            putc_unlocked ('\\', out.out);
++            putc_unlocked ('r', out.out);
++            break;
++          case '\t':
++            putc_unlocked ('\\', out.out);
++            putc_unlocked ('t', out.out);
++            break;
++          case '\v':
++            putc_unlocked ('\\', out.out);
++            putc_unlocked ('v', out.out);
++            break;
++          case '\\':
++          case '\'':
++          case '\"':
++            putc_unlocked ('\\', out.out);
++            putc_unlocked (ch, out.out);
++            break;
++        default:
++          if (ch < ' ' || ch > '~')
++            /* Use octal sequences because they are fixed width,
++               unlike hexadecimal sequences.  */
++            fprintf (out.out, "\\%03o", ch);
++          else
++            putc_unlocked (ch, out.out);
++        }
++    }
++
++  xfclose_memstream (&out);
++  return out.buffer;
++}
+diff --git a/support/support_test_compare_blob.c b/support/support_test_compare_blob.c
+new file mode 100644
+index 0000000000000000..c5e63d1b9327c9fe
+--- /dev/null
++++ b/support/support_test_compare_blob.c
+@@ -0,0 +1,76 @@
++/* Check two binary blobs for equality.
++   Copyright (C) 2018 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 <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <support/xmemstream.h>
++
++static void
++report_length (const char *what, unsigned long int length, const char *expr)
++{
++  printf ("  %s %lu bytes (from %s)\n", what, length, expr);
++}
++
++static void
++report_blob (const char *what, const unsigned char *blob,
++             unsigned long int length, const char *expr)
++{
++  if (length > 0)
++    {
++      printf ("  %s (evaluated from %s):\n", what, expr);
++      char *quoted = support_quote_blob (blob, length);
++      printf ("      \"%s\"\n", quoted);
++      free (quoted);
++
++      fputs ("     ", stdout);
++      for (unsigned long i = 0; i < length; ++i)
++        printf (" %02X", blob[i]);
++      putc ('\n', stdout);
++    }
++}
++
++void
++support_test_compare_blob (const void *left, unsigned long int left_length,
++                           const void *right, unsigned long int right_length,
++                           const char *file, int line,
++                           const char *left_expr, const char *left_len_expr,
++                           const char *right_expr, const char *right_len_expr)
++{
++  /* No differences are possible if both lengths are null.  */
++  if (left_length == 0 && right_length == 0)
++    return;
++
++  if (left_length != right_length || left == NULL || right == NULL
++      || memcmp (left, right, left_length) != 0)
++    {
++      support_record_failure ();
++      printf ("%s:%d: error: blob comparison failed\n", file, line);
++      if (left_length == right_length)
++        printf ("  blob length: %lu bytes\n", left_length);
++      else
++        {
++          report_length ("left length: ", left_length, left_len_expr);
++          report_length ("right length:", right_length, right_len_expr);
++        }
++      report_blob ("left", left, left_length, left_expr);
++      report_blob ("right", right, right_length, right_expr);
++    }
++}
+diff --git a/support/tst-support_quote_blob.c b/support/tst-support_quote_blob.c
+new file mode 100644
+index 0000000000000000..5467a190a6e0725c
+--- /dev/null
++++ b/support/tst-support_quote_blob.c
+@@ -0,0 +1,61 @@
++/* Test the support_quote_blob function.
++   Copyright (C) 2018 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 <support/check.h>
++#include <support/support.h>
++#include <string.h>
++#include <stdlib.h>
++
++static int
++do_test (void)
++{
++  /* Check handling of the empty blob, both with and without trailing
++     NUL byte.  */
++  char *p = support_quote_blob ("", 0);
++  TEST_COMPARE (strlen (p), 0);
++  free (p);
++  p = support_quote_blob ("X", 0);
++  TEST_COMPARE (strlen (p), 0);
++  free (p);
++
++  /* Check escaping of backslash-escaped characters, and lack of
++     escaping for other shell meta-characters.  */
++  p = support_quote_blob ("$()*?`@[]{}~\'\"X", 14);
++  TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\""), 0);
++  free (p);
++
++  /* Check lack of escaping for letters and digits.  */
++#define LETTERS_AND_DIGTS                       \
++  "abcdefghijklmnopqrstuvwxyz"                  \
++  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"                  \
++  "0123456789"
++  p = support_quote_blob (LETTERS_AND_DIGTS "@", 2 * 26 + 10);
++  TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS), 0);
++  free (p);
++
++  /* Check escaping of control characters and other non-printable
++     characters.  */
++  p = support_quote_blob ("\r\n\t\a\b\f\v\1\177\200\377\0@", 14);
++  TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\001"
++                        "\\177\\200\\377\\000@\\000"), 0);
++  free (p);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/support/tst-test_compare_blob.c b/support/tst-test_compare_blob.c
+new file mode 100644
+index 0000000000000000..aa8643e18227da85
+--- /dev/null
++++ b/support/tst-test_compare_blob.c
+@@ -0,0 +1,125 @@
++/* Basic test for the TEST_COMPARE_BLOB macro.
++   Copyright (C) 2018 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 <string.h>
++#include <support/check.h>
++#include <support/capture_subprocess.h>
++
++static void
++subprocess (void *closure)
++{
++  /* These tests should fail.  They were chosen to cover differences
++     in length (with the same contents), single-bit mismatches, and
++     mismatching null pointers.  */
++  TEST_COMPARE_BLOB ("", 0, "", 1);    /* Line 29.  */
++  TEST_COMPARE_BLOB ("X", 1, "", 1);   /* Line 30.  */
++  TEST_COMPARE_BLOB ("abcd", 3, "abcd", 4); /* Line 31.  */
++  TEST_COMPARE_BLOB ("abcd", 4, "abcD", 4); /* Line 32.  */
++  TEST_COMPARE_BLOB ("abcd", 4, NULL, 0); /* Line 33.  */
++  TEST_COMPARE_BLOB (NULL, 0, "abcd", 4); /* Line 34.  */
++}
++
++/* Same contents, different addresses.  */
++char buffer_abc_1[] = "abc";
++char buffer_abc_2[] = "abc";
++
++static int
++do_test (void)
++{
++  /* This should succeed.  Even if the pointers and array contents are
++     different, zero-length inputs are not different.  */
++  TEST_COMPARE_BLOB ("", 0, "", 0);
++  TEST_COMPARE_BLOB ("", 0, buffer_abc_1, 0);
++  TEST_COMPARE_BLOB (buffer_abc_1, 0, "", 0);
++  TEST_COMPARE_BLOB (NULL, 0, "", 0);
++  TEST_COMPARE_BLOB ("", 0, NULL, 0);
++  TEST_COMPARE_BLOB (NULL, 0, NULL, 0);
++
++  /* Check equality of blobs containing a single NUL byte.  */
++  TEST_COMPARE_BLOB ("", 1, "", 1);
++  TEST_COMPARE_BLOB ("", 1, &buffer_abc_1[3], 1);
++
++  /* Check equality of blobs of varying lengths.  */
++  for (size_t i = 0; i <= sizeof (buffer_abc_1); ++i)
++    TEST_COMPARE_BLOB (buffer_abc_1, i, buffer_abc_2, i);
++
++  struct support_capture_subprocess proc = support_capture_subprocess
++    (&subprocess, NULL);
++
++  /* Discard the reported error.  */
++  support_record_failure_reset ();
++
++  puts ("info: *** subprocess output starts ***");
++  fputs (proc.out.buffer, stdout);
++  puts ("info: *** subprocess output ends ***");
++
++  TEST_VERIFY
++    (strcmp (proc.out.buffer,
++"tst-test_compare_blob.c:29: error: blob comparison failed\n"
++"  left length:  0 bytes (from 0)\n"
++"  right length: 1 bytes (from 1)\n"
++"  right (evaluated from \"\"):\n"
++"      \"\\000\"\n"
++"      00\n"
++"tst-test_compare_blob.c:30: error: blob comparison failed\n"
++"  blob length: 1 bytes\n"
++"  left (evaluated from \"X\"):\n"
++"      \"X\"\n"
++"      58\n"
++"  right (evaluated from \"\"):\n"
++"      \"\\000\"\n"
++"      00\n"
++"tst-test_compare_blob.c:31: error: blob comparison failed\n"
++"  left length:  3 bytes (from 3)\n"
++"  right length: 4 bytes (from 4)\n"
++"  left (evaluated from \"abcd\"):\n"
++"      \"abc\"\n"
++"      61 62 63\n"
++"  right (evaluated from \"abcd\"):\n"
++"      \"abcd\"\n"
++"      61 62 63 64\n"
++"tst-test_compare_blob.c:32: error: blob comparison failed\n"
++"  blob length: 4 bytes\n"
++"  left (evaluated from \"abcd\"):\n"
++"      \"abcd\"\n"
++"      61 62 63 64\n"
++"  right (evaluated from \"abcD\"):\n"
++"      \"abcD\"\n"
++"      61 62 63 44\n"
++"tst-test_compare_blob.c:33: error: blob comparison failed\n"
++"  left length:  4 bytes (from 4)\n"
++"  right length: 0 bytes (from 0)\n"
++"  left (evaluated from \"abcd\"):\n"
++"      \"abcd\"\n"
++"      61 62 63 64\n"
++"tst-test_compare_blob.c:34: error: blob comparison failed\n"
++"  left length:  0 bytes (from 0)\n"
++"  right length: 4 bytes (from 4)\n"
++"  right (evaluated from \"abcd\"):\n"
++"      \"abcd\"\n"
++"      61 62 63 64\n"
++             ) == 0);
++
++  /* Check that there is no output on standard error.  */
++  support_capture_subprocess_check (&proc, "TEST_COMPARE_BLOB",
++                                    0, sc_allow_stdout);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-rh1705899-2.patch b/SOURCES/glibc-rh1705899-2.patch
new file mode 100644
index 0000000..5e0e669
--- /dev/null
+++ b/SOURCES/glibc-rh1705899-2.patch
@@ -0,0 +1,50 @@
+commit 5c0202af4b3d588c04bcec7baf05706b21cd7416
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Tue Jun 26 12:05:21 2018 +0200
+
+    support: Add TEST_NO_SETVBUF
+    
+    This is sometimes needed for testing stdio streams, where the
+    setvbuf call in the test driver could interfere with the test.
+
+diff --git a/support/support_test_main.c b/support/support_test_main.c
+index 396385729b6809ad..23429779aca85613 100644
+--- a/support/support_test_main.c
++++ b/support/support_test_main.c
+@@ -270,7 +270,8 @@ support_test_main (int argc, char **argv, const struct test_config *config)
+     timeout =  DEFAULT_TIMEOUT;
+ 
+   /* Make sure we see all message, even those on stdout.  */
+-  setvbuf (stdout, NULL, _IONBF, 0);
++  if (!config->no_setvbuf)
++    setvbuf (stdout, NULL, _IONBF, 0);
+ 
+   /* Make sure temporary files are deleted.  */
+   if (support_delete_temp_files != NULL)
+diff --git a/support/test-driver.c b/support/test-driver.c
+index 09c8783e4f54d809..9798f16227b9d467 100644
+--- a/support/test-driver.c
++++ b/support/test-driver.c
+@@ -140,6 +140,10 @@ main (int argc, char **argv)
+   test_config.no_mallopt = 1;
+ #endif
+ 
++#ifdef TEST_NO_SETVBUF
++  test_config.no_setvbuf = 1;
++#endif
++
+ #ifdef TIMEOUT
+   test_config.timeout = TIMEOUT;
+ #endif
+diff --git a/support/test-driver.h b/support/test-driver.h
+index 1708d68d608ee4a4..549179b254946390 100644
+--- a/support/test-driver.h
++++ b/support/test-driver.h
+@@ -35,6 +35,7 @@ struct test_config
+   int expected_status;   /* Expected exit status.  */
+   int expected_signal;   /* If non-zero, expect termination by signal.  */
+   char no_mallopt;       /* Boolean flag to disable mallopt.  */
++  char no_setvbuf;       /* Boolean flag to disable setvbuf.  */
+   const char *optstring; /* Short command line options.  */
+ };
+ 
diff --git a/SOURCES/glibc-rh1705899-3.patch b/SOURCES/glibc-rh1705899-3.patch
new file mode 100644
index 0000000..3e3fa24
--- /dev/null
+++ b/SOURCES/glibc-rh1705899-3.patch
@@ -0,0 +1,230 @@
+commit 0262507918cfad7223bf81b8f162b7adc7a2af01
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Fri Jun 1 10:43:06 2018 +0200
+
+    libio: Avoid _allocate_buffer, _free_buffer function pointers [BZ #23236]
+
+    These unmangled function pointers reside on the heap and could
+    be targeted by exploit writers, effectively bypassing libio vtable
+    validation.  Instead, we ignore these pointers and always call
+    malloc or free.
+
+    In theory, this is a backwards-incompatible change, but using the
+    global heap instead of the user-supplied callback functions should
+    have little application impact.  (The old libstdc++ implementation
+    exposed this functionality via a public, undocumented constructor
+    in its strstreambuf class.)
+
+    (cherry picked from commit 4e8a6346cd3da2d88bbad745a1769260d36f2783)
+
+Backported from the upstream release/2.27/master branch.
+
+diff --git a/debug/vasprintf_chk.c b/debug/vasprintf_chk.c
+index a8ca32bad57b4d13..113354749ccf8d9a 100644
+--- a/debug/vasprintf_chk.c
++++ b/debug/vasprintf_chk.c
+@@ -55,8 +55,8 @@ __vasprintf_chk (char **result_ptr, int flags, const char *format,
+   _IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
+   _IO_str_init_static_internal (&sf, string, init_string_size, string);
+   sf._sbf._f._flags &= ~_IO_USER_BUF;
+-  sf._s._allocate_buffer = (_IO_alloc_type) malloc;
+-  sf._s._free_buffer = (_IO_free_type) free;
++  sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc;
++  sf._s._free_buffer_unused = (_IO_free_type) free;
+ 
+   /* For flags > 0 (i.e. __USE_FORTIFY_LEVEL > 1) request that %n
+      can only come from read-only format strings.  */
+diff --git a/libio/memstream.c b/libio/memstream.c
+index e18a7756b297c9f4..9a51331e525c3468 100644
+--- a/libio/memstream.c
++++ b/libio/memstream.c
+@@ -87,8 +87,8 @@ open_memstream (char **bufloc, _IO_size_t *sizeloc)
+   _IO_JUMPS ((struct _IO_FILE_plus *) &new_f->fp._sf._sbf) = &_IO_mem_jumps;
+   _IO_str_init_static_internal (&new_f->fp._sf, buf, _IO_BUFSIZ, buf);
+   new_f->fp._sf._sbf._f._flags &= ~_IO_USER_BUF;
+-  new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc;
+-  new_f->fp._sf._s._free_buffer = (_IO_free_type) free;
++  new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc;
++  new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free;
+ 
+   new_f->fp.bufloc = bufloc;
+   new_f->fp.sizeloc = sizeloc;
+diff --git a/libio/strfile.h b/libio/strfile.h
+index 4ea7548f9fa92638..9cd8e7c466616b52 100644
+--- a/libio/strfile.h
++++ b/libio/strfile.h
+@@ -34,8 +34,11 @@ typedef void (*_IO_free_type) (void*);
+ 
+ struct _IO_str_fields
+ {
+-  _IO_alloc_type _allocate_buffer;
+-  _IO_free_type _free_buffer;
++  /* These members are preserved for ABI compatibility.  The glibc
++     implementation always calls malloc/free for user buffers if
++     _IO_USER_BUF or _IO_FLAGS2_USER_WBUF are not set.  */
++  _IO_alloc_type _allocate_buffer_unused;
++  _IO_free_type _free_buffer_unused;
+ };
+ 
+ /* This is needed for the Irix6 N32 ABI, which has a 64 bit off_t type,
+@@ -55,10 +58,6 @@ typedef struct _IO_strfile_
+   struct _IO_str_fields _s;
+ } _IO_strfile;
+ 
+-/* dynamic: set when the array object is allocated (or reallocated)  as
+-   necessary to hold a character sequence that can change in length. */
+-#define _IO_STR_DYNAMIC(FP) ((FP)->_s._allocate_buffer != (_IO_alloc_type)0)
+-
+ /* frozen: set when the program has requested that the array object not
+    be altered, reallocated, or freed. */
+ #define _IO_STR_FROZEN(FP) ((FP)->_f._IO_file_flags & _IO_USER_BUF)
+diff --git a/libio/strops.c b/libio/strops.c
+index fdd113a60811e593..129a0f6aeca818fd 100644
+--- a/libio/strops.c
++++ b/libio/strops.c
+@@ -61,7 +61,7 @@ _IO_str_init_static_internal (_IO_strfile *sf, char *ptr, _IO_size_t size,
+       fp->_IO_read_end = end;
+     }
+   /* A null _allocate_buffer function flags the strfile as being static. */
+-  sf->_s._allocate_buffer = (_IO_alloc_type) 0;
++  sf->_s._allocate_buffer_unused = (_IO_alloc_type) 0;
+ }
+ 
+ void
+@@ -103,8 +103,7 @@ _IO_str_overflow (_IO_FILE *fp, int c)
+ 	  _IO_size_t new_size = 2 * old_blen + 100;
+ 	  if (new_size < old_blen)
+ 	    return EOF;
+-	  new_buf
+-	    = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
++	  new_buf = malloc (new_size);
+ 	  if (new_buf == NULL)
+ 	    {
+ 	      /*	  __ferror(fp) = 1; */
+@@ -113,7 +112,7 @@ _IO_str_overflow (_IO_FILE *fp, int c)
+ 	  if (old_buf)
+ 	    {
+ 	      memcpy (new_buf, old_buf, old_blen);
+-	      (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
++	      free (old_buf);
+ 	      /* Make sure _IO_setb won't try to delete _IO_buf_base. */
+ 	      fp->_IO_buf_base = NULL;
+ 	    }
+@@ -182,15 +181,14 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
+ 
+   _IO_size_t newsize = offset + 100;
+   char *oldbuf = fp->_IO_buf_base;
+-  char *newbuf
+-    = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize);
++  char *newbuf = malloc (newsize);
+   if (newbuf == NULL)
+     return 1;
+ 
+   if (oldbuf != NULL)
+     {
+       memcpy (newbuf, oldbuf, _IO_blen (fp));
+-      (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
++      free (oldbuf);
+       /* Make sure _IO_setb won't try to delete
+ 	 _IO_buf_base. */
+       fp->_IO_buf_base = NULL;
+@@ -317,7 +315,7 @@ void
+ _IO_str_finish (_IO_FILE *fp, int dummy)
+ {
+   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
+-    (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
++    free (fp->_IO_buf_base);
+   fp->_IO_buf_base = NULL;
+ 
+   _IO_default_finish (fp, 0);
+diff --git a/libio/vasprintf.c b/libio/vasprintf.c
+index 282c86fff0a7ae0e..867ef4fe4ca4ec56 100644
+--- a/libio/vasprintf.c
++++ b/libio/vasprintf.c
+@@ -54,8 +54,8 @@ _IO_vasprintf (char **result_ptr, const char *format, _IO_va_list args)
+   _IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
+   _IO_str_init_static_internal (&sf, string, init_string_size, string);
+   sf._sbf._f._flags &= ~_IO_USER_BUF;
+-  sf._s._allocate_buffer = (_IO_alloc_type) malloc;
+-  sf._s._free_buffer = (_IO_free_type) free;
++  sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc;
++  sf._s._free_buffer_unused = (_IO_free_type) free;
+   ret = _IO_vfprintf (&sf._sbf._f, format, args);
+   if (ret < 0)
+     {
+diff --git a/libio/wmemstream.c b/libio/wmemstream.c
+index bd6d1798b1685fe9..3a9a681c80a321a7 100644
+--- a/libio/wmemstream.c
++++ b/libio/wmemstream.c
+@@ -90,8 +90,8 @@ open_wmemstream (wchar_t **bufloc, _IO_size_t *sizeloc)
+   _IO_wstr_init_static (&new_f->fp._sf._sbf._f, buf,
+ 			_IO_BUFSIZ / sizeof (wchar_t), buf);
+   new_f->fp._sf._sbf._f._flags2 &= ~_IO_FLAGS2_USER_WBUF;
+-  new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc;
+-  new_f->fp._sf._s._free_buffer = (_IO_free_type) free;
++  new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc;
++  new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free;
+ 
+   new_f->fp.bufloc = bufloc;
+   new_f->fp.sizeloc = sizeloc;
+diff --git a/libio/wstrops.c b/libio/wstrops.c
+index 7a9a33ab8763b8ff..a31d0e23341b2aad 100644
+--- a/libio/wstrops.c
++++ b/libio/wstrops.c
+@@ -63,7 +63,7 @@ _IO_wstr_init_static (_IO_FILE *fp, wchar_t *ptr, _IO_size_t size,
+       fp->_wide_data->_IO_read_end = end;
+     }
+   /* A null _allocate_buffer function flags the strfile as being static. */
+-  (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0;
++  (((_IO_strfile *) fp)->_s._allocate_buffer_unused) = (_IO_alloc_type)0;
+ }
+ 
+ _IO_wint_t
+@@ -95,9 +95,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c)
+ 	      || __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t)))
+ 	    return EOF;
+ 
+-	  new_buf
+-	    = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
+-									* sizeof (wchar_t));
++	  new_buf = malloc (new_size * sizeof (wchar_t));
+ 	  if (new_buf == NULL)
+ 	    {
+ 	      /*	  __ferror(fp) = 1; */
+@@ -106,7 +104,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c)
+ 	  if (old_buf)
+ 	    {
+ 	      __wmemcpy (new_buf, old_buf, old_wblen);
+-	      (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
++	      free (old_buf);
+ 	      /* Make sure _IO_setb won't try to delete _IO_buf_base. */
+ 	      fp->_wide_data->_IO_buf_base = NULL;
+ 	    }
+@@ -186,16 +184,14 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
+     return 1;
+ 
+   wchar_t *oldbuf = wd->_IO_buf_base;
+-  wchar_t *newbuf
+-    = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize
+-								* sizeof (wchar_t));
++  wchar_t *newbuf = malloc (newsize * sizeof (wchar_t));
+   if (newbuf == NULL)
+     return 1;
+ 
+   if (oldbuf != NULL)
+     {
+       __wmemcpy (newbuf, oldbuf, _IO_wblen (fp));
+-      (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
++      free (oldbuf);
+       /* Make sure _IO_setb won't try to delete
+ 	 _IO_buf_base. */
+       wd->_IO_buf_base = NULL;
+@@ -326,7 +322,7 @@ void
+ _IO_wstr_finish (_IO_FILE *fp, int dummy)
+ {
+   if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF))
+-    (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base);
++    free (fp->_wide_data->_IO_buf_base);
+   fp->_wide_data->_IO_buf_base = NULL;
+ 
+   _IO_wdefault_finish (fp, 0);
diff --git a/SOURCES/glibc-rh1705899-4.patch b/SOURCES/glibc-rh1705899-4.patch
new file mode 100644
index 0000000..80c7606
--- /dev/null
+++ b/SOURCES/glibc-rh1705899-4.patch
@@ -0,0 +1,34 @@
+commit 3bb748257405e94e13de76573a4e9da1cfd961d0
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Tue Jul 3 15:54:49 2018 +0200
+
+    libio: Disable vtable validation in case of interposition [BZ #23313]
+
+    (cherry picked from commit c402355dfa7807b8e0adb27c009135a7e2b9f1b0)
+
+Backported from the upstream release/2.27/master branch.
+
+diff --git a/libio/vtables.c b/libio/vtables.c
+index e364ea03edbfa75b..d6478e4bab9050ce 100644
+--- a/libio/vtables.c
++++ b/libio/vtables.c
+@@ -68,3 +68,19 @@ _IO_vtable_check (void)
+ 
+   __libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n");
+ }
++
++/* Some variants of libstdc++ interpose _IO_2_1_stdin_ etc. and
++   install their own vtables directly, without calling _IO_init or
++   other functions.  Detect this by looking at the vtables values
++   during startup, and disable vtable validation in this case.  */
++#ifdef SHARED
++__attribute__ ((constructor))
++static void
++check_stdfiles_vtables (void)
++{
++  if (_IO_2_1_stdin_.vtable != &_IO_file_jumps
++      || _IO_2_1_stdout_.vtable != &_IO_file_jumps
++      || _IO_2_1_stderr_.vtable != &_IO_file_jumps)
++    IO_set_accept_foreign_vtables (&_IO_vtable_check);
++}
++#endif
diff --git a/SOURCES/glibc-rh1705899-5.patch b/SOURCES/glibc-rh1705899-5.patch
new file mode 100644
index 0000000..1500ba3
--- /dev/null
+++ b/SOURCES/glibc-rh1705899-5.patch
@@ -0,0 +1,624 @@
+commit 44927211651adde42bbd431ef5ebe568186125e5
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Tue Jul 3 17:57:14 2018 +0200
+
+    libio: Add tst-vtables, tst-vtables-interposed
+
+    (cherry picked from commit 29055464a03c72762969a2e8734d0d05d4d70e58)
+
+    Some adjustments were needed for a tricky multi-inclusion issue related
+    to libioP.h.
+
+Backported from the upsteam release/2.27/master branch, adjusted for
+lack of tests-internal support downstream.
+
+diff --git a/libio/Makefile b/libio/Makefile
+index 0cef96141209fe99..1e923da42e45c492 100644
+--- a/libio/Makefile
++++ b/libio/Makefile
+@@ -61,7 +61,9 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \
+ 	bug-memstream1 bug-wmemstream1 \
+ 	tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
+ 	tst-fwrite-error tst-ftell-active-handler \
+-	tst-ftell-append
++	tst-ftell-append \
++	tst-vtables tst-vtables-interposed
++
+ ifeq (yes,$(build-shared))
+ # Add test-fopenloc only if shared library is enabled since it depends on
+ # shared localedata objects.
+diff --git a/libio/tst-vtables-common.c b/libio/tst-vtables-common.c
+new file mode 100644
+index 0000000000000000..dc8d89c195b95b8d
+--- /dev/null
++++ b/libio/tst-vtables-common.c
+@@ -0,0 +1,511 @@
++/* Test for libio vtables and their validation.  Common code.
++   Copyright (C) 2018 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/>.  */
++
++/* This test provides some coverage for how various stdio functions
++   use the vtables in FILE * objects.  The focus is mostly on which
++   functions call which methods, not so much on validating data
++   processing.  An initial series of tests check that custom vtables
++   do not work without activation through _IO_init.
++
++   Note: libio vtables are deprecated feature.  Do not use this test
++   as a documentation source for writing custom vtables.  See
++   fopencookie for a different way of creating custom stdio
++   streams.  */
++
++#include <stdbool.h>
++#include <string.h>
++#include <support/capture_subprocess.h>
++#include <support/check.h>
++#include <support/namespace.h>
++#include <support/support.h>
++#include <support/test-driver.h>
++#include <support/xunistd.h>
++
++/* Data shared between the test subprocess and the test driver in the
++   parent.  Note that *shared is reset at the start of the check_call
++   function.  */
++struct shared
++{
++  /* Expected file pointer for method calls.  */
++  FILE *fp;
++
++  /* If true, assume that a call to _IO_init is needed to enable
++     custom vtables.  */
++  bool initially_disabled;
++
++  /* Requested return value for the methods which have one.  */
++  int return_value;
++
++  /* A value (usually a character) recorded by some of the methods
++     below.  */
++  int value;
++
++  /* Likewise, for some data.  */
++  char buffer[16];
++  size_t buffer_length;
++
++  /* Total number of method calls.  */
++  unsigned int calls;
++
++  /* Individual method call counts.  */
++  unsigned int calls_finish;
++  unsigned int calls_overflow;
++  unsigned int calls_underflow;
++  unsigned int calls_uflow;
++  unsigned int calls_pbackfail;
++  unsigned int calls_xsputn;
++  unsigned int calls_xsgetn;
++  unsigned int calls_seekoff;
++  unsigned int calls_seekpos;
++  unsigned int calls_setbuf;
++  unsigned int calls_sync;
++  unsigned int calls_doallocate;
++  unsigned int calls_read;
++  unsigned int calls_write;
++  unsigned int calls_seek;
++  unsigned int calls_close;
++  unsigned int calls_stat;
++  unsigned int calls_showmanyc;
++  unsigned int calls_imbue;
++} *shared;
++
++/* Method implementations which increment the counters in *shared.  */
++
++static void
++log_method (FILE *fp, const char *name)
++{
++  if (test_verbose > 0)
++    printf ("info: %s (%p) called\n", name, fp);
++}
++
++static void
++method_finish (FILE *fp, int dummy)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_finish;
++}
++
++static int
++method_overflow (FILE *fp, int ch)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_overflow;
++  shared->value = ch;
++  return shared->return_value;
++}
++
++static int
++method_underflow (FILE *fp)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_underflow;
++  return shared->return_value;
++}
++
++static int
++method_uflow (FILE *fp)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_uflow;
++  return shared->return_value;
++}
++
++static int
++method_pbackfail (FILE *fp, int ch)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_pbackfail;
++  shared->value = ch;
++  return shared->return_value;
++}
++
++static size_t
++method_xsputn (FILE *fp, const void *data, size_t n)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_xsputn;
++
++  size_t to_copy = n;
++  if (n > sizeof (shared->buffer))
++    to_copy = sizeof (shared->buffer);
++  memcpy (shared->buffer, data, to_copy);
++  shared->buffer_length = to_copy;
++  return to_copy;
++}
++
++static size_t
++method_xsgetn (FILE *fp, void *data, size_t n)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_xsgetn;
++  return 0;
++}
++
++static off64_t
++method_seekoff (FILE *fp, off64_t offset, int dir, int mode)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_seekoff;
++  return shared->return_value;
++}
++
++static off64_t
++method_seekpos (FILE *fp, off64_t offset, int mode)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_seekpos;
++  return shared->return_value;
++}
++
++static FILE *
++method_setbuf (FILE *fp, char *buffer, ssize_t length)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_setbuf;
++  return fp;
++}
++
++static int
++method_sync (FILE *fp)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_sync;
++  return shared->return_value;
++}
++
++static int
++method_doallocate (FILE *fp)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_doallocate;
++  return shared->return_value;
++}
++
++static ssize_t
++method_read (FILE *fp, void *data, ssize_t length)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_read;
++  return shared->return_value;
++}
++
++static ssize_t
++method_write (FILE *fp, const void *data, ssize_t length)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_write;
++  return shared->return_value;
++}
++
++static off64_t
++method_seek (FILE *fp, off64_t offset, int mode)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_seek;
++  return shared->return_value;
++}
++
++static int
++method_close (FILE *fp)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_close;
++  return shared->return_value;
++}
++
++static int
++method_stat (FILE *fp, void *buffer)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_stat;
++  return shared->return_value;
++}
++
++static int
++method_showmanyc (FILE *fp)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_showmanyc;
++  return shared->return_value;
++}
++
++static void
++method_imbue (FILE *fp, void *locale)
++{
++  log_method (fp, __func__);
++  TEST_VERIFY (fp == shared->fp);
++  ++shared->calls;
++  ++shared->calls_imbue;
++}
++
++/* Our custom vtable.  */
++
++static const struct _IO_jump_t jumps =
++{
++  JUMP_INIT_DUMMY,
++  JUMP_INIT (finish, method_finish),
++  JUMP_INIT (overflow, method_overflow),
++  JUMP_INIT (underflow, method_underflow),
++  JUMP_INIT (uflow, method_uflow),
++  JUMP_INIT (pbackfail, method_pbackfail),
++  JUMP_INIT (xsputn, method_xsputn),
++  JUMP_INIT (xsgetn, method_xsgetn),
++  JUMP_INIT (seekoff, method_seekoff),
++  JUMP_INIT (seekpos, method_seekpos),
++  JUMP_INIT (setbuf, method_setbuf),
++  JUMP_INIT (sync, method_sync),
++  JUMP_INIT (doallocate, method_doallocate),
++  JUMP_INIT (read, method_read),
++  JUMP_INIT (write, method_write),
++  JUMP_INIT (seek, method_seek),
++  JUMP_INIT (close, method_close),
++  JUMP_INIT (stat, method_stat),
++  JUMP_INIT (showmanyc, method_showmanyc),
++  JUMP_INIT (imbue, method_imbue)
++};
++
++/* Our file implementation.  */
++
++struct my_file
++{
++  FILE f;
++  const struct _IO_jump_t *vtable;
++};
++
++struct my_file
++my_file_create (void)
++{
++  return (struct my_file)
++    {
++      /* Disable locking, so that we do not have to set up a lock
++         pointer.  */
++      .f._flags =  _IO_USER_LOCK,
++
++      /* Copy the offset from the an initialized handle, instead of
++         figuring it out from scratch.  */
++      .f._vtable_offset = stdin->_vtable_offset,
++
++      .vtable = &jumps,
++    };
++}
++
++/* Initial tests which do not enable vtable compatibility.  */
++
++/* Inhibit GCC optimization of fprintf.  */
++typedef int (*fprintf_type) (FILE *, const char *, ...);
++static const volatile fprintf_type fprintf_ptr = &fprintf;
++
++static void
++without_compatibility_fprintf (void *closure)
++{
++  /* This call should abort.  */
++  fprintf_ptr (shared->fp, " ");
++  _exit (1);
++}
++
++static void
++without_compatibility_fputc (void *closure)
++{
++  /* This call should abort.  */
++  fputc (' ', shared->fp);
++  _exit (1);
++}
++
++static void
++without_compatibility_fgetc (void *closure)
++{
++  /* This call should abort.  */
++  fgetc (shared->fp);
++  _exit (1);
++}
++
++static void
++without_compatibility_fflush (void *closure)
++{
++  /* This call should abort.  */
++  fflush (shared->fp);
++  _exit (1);
++}
++
++/* Exit status after abnormal termination.  */
++static int termination_status;
++
++static void
++init_termination_status (void)
++{
++  pid_t pid = xfork ();
++  if (pid == 0)
++    abort ();
++  xwaitpid (pid, &termination_status, 0);
++
++  TEST_VERIFY (WIFSIGNALED (termination_status));
++  TEST_COMPARE (WTERMSIG (termination_status), SIGABRT);
++}
++
++static void
++check_for_termination (const char *name, void (*callback) (void *))
++{
++  struct my_file file = my_file_create ();
++  shared->fp = &file.f;
++  shared->return_value = -1;
++  shared->calls = 0;
++  struct support_capture_subprocess proc
++    = support_capture_subprocess (callback, NULL);
++  support_capture_subprocess_check (&proc, name, termination_status,
++                                    sc_allow_stderr);
++  const char *message
++    = "Fatal error: glibc detected an invalid stdio handle\n";
++  TEST_COMPARE_BLOB (proc.err.buffer, proc.err.length,
++                     message, strlen (message));
++  TEST_COMPARE (shared->calls, 0);
++  support_capture_subprocess_free (&proc);
++}
++
++/* The test with vtable validation disabled.  */
++
++/* This function does not have a prototype in libioP.h to prevent
++   accidental use from within the library (which would disable vtable
++   verification).  */
++void _IO_init (FILE *fp, int flags);
++
++static void
++with_compatibility_fprintf (void *closure)
++{
++  TEST_COMPARE (fprintf_ptr (shared->fp, "A%sCD", "B"), 4);
++  TEST_COMPARE (shared->calls, 3);
++  TEST_COMPARE (shared->calls_xsputn, 3);
++  TEST_COMPARE_BLOB (shared->buffer, shared->buffer_length,
++                     "CD", 2);
++}
++
++static void
++with_compatibility_fputc (void *closure)
++{
++  shared->return_value = '@';
++  TEST_COMPARE (fputc ('@', shared->fp), '@');
++  TEST_COMPARE (shared->calls, 1);
++  TEST_COMPARE (shared->calls_overflow, 1);
++  TEST_COMPARE (shared->value, '@');
++}
++
++static void
++with_compatibility_fgetc (void *closure)
++{
++  shared->return_value = 'X';
++  TEST_COMPARE (fgetc (shared->fp), 'X');
++  TEST_COMPARE (shared->calls, 1);
++  TEST_COMPARE (shared->calls_uflow, 1);
++}
++
++static void
++with_compatibility_fflush (void *closure)
++{
++  TEST_COMPARE (fflush (shared->fp), 0);
++  TEST_COMPARE (shared->calls, 1);
++  TEST_COMPARE (shared->calls_sync, 1);
++}
++
++/* Call CALLBACK in a subprocess, after setting up a custom file
++   object and updating shared->fp.  */
++static void
++check_call (const char *name, void (*callback) (void *),
++            bool initially_disabled)
++{
++  *shared = (struct shared)
++    {
++     .initially_disabled = initially_disabled,
++    };
++
++  /* Set up a custom file object.  */
++  struct my_file file = my_file_create ();
++  shared->fp = &file.f;
++  if (shared->initially_disabled)
++    _IO_init (shared->fp, file.f._flags);
++
++  if (test_verbose > 0)
++    printf ("info: calling test %s\n", name);
++  support_isolate_in_subprocess (callback, NULL);
++}
++
++/* Run the tests.  INITIALLY_DISABLED indicates whether custom vtables
++   are disabled when the test starts.  */
++static int
++run_tests (bool initially_disabled)
++{
++  /* The test relies on fatal error messages being printed to standard
++     error.  */
++  setenv ("LIBC_FATAL_STDERR_", "1", 1);
++
++  shared = support_shared_allocate (sizeof (*shared));
++  shared->initially_disabled = initially_disabled;
++  init_termination_status ();
++
++  if (initially_disabled)
++    {
++      check_for_termination ("fprintf", without_compatibility_fprintf);
++      check_for_termination ("fputc", without_compatibility_fputc);
++      check_for_termination ("fgetc", without_compatibility_fgetc);
++      check_for_termination ("fflush", without_compatibility_fflush);
++    }
++
++  check_call ("fprintf", with_compatibility_fprintf, initially_disabled);
++  check_call ("fputc", with_compatibility_fputc, initially_disabled);
++  check_call ("fgetc", with_compatibility_fgetc, initially_disabled);
++  check_call ("fflush", with_compatibility_fflush, initially_disabled);
++
++  support_shared_free (shared);
++  shared = NULL;
++
++  return 0;
++}
+diff --git a/libio/tst-vtables-interposed.c b/libio/tst-vtables-interposed.c
+new file mode 100644
+index 0000000000000000..c8f4e8c7c386af39
+--- /dev/null
++++ b/libio/tst-vtables-interposed.c
+@@ -0,0 +1,37 @@
++/* Test for libio vtables and their validation.  Enabled through interposition.
++   Copyright (C) 2018 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/>.  */
++
++/* Provide an interposed definition of the standard file handles with
++   our own vtable.  stdout/stdin/stderr will not work as a result, but
++   a succesful test does not print anything, so this is fine.  */
++static const struct _IO_jump_t jumps;
++#define _IO_file_jumps jumps
++#include "stdfiles.c"
++
++#include "tst-vtables-common.c"
++
++static int
++do_test (void)
++{
++  return run_tests (false);
++}
++
++/* Calling setvbuf in the test driver is not supported with our
++   interposed file handles.  */
++#define TEST_NO_SETVBUF
++#include <support/test-driver.c>
+diff --git a/libio/tst-vtables.c b/libio/tst-vtables.c
+new file mode 100644
+index 0000000000000000..f16acf5d23b0fff6
+--- /dev/null
++++ b/libio/tst-vtables.c
+@@ -0,0 +1,29 @@
++/* Test for libio vtables and their validation.  Initially disabled case.
++   Copyright (C) 2018 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 "libioP.h"
++
++#include "tst-vtables-common.c"
++
++static int
++do_test (void)
++{
++  return run_tests (true);
++}
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-rh1705899-6.patch b/SOURCES/glibc-rh1705899-6.patch
new file mode 100644
index 0000000..4ff1252
--- /dev/null
+++ b/SOURCES/glibc-rh1705899-6.patch
@@ -0,0 +1,24 @@
+commit 2d1c89a5d7c872a1109768f50e2508cf9a4b0348
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Wed Jun 20 09:45:19 2018 +0200
+
+    libio: Avoid ptrdiff_t overflow in IO_validate_vtable
+
+    If the candidate pointer is sufficiently far away from
+    __start___libc_IO_vtables, the result might not fit into ptrdiff_t.
+
+diff --git a/libio/libioP.h b/libio/libioP.h
+index b60244ac5fc3d908..f1576381500ffc85 100644
+--- a/libio/libioP.h
++++ b/libio/libioP.h
+@@ -957,8 +957,8 @@ IO_validate_vtable (const struct _IO_jump_t *vtable)
+   /* Fast path: The vtable pointer is within the __libc_IO_vtables
+      section.  */
+   uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables;
+-  const char *ptr = (const char *) vtable;
+-  uintptr_t offset = ptr - __start___libc_IO_vtables;
++  uintptr_t ptr = (uintptr_t) vtable;
++  uintptr_t offset = ptr - (uintptr_t) __start___libc_IO_vtables;
+   if (__glibc_unlikely (offset >= section_length))
+     /* The vtable pointer is not in the expected section.  Use the
+        slow path, which will terminate the process if necessary.  */
diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec
index f848b48..e3c3634 100644
--- a/SPECS/glibc.spec
+++ b/SPECS/glibc.spec
@@ -1,6 +1,6 @@
 %define glibcsrcdir glibc-2.17-c758a686
 %define glibcversion 2.17
-%define glibcrelease 260%{?dist}.5
+%define glibcrelease 260%{?dist}.6
 ##############################################################################
 # We support the following options:
 # --with/--without,
@@ -1422,6 +1422,12 @@ Patch2753: glibc-rh1661242-1.patch
 Patch2754: glibc-rh1661242-2.patch
 Patch2755: glibc-rh1693152-1.patch
 Patch2756: glibc-rh1693152-2.patch
+Patch2757: glibc-rh1705899-1.patch
+Patch2758: glibc-rh1705899-2.patch
+Patch2759: glibc-rh1705899-3.patch
+Patch2760: glibc-rh1705899-4.patch
+Patch2761: glibc-rh1705899-5.patch
+Patch2762: glibc-rh1705899-6.patch
 
 ##############################################################################
 #
@@ -2827,6 +2833,12 @@ package or when debugging this package.
 %patch2754 -p1
 %patch2755 -p1
 %patch2756 -p1
+%patch2757 -p1
+%patch2758 -p1
+%patch2759 -p1
+%patch2760 -p1
+%patch2761 -p1
+%patch2762 -p1
 
 ##############################################################################
 # %%prep - Additional prep required...
@@ -3990,6 +4002,9 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Fri May  3 2019 Florian Weimer <fweimer@redhat.com> - 2.17-260.6
+- Backport libio vtable validation improvements (#1705899)
+
 * Tue Apr 30 2019 Florian Weimer <fweimer@redhat.com> - 2.17-260.5
 - Use versioned Obsoletes: for nss_db (#1704593)