vtables.c 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /* libio vtable validation.
  2. Copyright (C) 2016-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #include <dlfcn.h>
  16. #include <libioP.h>
  17. #include <stdio.h>
  18. #include <ldsodefs.h>
  19. #ifdef SHARED
  20. void (*IO_accept_foreign_vtables) (void) attribute_hidden;
  21. /* Used to detected multiple libcs. */
  22. extern struct dl_open_hook *_dl_open_hook;
  23. libc_hidden_proto (_dl_open_hook);
  24. #else /* !SHARED */
  25. /* Used to check whether static dlopen support is needed. */
  26. # pragma weak __dlopen
  27. #endif
  28. void attribute_hidden
  29. _IO_vtable_check (void)
  30. {
  31. #ifdef SHARED
  32. /* Honor the compatibility flag. */
  33. void (*flag) (void) = atomic_load_relaxed (&IO_accept_foreign_vtables);
  34. #ifdef PTR_DEMANGLE
  35. PTR_DEMANGLE (flag);
  36. #endif
  37. if (flag == &_IO_vtable_check)
  38. return;
  39. /* In case this libc copy is in a non-default namespace, we always
  40. need to accept foreign vtables because there is always a
  41. possibility that FILE * objects are passed across the linking
  42. boundary. */
  43. {
  44. Dl_info di;
  45. struct link_map *l;
  46. if (!rtld_active ()
  47. || (_dl_addr (_IO_vtable_check, &di, &l, NULL) != 0
  48. && l->l_ns != LM_ID_BASE))
  49. return;
  50. }
  51. #else /* !SHARED */
  52. /* We cannot perform vtable validation in the static dlopen case
  53. because FILE * handles might be passed back and forth across the
  54. boundary. Therefore, we disable checking in this case. */
  55. if (__dlopen != NULL)
  56. return;
  57. #endif
  58. __libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n");
  59. }
  60. /* Some variants of libstdc++ interpose _IO_2_1_stdin_ etc. and
  61. install their own vtables directly, without calling _IO_init or
  62. other functions. Detect this by looking at the vtables values
  63. during startup, and disable vtable validation in this case. */
  64. #ifdef SHARED
  65. __attribute__ ((constructor))
  66. static void
  67. check_stdfiles_vtables (void)
  68. {
  69. if (_IO_2_1_stdin_.vtable != &_IO_file_jumps
  70. || _IO_2_1_stdout_.vtable != &_IO_file_jumps
  71. || _IO_2_1_stderr_.vtable != &_IO_file_jumps)
  72. IO_set_accept_foreign_vtables (&_IO_vtable_check);
  73. }
  74. #endif