aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@altlinux.org>2019-02-13 01:20:51 +0000
committerAndreas K. Hüttel <dilfridge@gentoo.org>2019-07-04 00:48:15 +0200
commit95d725c0ee37ced821e24b89b59788a91479fa63 (patch)
treeac9c41290d685be16004eef6aa12936cfeb1a461
parentUse a proper C tokenizer to implement the obsolete typedefs test. (diff)
downloadglibc-gentoo/2.29-hygiene.tar.gz
glibc-gentoo/2.29-hygiene.tar.bz2
glibc-gentoo/2.29-hygiene.zip
libio: do not attempt to free wide buffers of legacy streams [BZ #24228]gentoo/2.29-hygiene
Commit a601b74d31ca086de38441d316a3dee24c866305 aka glibc-2.23~693 ("In preparation for fixing BZ#16734, fix failure in misc/tst-error1-mem when _G_HAVE_MMAP is turned off.") introduced a regression: _IO_unbuffer_all now invokes _IO_wsetb to free wide buffers of all files, including legacy standard files which are small statically allocated objects that do not have wide buffers and the _mode member, causing memory corruption. Another memory corruption in _IO_unbuffer_all happens when -1 is assigned to the _mode member of legacy standard files that do not have it. [BZ #24228] * libio/genops.c (_IO_unbuffer_all) [SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)]: Do not attempt to free wide buffers and access _IO_FILE_complete members of legacy libio streams. * libio/tst-bz24228.c: New file. * libio/tst-bz24228.map: Likewise. * libio/Makefile [build-shared] (tests): Add tst-bz24228. [build-shared] (generated): Add tst-bz24228.mtrace and tst-bz24228.check. [run-built-tests && build-shared] (tests-special): Add $(objpfx)tst-bz24228-mem.out. (LDFLAGS-tst-bz24228, tst-bz24228-ENV): New variables. ($(objpfx)tst-bz24228-mem.out): New rule. (cherry picked from commit 21cc130b78a4db9113fb6695e2b951e697662440) (cherry picked from commit 34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4) Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>
-rw-r--r--ChangeLog17
-rw-r--r--NEWS1
-rw-r--r--libio/Makefile14
-rw-r--r--libio/genops.c16
-rw-r--r--libio/tst-bz24228.c29
-rw-r--r--libio/tst-bz24228.map5
6 files changed, 77 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 306ea16ad5..20b650e026 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2019-06-20 Dmitry V. Levin <ldv@altlinux.org>
+ Florian Weimer <fweimer@redhat.com>
+
+ [BZ #24228]
+ * libio/genops.c (_IO_unbuffer_all)
+ [SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)]: Do not attempt to free wide
+ buffers and access _IO_FILE_complete members of legacy libio streams.
+ * libio/tst-bz24228.c: New file.
+ * libio/tst-bz24228.map: Likewise.
+ * libio/Makefile [build-shared] (tests): Add tst-bz24228.
+ [build-shared] (generated): Add tst-bz24228.mtrace and
+ tst-bz24228.check.
+ [run-built-tests && build-shared] (tests-special): Add
+ $(objpfx)tst-bz24228-mem.out.
+ (LDFLAGS-tst-bz24228, tst-bz24228-ENV): New variables.
+ ($(objpfx)tst-bz24228-mem.out): New rule.
+
2019-03-13 Zack Weinberg <zackw@panix.com>
* scripts/check-obsolete-constructs.py: New test script.
diff --git a/NEWS b/NEWS
index 17dcaa7b74..68d88b1036 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,7 @@ The following bugs are resolved with this release:
[24164] Systemtap probes need to use "nr" constraint on 32-bit Arm
[24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2
[24211] Use-after-free in Systemtap probe in pthread_join
+ [24228] old x86 applications that use legacy libio crash on exit
[24476] dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once)
Security related changes:
diff --git a/libio/Makefile b/libio/Makefile
index ee3a34cc3b..9626a16b01 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -73,6 +73,9 @@ ifeq (yes,$(build-shared))
# Add test-fopenloc only if shared library is enabled since it depends on
# shared localedata objects.
tests += tst-fopenloc
+# Add tst-bz24228 only if shared library is enabled since it can never meet its
+# objective with static linking because the relevant code just is not there.
+tests += tst-bz24228
endif
test-srcs = test-freopen
@@ -157,11 +160,14 @@ CFLAGS-tst_putwc.c += -DOBJPFX=\"$(objpfx)\"
CFLAGS-tst-sprintf-ub.c += -Wno-restrict
CFLAGS-tst-sprintf-chk-ub.c += -Wno-restrict
+LDFLAGS-tst-bz24228 = -Wl,--version-script=tst-bz24228.map
+
tst_wprintf2-ARGS = "Some Text"
test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace
tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace
tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace
+tst-bz24228-ENV = MALLOC_TRACE=$(objpfx)tst-bz24228.mtrace
generated += test-fmemopen.mtrace test-fmemopen.check
generated += tst-fopenloc.mtrace tst-fopenloc.check
@@ -170,6 +176,7 @@ generated += tst-bz22415.mtrace tst-bz22415.check
aux := fileops genops stdfiles stdio strops
ifeq ($(build-shared),yes)
+generated += tst-bz24228.mtrace tst-bz24228.check
aux += oldfileops oldstdfiles
endif
@@ -184,7 +191,8 @@ tests-special += $(objpfx)test-freopen.out $(objpfx)test-fmemopen-mem.out \
ifeq (yes,$(build-shared))
# Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared
# library is enabled since they depend on tst-fopenloc.out.
-tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out
+tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
+ $(objpfx)tst-bz24228-mem.out
endif
endif
@@ -236,3 +244,7 @@ $(objpfx)tst-fopenloc-mem.out: $(objpfx)tst-fopenloc.out
$(objpfx)tst-bz22415-mem.out: $(objpfx)tst-bz22415.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-bz22415.mtrace > $@; \
$(evaluate-test)
+
+$(objpfx)tst-bz24228-mem.out: $(objpfx)tst-bz24228.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-bz24228.mtrace > $@; \
+ $(evaluate-test)
diff --git a/libio/genops.c b/libio/genops.c
index 2a0d9b81df..11a15549e8 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -789,9 +789,16 @@ _IO_unbuffer_all (void)
for (fp = (FILE *) _IO_list_all; fp; fp = fp->_chain)
{
+ int legacy = 0;
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+ if (__glibc_unlikely (_IO_vtable_offset (fp) != 0))
+ legacy = 1;
+#endif
+
if (! (fp->_flags & _IO_UNBUFFERED)
/* Iff stream is un-orientated, it wasn't used. */
- && fp->_mode != 0)
+ && (legacy || fp->_mode != 0))
{
#ifdef _IO_MTSAFE_IO
int cnt;
@@ -805,7 +812,7 @@ _IO_unbuffer_all (void)
__sched_yield ();
#endif
- if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
+ if (! legacy && ! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
{
fp->_flags |= _IO_USER_BUF;
@@ -816,7 +823,7 @@ _IO_unbuffer_all (void)
_IO_SETBUF (fp, NULL, 0);
- if (fp->_mode > 0)
+ if (! legacy && fp->_mode > 0)
_IO_wsetb (fp, NULL, NULL, 0);
#ifdef _IO_MTSAFE_IO
@@ -827,7 +834,8 @@ _IO_unbuffer_all (void)
/* Make sure that never again the wide char functions can be
used. */
- fp->_mode = -1;
+ if (! legacy)
+ fp->_mode = -1;
}
#ifdef _IO_MTSAFE_IO
diff --git a/libio/tst-bz24228.c b/libio/tst-bz24228.c
new file mode 100644
index 0000000000..6a74500d47
--- /dev/null
+++ b/libio/tst-bz24228.c
@@ -0,0 +1,29 @@
+/* BZ #24228 check for memory corruption in legacy libio
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <mcheck.h>
+#include <support/test-driver.h>
+
+static int
+do_test (void)
+{
+ mtrace ();
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/libio/tst-bz24228.map b/libio/tst-bz24228.map
new file mode 100644
index 0000000000..4383e0817d
--- /dev/null
+++ b/libio/tst-bz24228.map
@@ -0,0 +1,5 @@
+# Hide the symbol from libc.so.6 to switch to the libio/oldfileops.c
+# implementation when it is available for the architecture.
+{
+ local: _IO_stdin_used;
+};