public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* Future of libio vtable compatibility
@ 2018-06-15  7:50 Florian Weimer
  2018-06-18 16:07 ` Carlos O'Donell
  0 siblings, 1 reply; 14+ messages in thread
From: Florian Weimer @ 2018-06-15  7:50 UTC (permalink / raw)
  To: libc-alpha

The libio implementation of streams (behind FILE *) was originally
written so that it was ABI-compatible with the C++ implementation of
filebuf and streambuf in GCC, so that the implementation could be
shared, and C functions printf etc. could write directly C++ streams.

This did not work out as planned because the C++ ABI changed a couple
of times since then (until settling on the Itanium ABI).

If you remember, we put in some complicated code to detect when
binaries brought along their own vtables, and disable the hardening
(so that exploit writers could no longer trivially inject code).  This
worked in some cases, such as historic APT versions (which I verified
at the time).

Now some other unsupported cases have surfaced.  It's quite difficult
to get hold of binaries which fail, but here is one documented case
with binaries still available (through snapshot.debian.org):

  https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=861116

I was able to get run yadex to run to the point of the crash on Debian
unstable.  The crash happens here:

(gdb) where
#0  0xf7fd4c89 in __kernel_vsyscall ()
#1  0xf7b885b2 in __libc_signal_restore_set (set=0xffffcd1c) at ../sysdeps/unix/sysv/linux/nptl-signals.h:80
#2  __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:48
#3  0xf7b899d1 in __GI_abort () at abort.c:79
#4  0xf7bca273 in __libc_message (action=(do_abort | do_backtrace), fmt=<optimized out>) at ../sysdeps/posix/libc_fatal.c:181
#5  0xf7bca30c in __GI___libc_fatal (message=0xf7cdac38 "Fatal error: glibc detected an invalid stdio handle\n") at ../sysdeps/posix/libc_fatal.c:191
#6  0xf7bcacda in _IO_vtable_check () at vtables.c:72
#7  0xf7ba3c7b in IO_validate_vtable (vtable=0xf7e6c720 <filebuf virtual table>) at ../libio/libioP.h:876
#8  _IO_vfprintf_internal (s=0xf7e6c480 <_IO_2_1_stdout_>, format=0x808c040 "%s\nThis program is derived from DEU 5.21 by Rapha\353l Quinet and Brendon Wyber.\n", ap=0xffffd584 "\200\254\t\b\001") at vfprintf.c:1328
#9  0xf7babc66 in __printf (format=0x808c040 "%s\nThis program is derived from DEU 5.21 by Rapha\353l Quinet and Brendon Wyber.\n") at printf.c:33
#10 0x0807b1a9 in ?? ()
#11 0xf7b73e81 in __libc_start_main (main=0x807aff0, argc=1, argv=0xffffd644, init=0x8049dec <_init>, fini=0x8081844 <_fini>, rtld_fini=0xf7fe59a0 <_dl_fini>, stack_end=0xffffd63c) at ../csu/libc-start.c:310
#12 0x0804a671 in ?? ()

glibc's printf uses this stdout value to call _IO_vfprintf_internal:

(gdb) info symb 0xf7e6c480
_IO_2_1_stdout_ in section .data of /usr/lib/libstdc++-libc6.2-2.so.3

What happened here is that this version of libstdc++ has interposed
_IO_2_1_stdout_, and it supplied its own vtable:

(gdb) info symb _IO_2_1_stdout_.vtable 
filebuf virtual table in section .data of /usr/lib/libstdc++-libc6.2-2.so.3

This is also visibile in LD_DEBUG=bindings logging:

     21425:  binding file /lib/i386-linux-gnu/libc.so.6 [0] to /usr/lib/libstdc++-libc6.2-2.so.3 [0]: normal symbol `_IO_2_1_stderr_' [GLIBC_2.1]
     21425:  binding file /lib/i386-linux-gnu/libc.so.6 [0] to /usr/lib/libstdc++-libc6.2-2.so.3 [0]: normal symbol `_IO_2_1_stdout_' [GLIBC_2.1]
     21425:  binding file /lib/i386-linux-gnu/libc.so.6 [0] to /usr/lib/libstdc++-libc6.2-2.so.3 [0]: normal symbol `_IO_2_1_stdin_' [GLIBC_2.1]

Needless to say, I did not expect that.

In order to fix that, we could accept any vtable if it is loaded from
the symbols _IO_2_1_stderr_, _IO_2_1_stdout_, _IO_2_1_stdin_.  If we
do that after a vtable verification failure, there should not be any
performance impact for current binaries, on top of the overhead for
vtable verification.

But I do wonder if it is worth the effort to make this change.  It has
been rather difficult to get hold of old binaries which are currently
broken, and I don't know if the sketched workaround addresses the
issues users have encountered.

Should we instead remove the compatibility logic altogether?

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

end of thread, other threads:[~2018-06-19 19:20 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-15  7:50 Future of libio vtable compatibility Florian Weimer
2018-06-18 16:07 ` Carlos O'Donell
2018-06-18 17:15   ` Florian Weimer
2018-06-18 17:41     ` Zack Weinberg
2018-06-18 18:25       ` Adhemerval Zanella
2018-06-18 19:08       ` Florian Weimer
2018-06-18 19:26         ` Zack Weinberg
2018-06-18 19:22     ` Carlos O'Donell
2018-06-18 20:18       ` Florian Weimer
2018-06-18 20:28         ` Carlos O'Donell
     [not found]           ` <878t7bu834.fsf@mid.deneb.enyo.de>
     [not found]             ` <80e0f086-a966-618d-7b27-1f42a7b9a5c9@redhat.com>
2018-06-19 19:11               ` Florian Weimer
2018-06-19 19:20                 ` Carlos O'Donell
2018-06-19 12:18       ` Joseph Myers
2018-06-19 12:39         ` Adhemerval Zanella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).