|
Packit |
6c4009 |
/* libio vtable validation.
|
|
Packit |
6c4009 |
Copyright (C) 2016-2018 Free Software Foundation, Inc.
|
|
Packit |
6c4009 |
This file is part of the GNU C Library.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
The GNU C Library is free software; you can redistribute it and/or
|
|
Packit |
6c4009 |
modify it under the terms of the GNU Lesser General Public
|
|
Packit |
6c4009 |
License as published by the Free Software Foundation; either
|
|
Packit |
6c4009 |
version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
The GNU C Library is distributed in the hope that it will be useful,
|
|
Packit |
6c4009 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
6c4009 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
6c4009 |
Lesser General Public License for more details.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
6c4009 |
License along with the GNU C Library; if not, see
|
|
Packit |
6c4009 |
<http://www.gnu.org/licenses/>. */
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#include <dlfcn.h>
|
|
Packit |
6c4009 |
#include <libioP.h>
|
|
Packit |
6c4009 |
#include <stdio.h>
|
|
Packit |
6c4009 |
#include <ldsodefs.h>
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#ifdef SHARED
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
void (*IO_accept_foreign_vtables) (void) attribute_hidden;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Used to detected multiple libcs. */
|
|
Packit |
6c4009 |
extern struct dl_open_hook *_dl_open_hook;
|
|
Packit |
6c4009 |
libc_hidden_proto (_dl_open_hook);
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#else /* !SHARED */
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Used to check whether static dlopen support is needed. */
|
|
Packit |
6c4009 |
# pragma weak __dlopen
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#endif
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
void attribute_hidden
|
|
Packit |
6c4009 |
_IO_vtable_check (void)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
#ifdef SHARED
|
|
Packit |
6c4009 |
/* Honor the compatibility flag. */
|
|
Packit |
6c4009 |
void (*flag) (void) = atomic_load_relaxed (&IO_accept_foreign_vtables);
|
|
Packit |
6c4009 |
#ifdef PTR_DEMANGLE
|
|
Packit |
6c4009 |
PTR_DEMANGLE (flag);
|
|
Packit |
6c4009 |
#endif
|
|
Packit |
6c4009 |
if (flag == &_IO_vtable_check)
|
|
Packit |
6c4009 |
return;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* In case this libc copy is in a non-default namespace, we always
|
|
Packit |
6c4009 |
need to accept foreign vtables because there is always a
|
|
Packit |
6c4009 |
possibility that FILE * objects are passed across the linking
|
|
Packit |
6c4009 |
boundary. */
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
Dl_info di;
|
|
Packit |
6c4009 |
struct link_map *l;
|
|
Packit |
6c4009 |
if (!rtld_active ()
|
|
Packit |
6c4009 |
|| (_dl_addr (_IO_vtable_check, &di, &l, NULL) != 0
|
|
Packit |
6c4009 |
&& l->l_ns != LM_ID_BASE))
|
|
Packit |
6c4009 |
return;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#else /* !SHARED */
|
|
Packit |
6c4009 |
/* We cannot perform vtable validation in the static dlopen case
|
|
Packit |
6c4009 |
because FILE * handles might be passed back and forth across the
|
|
Packit |
6c4009 |
boundary. Therefore, we disable checking in this case. */
|
|
Packit |
6c4009 |
if (__dlopen != NULL)
|
|
Packit |
6c4009 |
return;
|
|
Packit |
6c4009 |
#endif
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
__libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n");
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Some variants of libstdc++ interpose _IO_2_1_stdin_ etc. and
|
|
Packit |
6c4009 |
install their own vtables directly, without calling _IO_init or
|
|
Packit |
6c4009 |
other functions. Detect this by looking at the vtables values
|
|
Packit |
6c4009 |
during startup, and disable vtable validation in this case. */
|
|
Packit |
6c4009 |
#ifdef SHARED
|
|
Packit |
6c4009 |
__attribute__ ((constructor))
|
|
Packit |
6c4009 |
static void
|
|
Packit |
6c4009 |
check_stdfiles_vtables (void)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
if (_IO_2_1_stdin_.vtable != &_IO_file_jumps
|
|
Packit |
6c4009 |
|| _IO_2_1_stdout_.vtable != &_IO_file_jumps
|
|
Packit |
6c4009 |
|| _IO_2_1_stderr_.vtable != &_IO_file_jumps)
|
|
Packit |
6c4009 |
IO_set_accept_foreign_vtables (&_IO_vtable_check);
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
#endif
|