@@ -116,6 +116,12 @@ will be used, and CFLAGS sets optimization options for the compiler.
program linked statically with the NSS libraries cannot be
dynamically reconfigured to use a different name database.
+'--disable-libio-compatibility'
+ Instead of remaining compatibile with pre-libstdc++.so.6 binaries
+ that may be sharing the vtable (i.e. roughly pre-2007 binaries),
+ compile libio with PTR_MANGLE of the FILE vtable, as a security
+ flaw mitigation.
+
'--without-tls'
By default the C library is built with support for thread-local
storage if the used tools support it. By using '--without-tls'
@@ -161,6 +161,9 @@
/* Define if the dynamic linker should consult an ld.so.cache file. */
#undef USE_LDCONFIG
+/* Define if we should remain compatibile with pre-libstdc++.so.6 libio. */
+#undef USE_COMPAT_LIBIO
+
/* Define to 1 if STT_GNU_IFUNC support actually works. */
#define HAVE_IFUNC 0
@@ -761,6 +761,7 @@ enable_add_ons
enable_hidden_plt
enable_bind_now
enable_static_nss
+enable_libio_compatibility
enable_force_install
enable_maintainer_mode
enable_kernel
@@ -1422,6 +1423,9 @@ Optional Features:
--disable-hidden-plt do not hide internal function calls to avoid PLT
--enable-bind-now disable lazy relocations in DSOs
--enable-static-nss build static NSS modules [default=no]
+ --disable-libio-compatibility
+ enable PTR_MANGLE for FILE vtable (breaks
+ pre-libstdc++.so.6 binaries)
--disable-force-install don't force installation of files from this package,
even if they are older than the installed files
--enable-maintainer-mode
@@ -3430,6 +3434,18 @@ if test x"$static_nss" = xyes || test x"$shared" = xno; then
fi
+# Check whether --enable-libio-compatibility was given.
+if test "${enable_libio_compatibility+set}" = set; then :
+ enableval=$enable_libio_compatibility; libio_compatibility=$enableval
+else
+ libio_compatibility=yes
+fi
+
+if test "$libio_compatibility" = yes; then
+ $as_echo "#define USE_COMPAT_LIBIO 1" >>confdefs.h
+
+fi
+
# Check whether --enable-force-install was given.
if test "${enable_force_install+set}" = set; then :
enableval=$enable_force_install; force_install=$enableval
@@ -245,6 +245,17 @@ if test x"$static_nss" = xyes || test x"$shared" = xno; then
AC_DEFINE(DO_STATIC_NSS)
fi
+dnl To enable PTR_MANGLE on the FILE vtable, we break compatibility with
+dnl pre-libstdc++.so.6 libio.
+AC_ARG_ENABLE([libio-compatibility],
+ AC_HELP_STRING([--disable-libio-compatibility],
+ [enable PTR_MANGLE for FILE vtable (breaks pre-libstdc++.so.6 binaries)]),
+ [libio_compatibility=$enableval],
+ [libio_compatibility=yes])
+if test "$libio_compatibility" = yes; then
+ AC_DEFINE(USE_COMPAT_LIBIO)
+fi
+
AC_ARG_ENABLE([force-install],
AC_HELP_STRING([--disable-force-install],
[don't force installation of files from this package, even if they are older than the installed files]),
@@ -54,7 +54,7 @@ __obstack_vprintf_chk (struct obstack *obstack, int flags, const char *format,
#endif
_IO_no_init (&new_f.ofile.file.file, _IO_USER_LOCK, -1, NULL, NULL);
- _IO_JUMPS (&new_f.ofile.file) = &_IO_obstack_jumps;
+ _IO_JUMPS_SET (&new_f.ofile.file, &_IO_obstack_jumps);
room = obstack_room (obstack);
size = obstack_object_size (obstack) + room;
if (size == 0)
@@ -52,7 +52,7 @@ __vasprintf_chk (char **result_ptr, int flags, const char *format,
sf._sbf._f._lock = NULL;
#endif
_IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
- _IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
+ _IO_JUMPS_SET (&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;
@@ -38,7 +38,7 @@ __vdprintf_chk (int d, int flags, const char *format, va_list arg)
tmpfil.file._lock = NULL;
#endif
_IO_no_init (&tmpfil.file, _IO_USER_LOCK, 0, &wd, &_IO_wfile_jumps);
- _IO_JUMPS (&tmpfil) = &_IO_file_jumps;
+ _IO_JUMPS_SET (&tmpfil, &_IO_file_jumps);
_IO_file_init (&tmpfil);
#if !_IO_UNIFIED_JUMPTABLES
tmpfil.vtable = NULL;
@@ -51,7 +51,7 @@ ___vsnprintf_chk (char *s, size_t maxlen, int flags, size_t slen,
}
_IO_no_init (&sf.f._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
- _IO_JUMPS (&sf.f._sbf) = &_IO_strn_jumps;
+ _IO_JUMPS_SET (&sf.f._sbf, &_IO_strn_jumps);
s[0] = '\0';
/* For flags > 0 (i.e. __USE_FORTIFY_LEVEL > 1) request that %n
@@ -71,7 +71,7 @@ ___vsprintf_chk (char *s, int flags, size_t slen, const char *format,
__chk_fail ();
_IO_no_init (&f._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
- _IO_JUMPS (&f._sbf) = &_IO_str_chk_jumps;
+ _IO_JUMPS_SET (&f._sbf, &_IO_str_chk_jumps);
s[0] = '\0';
_IO_str_init_static_internal (&f, s, slen - 1, s);
@@ -414,7 +414,7 @@ _IO_new_file_fopen (_IO_FILE *fp, const char *filename, const char *mode,
&result->_wide_data->_IO_state;
/* From now on use the wide character callback functions. */
- _IO_JUMPS_FILE_plus (fp) = fp->_wide_data->_wide_vtable;
+ _IO_JUMPS_FILE_plus_SET (fp, _IO_WIDE_JUMPS_FUNC (fp));
/* Set the mode now. */
result->_mode = 1;
@@ -466,8 +466,8 @@ _IO_file_setbuf_mmap (_IO_FILE *fp, char *p, _IO_ssize_t len)
_IO_FILE *result;
/* Change the function table. */
- _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps;
- fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_file_jumps);
+ _IO_WIDE_JUMPS_SET (fp, &_IO_wfile_jumps);
/* And perform the normal operation. */
result = _IO_new_file_setbuf (fp, p, len);
@@ -475,8 +475,8 @@ _IO_file_setbuf_mmap (_IO_FILE *fp, char *p, _IO_ssize_t len)
/* If the call failed, restore to using mmap. */
if (result == NULL)
{
- _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps_mmap;
- fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_file_jumps_mmap);
+ _IO_WIDE_JUMPS_SET (fp, &_IO_wfile_jumps_mmap);
}
return result;
@@ -703,10 +703,10 @@ mmap_remap_check (_IO_FILE *fp)
fp->_IO_buf_base = fp->_IO_buf_end = NULL;
_IO_setg (fp, NULL, NULL, NULL);
if (fp->_mode <= 0)
- _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_file_jumps);
else
- _IO_JUMPS_FILE_plus (fp) = &_IO_wfile_jumps;
- fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_wfile_jumps);
+ _IO_WIDE_JUMPS_SET (fp, &_IO_wfile_jumps);
return 1;
}
@@ -773,10 +773,10 @@ decide_maybe_mmap (_IO_FILE *fp)
fp->_offset = st.st_size;
if (fp->_mode <= 0)
- _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps_mmap;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_file_jumps_mmap);
else
- _IO_JUMPS_FILE_plus (fp) = &_IO_wfile_jumps_mmap;
- fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_wfile_jumps_mmap);
+ _IO_WIDE_JUMPS_SET (fp, &_IO_wfile_jumps_mmap);
return;
}
@@ -786,10 +786,10 @@ decide_maybe_mmap (_IO_FILE *fp)
/* We couldn't use mmap, so revert to the vanilla file operations. */
if (fp->_mode <= 0)
- _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_file_jumps);
else
- _IO_JUMPS_FILE_plus (fp) = &_IO_wfile_jumps;
- fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_wfile_jumps);
+ _IO_WIDE_JUMPS_SET (fp, &_IO_wfile_jumps);
}
int
@@ -56,16 +56,16 @@ freopen (const char *filename, const char *mode, FILE *fp)
to the old libio may be passed into shared C library and wind
up here. */
_IO_old_file_close_it (fp);
- _IO_JUMPS_FILE_plus (fp) = &_IO_old_file_jumps;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_old_file_jumps);
result = _IO_old_file_fopen (fp, gfilename, mode);
}
else
#endif
{
_IO_file_close_it (fp);
- _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_file_jumps);
if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL)
- fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
+ _IO_WIDE_JUMPS_SET (fp, &_IO_wfile_jumps);
result = _IO_file_fopen (fp, gfilename, mode, 1);
if (result != NULL)
result = __fopen_maybe_mmap (result);
@@ -47,9 +47,9 @@ freopen64 (const char *filename, const char *mode, FILE *fp)
? fd_to_filename (fd) : filename);
fp->_flags2 |= _IO_FLAGS2_NOCLOSE;
_IO_file_close_it (fp);
- _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_file_jumps);
if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL)
- fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
+ _IO_WIDE_JUMPS_SET (fp, &_IO_wfile_jumps);
result = _IO_file_fopen (fp, gfilename, mode, 0);
fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
if (result != NULL)
@@ -615,7 +615,7 @@ _IO_no_init (_IO_FILE *fp, int flags, int orientation,
fp->_wide_data->_IO_backup_base = NULL;
fp->_wide_data->_IO_save_end = NULL;
- fp->_wide_data->_wide_vtable = jmp;
+ _IO_WIDE_JUMPS_SET (fp, jmp);
}
else
/* Cause predictable crash when a wide function is called on a byte
@@ -148,11 +148,11 @@ _IO_new_fdopen (int fd, const char *mode)
? &_IO_wfile_jumps_maybe_mmap :
#endif
&_IO_wfile_jumps);
- _IO_JUMPS (&new_f->fp) =
+ _IO_JUMPS_SET (&new_f->fp,
#ifdef _G_HAVE_MMAP
(use_mmap && (read_write & _IO_NO_WRITES)) ? &_IO_file_jumps_maybe_mmap :
#endif
- &_IO_file_jumps;
+ &_IO_file_jumps);
_IO_file_init (&new_f->fp);
#if !_IO_UNIFIED_JUMPTABLES
new_f->fp.vtable = NULL;
@@ -46,10 +46,10 @@ __fopen_maybe_mmap (_IO_FILE *fp)
vanilla file operations and reset the jump table accordingly. */
if (fp->_mode <= 0)
- _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps_maybe_mmap;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_file_jumps_maybe_mmap);
else
- _IO_JUMPS_FILE_plus (fp) = &_IO_wfile_jumps_maybe_mmap;
- fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_maybe_mmap;
+ _IO_JUMPS_FILE_plus_SET (fp, &_IO_wfile_jumps_maybe_mmap);
+ _IO_WIDE_JUMPS_SET (fp, &_IO_wfile_jumps_maybe_mmap);
}
#endif
return fp;
@@ -78,7 +78,7 @@ __fopen_internal (const char *filename, const char *mode, int is32)
#else
_IO_no_init (&new_f->fp.file, 1, 0, NULL, NULL);
#endif
- _IO_JUMPS (&new_f->fp) = &_IO_file_jumps;
+ _IO_JUMPS_SET (&new_f->fp, &_IO_file_jumps);
_IO_file_init (&new_f->fp);
#if !_IO_UNIFIED_JUMPTABLES
new_f->fp.vtable = NULL;
@@ -131,7 +131,7 @@ _IO_cookie_init (struct _IO_cookie_file *cfile, int read_write,
void *cookie, _IO_cookie_io_functions_t io_functions)
{
_IO_init (&cfile->__fp.file, 0);
- _IO_JUMPS (&cfile->__fp) = &_IO_cookie_jumps;
+ _IO_JUMPS_SET (&cfile->__fp, &_IO_cookie_jumps);
cfile->__cookie = cookie;
cfile->__io_functions = io_functions;
@@ -249,7 +249,7 @@ _IO_old_fopencookie (void *cookie, const char *mode,
ret = _IO_fopencookie (cookie, mode, io_functions);
if (ret != NULL)
- _IO_JUMPS_FILE_plus (ret) = &_IO_old_cookie_jumps;
+ _IO_JUMPS_FILE_plus_SET (ret, &_IO_old_cookie_jumps);
return ret;
}
@@ -182,7 +182,7 @@ _IO_fwide (_IO_FILE *fp, int mode)
#endif
/* From now on use the wide character callback functions. */
- _IO_JUMPS_FILE_plus (fp) = fp->_wide_data->_wide_vtable;
+ _IO_JUMPS_FILE_plus_SET (fp, _IO_WIDE_JUMPS_FUNC (fp));
}
/* Set the mode now. */
@@ -288,7 +288,7 @@ _IO_new_popen (const char *command, const char *mode)
#endif
fp = &new_f->fpx.file.file;
_IO_init (fp, 0);
- _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
+ _IO_JUMPS_SET (&new_f->fpx.file, &_IO_proc_jumps);
_IO_new_file_init (&new_f->fpx.file);
#if !_IO_UNIFIED_JUMPTABLES
new_f->fpx.file.vtable = NULL;
@@ -38,7 +38,7 @@ _IO_vdprintf (int d, const char *format, _IO_va_list arg)
tmpfil.file._lock = NULL;
#endif
_IO_no_init (&tmpfil.file, _IO_USER_LOCK, 0, &wd, &_IO_wfile_jumps);
- _IO_JUMPS (&tmpfil) = &_IO_file_jumps;
+ _IO_JUMPS_SET (&tmpfil, &_IO_file_jumps);
_IO_file_init (&tmpfil);
#if !_IO_UNIFIED_JUMPTABLES
tmpfil.vtable = NULL;
@@ -37,7 +37,7 @@ __IO_vsprintf (char *string, const char *format, _IO_va_list args)
sf._sbf._f._lock = NULL;
#endif
_IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
- _IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
+ _IO_JUMPS_SET (&sf._sbf, &_IO_str_jumps);
_IO_str_init_static_internal (&sf, string, -1, string);
ret = _IO_vfprintf (&sf._sbf._f, format, args);
_IO_putc_unlocked ('\0', &sf._sbf._f);
@@ -36,7 +36,7 @@ _IO_vsscanf (const char *string, const char *format, _IO_va_list args)
sf._sbf._f._lock = NULL;
#endif
_IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
- _IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
+ _IO_JUMPS_SET (&sf._sbf, &_IO_str_jumps);
_IO_str_init_static_internal (&sf, (char*)string, 0, NULL);
ret = _IO_vfscanf (&sf._sbf._f, format, args, NULL);
return ret;
@@ -70,17 +70,16 @@ extern "C" {
/* THE JUMPTABLE FUNCTIONS.
- * The _IO_FILE type is used to implement the FILE type in GNU libc,
- * as well as the streambuf class in GNU iostreams for C++.
- * These are all the same, just used differently.
- * An _IO_FILE (or FILE) object is allows followed by a pointer to
- * a jump table (of pointers to functions). The pointer is accessed
- * with the _IO_JUMPS macro. The jump table has an eccentric format,
- * so as to be compatible with the layout of a C++ virtual function table.
- * (as implemented by g++). When a pointer to a streambuf object is
- * coerced to an (_IO_FILE*), then _IO_JUMPS on the result just
- * happens to point to the virtual function table of the streambuf.
- * Thus the _IO_JUMPS function table used for C stdio/libio does
+ * The _IO_FILE type is used to implement the FILE type in GNU libc, as well
+ * as the streambuf class in GNU iostreams for C++. These are all the same,
+ * just used differently. An _IO_FILE (or FILE) object is always followed by
+ * a pointer to a jump table (of pointers to functions). The pointer is
+ * accessed with the _IO_JUMPS_SET and _IO_JUMPS_FUNC macros. The jump table
+ * has an eccentric format, so as to be compatible with the layout of a C++
+ * virtual function table (as implemented by g++). When a pointer to a
+ * streambuf object is coerced to an (_IO_FILE*), then _IO_JUMPS on the
+ * result just happens to point to the virtual function table of the
+ * streambuf. Thus the _IO_JUMPS function table used for C stdio/libio does
* double duty as the virtual function table for C++ streambuf.
*
* The entries in the _IO_JUMPS function table (and hence also the
@@ -106,6 +105,17 @@ extern "C" {
# define _IO_JUMPS_OFFSET 0
#endif
+static inline void
+_IO_mangle_vtable (const struct _IO_jump_t **vtable,
+ const struct _IO_jump_t *table)
+{
+ struct _IO_jump_t *ptr = (struct _IO_jump_t *)table;
+#ifndef USE_COMPAT_LIBIO
+ PTR_MANGLE (ptr);
+#endif
+ *vtable = ptr;
+}
+
/* Type of MEMBER in struct type TYPE. */
#define _IO_MEMBER_TYPE(TYPE, MEMBER) __typeof__ (((TYPE){}).MEMBER)
@@ -115,24 +125,43 @@ extern "C" {
(*(_IO_MEMBER_TYPE (TYPE, MEMBER) *)(((char *) (THIS)) \
+ offsetof(TYPE, MEMBER)))
-#define _IO_JUMPS(THIS) (THIS)->vtable
-#define _IO_JUMPS_FILE_plus(THIS) \
+#define _IO_JUMPS_RAW(THIS) (THIS)->vtable
+#define _IO_JUMPS_SET(THIS, TABLE) \
+ _IO_mangle_vtable (&_IO_JUMPS_RAW (THIS), (TABLE))
+
+#define _IO_JUMPS_FILE_plus_RAW(THIS) \
_IO_CAST_FIELD_ACCESS ((THIS), struct _IO_FILE_plus, vtable)
-#define _IO_WIDE_JUMPS(THIS) \
+#define _IO_JUMPS_FILE_plus_SET(THIS, TABLE) \
+ _IO_mangle_vtable (&_IO_JUMPS_FILE_plus_RAW (THIS), (TABLE))
+
+#define _IO_WIDE_JUMPS_RAW(THIS) \
_IO_CAST_FIELD_ACCESS ((THIS), struct _IO_FILE, _wide_data)->_wide_vtable
+#define _IO_WIDE_JUMPS_SET(THIS, TABLE) \
+ _IO_mangle_vtable (&_IO_WIDE_JUMPS_RAW (THIS), (TABLE))
+
#define _IO_CHECK_WIDE(THIS) \
(_IO_CAST_FIELD_ACCESS ((THIS), struct _IO_FILE, _wide_data) != NULL)
+static inline const struct _IO_jump_t *
+_IO_demangle_vtable (const struct _IO_jump_t *vtable)
+{
+ struct _IO_jump_t *ptr = (struct _IO_jump_t *)vtable;
+#ifndef USE_COMPAT_LIBIO
+ PTR_DEMANGLE (ptr);
+#endif
+ return (const struct _IO_jump_t *)ptr;
+}
+
#if _IO_JUMPS_OFFSET
-# define _IO_JUMPS_FUNC(THIS) \
- (*(struct _IO_jump_t **) ((void *) &_IO_JUMPS_FILE_plus (THIS) \
- + (THIS)->_vtable_offset))
+# define _IO_JUMPS_FUNC(THIS) _IO_demangle_vtable (\
+ (*(struct _IO_jump_t **) ((void *) &_IO_JUMPS_FILE_plus_RAW (THIS) \
+ + (THIS)->_vtable_offset)))
# define _IO_vtable_offset(THIS) (THIS)->_vtable_offset
#else
-# define _IO_JUMPS_FUNC(THIS) _IO_JUMPS_FILE_plus (THIS)
+# define _IO_JUMPS_FUNC(THIS) _IO_demangle_vtable (_IO_JUMPS_FILE_plus_RAW (THIS))
# define _IO_vtable_offset(THIS) 0
#endif
-#define _IO_WIDE_JUMPS_FUNC(THIS) _IO_WIDE_JUMPS(THIS)
+#define _IO_WIDE_JUMPS_FUNC(THIS) _IO_demangle_vtable (_IO_WIDE_JUMPS_RAW (THIS))
#define JUMP_FIELD(TYPE, NAME) TYPE NAME
#define JUMP0(FUNC, THIS) (_IO_JUMPS_FUNC(THIS)->FUNC) (THIS)
#define JUMP1(FUNC, THIS, X1) (_IO_JUMPS_FUNC(THIS)->FUNC) (THIS, X1)
@@ -87,7 +87,7 @@ __open_memstream (char **bufloc, _IO_size_t *sizeloc)
return NULL;
}
_IO_init (&new_f->fp._sf._sbf._f, 0);
- _IO_JUMPS_FILE_plus (&new_f->fp._sf._sbf) = &_IO_mem_jumps;
+ _IO_JUMPS_FILE_plus_SET (&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;
@@ -132,7 +132,7 @@ _IO_obstack_vprintf (struct obstack *obstack, const char *format, va_list args)
#endif
_IO_no_init (&new_f.ofile.file.file, _IO_USER_LOCK, -1, NULL, NULL);
- _IO_JUMPS (&new_f.ofile.file) = &_IO_obstack_jumps;
+ _IO_JUMPS_SET (&new_f.ofile.file, &_IO_obstack_jumps);
room = obstack_room (obstack);
size = obstack_object_size (obstack) + room;
if (size == 0)
@@ -111,7 +111,7 @@ _IO_old_fdopen (int fd, const char *mode)
new_f->fp.file._file._lock = &new_f->lock;
#endif
_IO_old_init (&new_f->fp.file._file, 0);
- _IO_JUMPS_FILE_plus (&new_f->fp) = &_IO_old_file_jumps;
+ _IO_JUMPS_FILE_plus_SET (&new_f->fp, &_IO_old_file_jumps);
_IO_old_file_init ((struct _IO_FILE_plus *) &new_f->fp);
#if !_IO_UNIFIED_JUMPTABLES
new_f->fp.vtable = NULL;
@@ -50,7 +50,7 @@ _IO_old_fopen (const char *filename, const char *mode)
new_f->fp.file._file._lock = &new_f->lock;
#endif
_IO_old_init (&new_f->fp.file._file, 0);
- _IO_JUMPS_FILE_plus (&new_f->fp) = &_IO_old_file_jumps;
+ _IO_JUMPS_FILE_plus_SET (&new_f->fp, &_IO_old_file_jumps);
_IO_old_file_init ((struct _IO_FILE_plus *) &new_f->fp);
#if !_IO_UNIFIED_JUMPTABLES
new_f->fp.vtable = NULL;
@@ -210,7 +210,7 @@ _IO_old_popen (const char *command, const char *mode)
#endif
fp = &new_f->fpx.file.file._file;
_IO_old_init (fp, 0);
- _IO_JUMPS_FILE_plus (&new_f->fpx.file) = &_IO_old_proc_jumps;
+ _IO_JUMPS_FILE_plus_SET (&new_f->fpx.file, &_IO_old_proc_jumps);
_IO_old_file_init ((struct _IO_FILE_plus *) &new_f->fpx.file);
#if !_IO_UNIFIED_JUMPTABLES
new_f->fpx.file.vtable = NULL;
@@ -51,7 +51,7 @@ _IO_vasprintf (char **result_ptr, const char *format, _IO_va_list args)
sf._sbf._f._lock = NULL;
#endif
_IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
- _IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
+ _IO_JUMPS_SET (&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;
@@ -108,7 +108,7 @@ _IO_vsnprintf (char *string, _IO_size_t maxlen, const char *format,
}
_IO_no_init (&sf.f._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
- _IO_JUMPS (&sf.f._sbf) = &_IO_strn_jumps;
+ _IO_JUMPS_SET (&sf.f._sbf, &_IO_strn_jumps);
string[0] = '\0';
_IO_str_init_static_internal (&sf.f, string, maxlen - 1, string);
ret = _IO_vfprintf (&sf.f._sbf._f, format, args);
@@ -146,6 +146,11 @@ This is not recommended because it defeats the purpose of NSS; a program
linked statically with the NSS libraries cannot be dynamically
reconfigured to use a different name database.
+@item --disable-libio-compatibility
+Instead of remaining compatibile with pre-@file{libstdc++.so.6} binaries
+that may be sharing the vtable (i.e. roughly pre-2007 binaries), compile
+libio with PTR_MANGLE of the FILE vtable, as a security flaw mitigation.
+
@item --without-tls
By default the C library is built with support for thread-local storage
if the used tools support it. By using @samp{--without-tls} this can be
@@ -16,7 +16,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include "libioP.h"
+
#include <string.h>
+#include <stdio.h>
+#include <sysdep.h>
#include <libc-internal.h>
char *__progname_full = (char *) "";
@@ -37,4 +41,15 @@ __init_misc (int argc, char **argv, char **envp)
__progname = p + 1;
__progname_full = argv[0];
}
+
+#ifndef USE_COMPAT_LIBIO
+ PTR_MANGLE (_IO_JUMPS_FILE_plus_RAW (stdin));
+ PTR_MANGLE (_IO_WIDE_JUMPS_RAW (stdin));
+
+ PTR_MANGLE (_IO_JUMPS_FILE_plus_RAW (stdout));
+ PTR_MANGLE (_IO_WIDE_JUMPS_RAW (stdout));
+
+ PTR_MANGLE (_IO_JUMPS_FILE_plus_RAW (stderr));
+ PTR_MANGLE (_IO_WIDE_JUMPS_RAW (stderr));
+#endif
}
@@ -37,7 +37,7 @@ __isoc99_vsscanf (const char *string, const char *format, _IO_va_list args)
sf._sbf._f._lock = NULL;
#endif
_IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
- _IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
+ _IO_JUMPS_SET (&sf._sbf, &_IO_str_jumps);
_IO_str_init_static_internal (&sf, (char*)string, 0, NULL);
sf._sbf._f._flags2 |= _IO_FLAGS2_SCANF_STD;
ret = _IO_vfscanf (&sf._sbf._f, format, args, NULL);
@@ -2318,7 +2318,7 @@ buffered_vfprintf (_IO_FILE *s, const CHAR_T *format,
hp->_lock = NULL;
#endif
hp->_flags2 = s->_flags2;
- _IO_JUMPS (&helper._f) = (struct _IO_jump_t *) &_IO_helper_jumps;
+ _IO_JUMPS_SET (&helper._f, (struct _IO_jump_t *) &_IO_helper_jumps);
/* Now print to helper instead. */
#ifndef COMPILE_WPRINTF
@@ -513,7 +513,7 @@ __vstrfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format,
f._sbf._f._lock = NULL;
#endif
_IO_init (&f._sbf._f, 0);
- _IO_JUMPS (&f._sbf) = &_IO_str_jumps;
+ _IO_JUMPS_SET (&f._sbf, &_IO_str_jumps);
_IO_str_init_static_internal (&f, dest, (s + maxsize) - dest, dest);
/* We clear the last available byte so we can find out whether
the numeric representation is too long. */