Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
4.4 KiB

  1. /***
  2. *seccook.c - defines and checks buffer overrun security cookie
  3. *
  4. * Copyright (c) 2000-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Defines per-module global variable __security_cookie and compiler
  8. * helper __security_check_cookie, which are used by the /GS compile
  9. * switch to detect local buffer variable overrun bugs/attacks.
  10. *
  11. * When compiling /GS, the compiler injects code to detect when a local
  12. * array variable has been overwritten, potentially overwriting the
  13. * return address (on machines like x86 where the return address is on
  14. * the stack). A local variable is allocated directly before the return
  15. * address and initialized on entering the function. When exiting the
  16. * function, the compiler inserts code to verify that the local variable
  17. * has not been modified. If it has, then an error reporting routine
  18. * is called.
  19. *
  20. * NOTE: The ATLMINCRT library includes a version of this file. If any
  21. * changes are made here, they should be duplicated in the ATL version.
  22. *
  23. *Revision History:
  24. * 01-24-00 PML Created.
  25. * 08-09-00 PML Preserve EAX on non-failure case (VS7#147203). Also
  26. * make sure failure case never returns.
  27. * 08-29-00 PML Rename handlers, add extra parameters. Move most of
  28. * system CRT version over to seclocf.c.
  29. * 09-16-00 PML Initialize global cookie earlier, and give it a nonzero
  30. * static initialization (vs7#162619).
  31. *
  32. *******************************************************************************/
  33. #include <sect_attribs.h>
  34. #include <internal.h>
  35. #include <windows.h>
  36. #include <stdlib.h>
  37. /*
  38. * The global security cookie. This name is known to the compiler.
  39. * Initialize to a garbage non-zero value just in case we have a buffer overrun
  40. * in any code that gets run before __security_init_cookie() has a chance to
  41. * initialize the cookie to the final value.
  42. */
  43. DWORD_PTR __security_cookie = 0xBB40E64E;
  44. /*
  45. * Trigger initialization of the global security cookie on program startup.
  46. * Force initialization before any #pragma init_seg() inits by using .CRT$XCAA
  47. * as the startup funcptr section.
  48. */
  49. #pragma data_seg(".CRT$XCAA")
  50. extern void __cdecl __security_init_cookie(void);
  51. static _CRTALLOC(".CRT$XCAA") _PVFV init_cookie = __security_init_cookie;
  52. #pragma data_seg()
  53. static void __cdecl report_failure(void);
  54. #if !defined(_SYSCRT) || !defined(CRTDLL)
  55. /*
  56. * The routine called if a cookie check fails.
  57. */
  58. #define REPORT_ERROR_HANDLER __security_error_handler
  59. #else
  60. /*
  61. * When using an older system CRT, use a local cookie failure reporting
  62. * routine, with a default implementation that calls __security_error_handler
  63. * if available, otherwise displays a default message box.
  64. */
  65. #define REPORT_ERROR_HANDLER __local_security_error_handler
  66. #endif
  67. extern void __cdecl REPORT_ERROR_HANDLER(int, void *);
  68. /***
  69. *__security_check_cookie(cookie) - check for buffer overrun
  70. *
  71. *Purpose:
  72. * Compiler helper. Check if a local copy of the security cookie still
  73. * matches the global value. If not, then report the fatal error.
  74. *
  75. * The actual reporting is split out into static helper report_failure,
  76. * since the cookie check routine must be minimal code that preserves
  77. * any registers used in returning the callee's result.
  78. *
  79. *Entry:
  80. * DWORD_PTR cookie - local security cookie to check
  81. *
  82. *Exit:
  83. * Returns immediately if the local cookie matches the global version.
  84. * Otherwise, calls the failure reporting handler and exits.
  85. *
  86. *Exceptions:
  87. *
  88. *******************************************************************************/
  89. #ifndef _M_IX86
  90. void __fastcall __security_check_cookie(DWORD_PTR cookie)
  91. {
  92. /* Immediately return if the local cookie is OK. */
  93. if (cookie == __security_cookie)
  94. return;
  95. /* Report the failure */
  96. report_failure();
  97. }
  98. #else
  99. void __declspec(naked) __fastcall __security_check_cookie(DWORD_PTR cookie)
  100. {
  101. /* x86 version written in asm to preserve all regs */
  102. __asm {
  103. cmp ecx, __security_cookie
  104. jne failure
  105. ret
  106. failure:
  107. jmp report_failure
  108. }
  109. }
  110. #endif
  111. static void __cdecl report_failure(void)
  112. {
  113. /* Report the failure */
  114. __try {
  115. REPORT_ERROR_HANDLER(_SECERR_BUFFER_OVERRUN, NULL);
  116. }
  117. __except (EXCEPTION_EXECUTE_HANDLER) {
  118. /* nothing */
  119. }
  120. ExitProcess(3);
  121. }