Bug#669154: freopen() can crash due to incomplete stream version detection
Package: libc6
Version: 2.13-27
Severity: important
Tags: upstream
The i386 version of eglibc provides two versions of fopen() and
fclose(), version GLIBC_2.0 and GLIBC2.1. However, they only provide
one version of freopen(), version GLIBC_2.0.
This shouldn't be a problem because freopen() does a version check,
found in freopen.c:
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
if (&_IO_stdin_used == NULL)
{
/* (call _IO_old_file_fopen instead of _IO_file_fopen) */
So if the current binary was built with an older version of the libc,
&_IO_stdin_used will be NULL and the older version of the builtin fopen
will be called.
However, it may happen that the file was opened with the old version
but the _IO_stdin_used symbol from the new library be present anyway.
For instance, when the application gets the address of freopen using
dlsym(). Here is a simple test case:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
static FILE * (*my_fopen) (const char *, const char *);
static FILE * (*my_freopen) (const char *, const char *, FILE *);
static int (*my_fclose) (FILE *);
int main(void)
{
my_fopen = dlsym(RTLD_NEXT, "fopen");
my_freopen = dlsym(RTLD_NEXT, "freopen");
my_fclose = dlsym(RTLD_NEXT, "fclose");
FILE * s = my_fopen("/dev/null", "w+t");
s = my_freopen("/dev/null", "w+t", s);
my_fclose(s);
return 0;
}
This program will crash on Debian i386, because 1) my_freopen()
will call _IO_file_fopen() from the new libio, but 2) the symbol for
fclose() will be "fopen@GLIBC_2.0" from the old libio, causing a memory
corruption.
There might be a way for freopen() to better check which version of
libio was used. Maybe upstream has an opinion on this. Or maybe they
believe it's not a problem; however, note that there is no way to use
dlsym() with a libc6 symbol and ensure we get a version compatible with
the current running binary. There is dlvsym() but it requires to know
the version string beforehands.
I hope I'm being clear enough!
-- System Information:
Debian Release: wheezy/sid
APT prefers stable
APT policy: (500, 'stable')
Architecture: amd64 (x86_64)
Kernel: Linux 3.2.0-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Versions of packages libc6 depends on:
ii libc-bin 2.13-27
ii libgcc1 1:4.7.0-2
libc6 recommends no packages.
Versions of packages libc6 suggests:
ii debconf [debconf-2.0] 1.5.42
ii glibc-doc <none>
ii locales 2.13-27
-- debconf information:
glibc/upgrade: true
glibc/disable-screensaver:
glibc/restart-failed:
* glibc/restart-services: postfix cups cron atd
libraries/restart-without-asking: false
Reply to: