ssp.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * Distributed under the terms of the GNU Lesser General Public License
  3. * $Header: $
  4. *
  5. * This is a modified version of Hiroaki Etoh's stack smashing routines
  6. * implemented for glibc.
  7. *
  8. * The following people have contributed input to this code.
  9. * Ned Ludd - <solar[@]gentoo.org>
  10. * Alexander Gabert - <pappy[@]gentoo.org>
  11. * The PaX Team - <pageexec[@]freemail.hu>
  12. * Peter S. Mazinger - <ps.m[@]gmx.net>
  13. * Yoann Vandoorselaere - <yoann[@]prelude-ids.org>
  14. * Robert Connolly - <robert[@]linuxfromscratch.org>
  15. * Cory Visi <cory[@]visi.name>
  16. * Mike Frysinger <vapier[@]gentoo.org>
  17. */
  18. #if defined __SSP__ || defined __SSP_ALL__
  19. #error "file must not be compiled with stack protection enabled on it. Use -fno-stack-protector"
  20. #endif
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <signal.h>
  24. #ifdef __UCLIBC_HAS_SYSLOG__
  25. #include <sys/syslog.h>
  26. #endif
  27. #ifdef __PROPOLICE_BLOCK_SEGV__
  28. # define SSP_SIGTYPE SIGSEGV
  29. #else
  30. # define SSP_SIGTYPE SIGABRT
  31. #endif
  32. static void do_write(const char *msg)
  33. {
  34. /* could use inlined syscall here to be sure ... */
  35. return (void) write(STDERR_FILENO, msg, strlen(msg));
  36. }
  37. static void __cold do_msg(const char *msg1, const char *msg2, const char *msg3)
  38. {
  39. do_write(msg1);
  40. do_write(msg2);
  41. do_write(msg3);
  42. do_write("\n");
  43. #ifdef __UCLIBC_HAS_SYSLOG__
  44. syslog(LOG_INFO, "%s%s%s()", msg1, msg2, msg3);
  45. #endif
  46. }
  47. static void __cold attribute_noreturn
  48. #ifdef __UCLIBC_HAS_SSP_COMPAT__
  49. ssp_handler(char func[])
  50. #else
  51. ssp_handler(void)
  52. #endif
  53. {
  54. pid_t pid;
  55. static const char msg_ssd[] = "*** stack smashing detected ***: ";
  56. static const char msg_terminated[] = " terminated";
  57. #ifdef __UCLIBC_HAS_SSP_COMPAT__
  58. static const char msg_ssa[] = ": stack smashing attack in function ";
  59. #endif
  60. #ifdef __DODEBUG__
  61. struct sigaction sa;
  62. sigset_t mask;
  63. __sigfillset(&mask);
  64. __sigdelset(&mask, SSP_SIGTYPE); /* Block all signal handlers */
  65. sigprocmask(SIG_BLOCK, &mask, NULL); /* except SSP_SIGTYPE */
  66. #endif
  67. #ifdef __UCLIBC_HAS_SSP_COMPAT__
  68. if (func != NULL)
  69. do_msg(__uclibc_progname, msg_ssa, func);
  70. else
  71. #endif
  72. do_msg(msg_ssd, __uclibc_progname, msg_terminated);
  73. pid = getpid();
  74. #ifdef __DODEBUG__
  75. /* Make the default handler associated with the signal handler */
  76. memset(&sa, 0, sizeof(sa));
  77. __sigfillset(&sa.sa_mask); /* Block all signals */
  78. if (SIG_DFL) /* if it's constant zero, it's already done */
  79. sa.sa_handler = SIG_DFL;
  80. if (sigaction(SSP_SIGTYPE, &sa, NULL) == 0)
  81. (void)kill(pid, SSP_SIGTYPE);
  82. #endif
  83. (void)kill(pid, SIGKILL);
  84. /* The loop is added only to keep gcc happy. */
  85. while(1)
  86. _exit(127);
  87. }
  88. #ifdef __UCLIBC_HAS_SSP_COMPAT__
  89. void __stack_smash_handler(char func[], int damaged) attribute_noreturn __cold;
  90. void __stack_smash_handler(char func[], int damaged attribute_unused)
  91. {
  92. ssp_handler(func);
  93. }
  94. void __stack_chk_fail(void)
  95. {
  96. ssp_handler(NULL);
  97. }
  98. #else
  99. strong_alias(ssp_handler,__stack_chk_fail)
  100. #endif
  101. #ifdef __UCLIBC_HAS_FORTIFY__
  102. /* should be redone when activated to use common code above.
  103. * for now, it works without debugging support */
  104. void __chk_fail(void)
  105. {
  106. static const char msg_fail[] = "*** buffer overflow detected ***: ";
  107. static const char msg_terminated[] = " terminated";
  108. pid_t pid;
  109. do_msg(msg_fail, __uclibc_progname, msg_terminated);
  110. pid = getpid();
  111. (void)kill(pid, SIGKILL);
  112. /* The loop is added only to keep gcc happy. */
  113. while(1)
  114. _exit(127);
  115. }
  116. libc_hidden_def(__chk_fail)
  117. #endif