protect.cpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #include "protect.h"
  2. #include <util/generic/yexception.h>
  3. #include <util/generic/string.h>
  4. #include "yassert.h"
  5. #if defined(_unix_) || defined(_darwin_)
  6. #include <sys/mman.h>
  7. #endif
  8. #ifdef _win_
  9. #include <Windows.h>
  10. #endif
  11. static TString ModeToString(const EProtectMemory mode) {
  12. TString strMode;
  13. if (mode == PM_NONE) {
  14. return "PM_NONE";
  15. }
  16. if (mode & PM_READ) {
  17. strMode += "PM_READ|";
  18. }
  19. if (mode & PM_WRITE) {
  20. strMode += "PM_WRITE|";
  21. }
  22. if (mode & PM_EXEC) {
  23. strMode += "PM_EXEC|";
  24. }
  25. return strMode.substr(0, strMode.size() - 1);
  26. }
  27. void ProtectMemory(void* addr, const size_t length, const EProtectMemory mode) {
  28. Y_ABORT_UNLESS(!(mode & ~(PM_READ | PM_WRITE | PM_EXEC)), "Invalid memory protection flag combination. ");
  29. #if defined(_unix_) || defined(_darwin_)
  30. int mpMode = PROT_NONE;
  31. if (mode & PM_READ) {
  32. mpMode |= PROT_READ;
  33. }
  34. if (mode & PM_WRITE) {
  35. mpMode |= PROT_WRITE;
  36. }
  37. if (mode & PM_EXEC) {
  38. mpMode |= PROT_EXEC;
  39. }
  40. // some old manpages for mprotect say 'const void* addr', but that's wrong
  41. if (mprotect(addr, length, mpMode) == -1) {
  42. ythrow TSystemError() << "Memory protection failed for mode " << ModeToString(mode) << ". ";
  43. }
  44. #endif
  45. #ifdef _win_
  46. DWORD mpMode = PAGE_NOACCESS;
  47. // windows developers are not aware of bit flags :(
  48. /*
  49. * It's unclear that we should NOT fail on Windows that does not support write-only
  50. * memory protection. As we don't know, what behavior is more correct, we choose
  51. * one of them. A discussion was here: REVIEW: 39725
  52. */
  53. switch (mode.ToBaseType()) {
  54. case PM_READ:
  55. mpMode = PAGE_READONLY;
  56. break;
  57. case PM_WRITE:
  58. mpMode = PAGE_READWRITE;
  59. break; // BUG: no write-only support
  60. /*case PM_WRITE:
  61. ythrow TSystemError() << "Write-only protection mode is not supported under Windows. ";*/
  62. case PM_READ | PM_WRITE:
  63. mpMode = PAGE_READWRITE;
  64. break;
  65. case PM_EXEC:
  66. mpMode = PAGE_EXECUTE;
  67. break;
  68. case PM_READ | PM_EXEC:
  69. mpMode = PAGE_EXECUTE_READ;
  70. break;
  71. case PM_WRITE | PM_EXEC:
  72. mpMode = PAGE_EXECUTE_READWRITE;
  73. break; // BUG: no write-only support
  74. /*case PM_WRITE | PM_EXEC:
  75. ythrow TSystemError() << "Write-execute-only protection mode is not supported under Windows. ";*/
  76. case PM_READ | PM_WRITE | PM_EXEC:
  77. mpMode = PAGE_EXECUTE_READWRITE;
  78. break;
  79. }
  80. DWORD oldMode = 0;
  81. if (!VirtualProtect(addr, length, mpMode, &oldMode))
  82. ythrow TSystemError() << "Memory protection failed for mode " << ModeToString(mode) << ". ";
  83. #endif
  84. }