restrict.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #include "orconfig.h"
  6. #include "lib/process/restrict.h"
  7. #include "lib/log/torlog.h"
  8. /* We only use the linux prctl for now. There is no Win32 support; this may
  9. * also work on various BSD systems and Mac OS X - send testing feedback!
  10. *
  11. * On recent Gnu/Linux kernels it is possible to create a system-wide policy
  12. * that will prevent non-root processes from attaching to other processes
  13. * unless they are the parent process; thus gdb can attach to programs that
  14. * they execute but they cannot attach to other processes running as the same
  15. * user. The system wide policy may be set with the sysctl
  16. * kernel.yama.ptrace_scope or by inspecting
  17. * /proc/sys/kernel/yama/ptrace_scope and it is 1 by default on Ubuntu 11.04.
  18. *
  19. * This ptrace scope will be ignored on Gnu/Linux for users with
  20. * CAP_SYS_PTRACE and so it is very likely that root will still be able to
  21. * attach to the Tor process.
  22. */
  23. /** Attempt to disable debugger attachment: return 1 on success, -1 on
  24. * failure, and 0 if we don't know how to try on this platform. */
  25. int
  26. tor_disable_debugger_attach(void)
  27. {
  28. int r = -1;
  29. log_debug(LD_CONFIG,
  30. "Attemping to disable debugger attachment to Tor for "
  31. "unprivileged users.");
  32. #if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) \
  33. && defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
  34. #define TRIED_TO_DISABLE
  35. r = prctl(PR_SET_DUMPABLE, 0);
  36. #elif defined(__APPLE__) && defined(PT_DENY_ATTACH)
  37. #define TRIED_TO_ATTACH
  38. r = ptrace(PT_DENY_ATTACH, 0, 0, 0);
  39. #endif /* defined(__linux__) && defined(HAVE_SYS_PRCTL_H) ... || ... */
  40. // XXX: TODO - Mac OS X has dtrace and this may be disabled.
  41. // XXX: TODO - Windows probably has something similar
  42. #ifdef TRIED_TO_DISABLE
  43. if (r == 0) {
  44. log_debug(LD_CONFIG,"Debugger attachment disabled for "
  45. "unprivileged users.");
  46. return 1;
  47. } else {
  48. log_warn(LD_CONFIG, "Unable to disable debugger attaching: %s",
  49. strerror(errno));
  50. }
  51. #endif /* defined(TRIED_TO_DISABLE) */
  52. #undef TRIED_TO_DISABLE
  53. return r;
  54. }
  55. #if defined(HAVE_MLOCKALL) && HAVE_DECL_MLOCKALL && defined(RLIMIT_MEMLOCK)
  56. #define HAVE_UNIX_MLOCKALL
  57. #endif
  58. #ifdef HAVE_UNIX_MLOCKALL
  59. /** Attempt to raise the current and max rlimit to infinity for our process.
  60. * This only needs to be done once and can probably only be done when we have
  61. * not already dropped privileges.
  62. */
  63. static int
  64. tor_set_max_memlock(void)
  65. {
  66. /* Future consideration for Windows is probably SetProcessWorkingSetSize
  67. * This is similar to setting the memory rlimit of RLIMIT_MEMLOCK
  68. * http://msdn.microsoft.com/en-us/library/ms686234(VS.85).aspx
  69. */
  70. struct rlimit limit;
  71. /* RLIM_INFINITY is -1 on some platforms. */
  72. limit.rlim_cur = RLIM_INFINITY;
  73. limit.rlim_max = RLIM_INFINITY;
  74. if (setrlimit(RLIMIT_MEMLOCK, &limit) == -1) {
  75. if (errno == EPERM) {
  76. log_warn(LD_GENERAL, "You appear to lack permissions to change memory "
  77. "limits. Are you root?");
  78. }
  79. log_warn(LD_GENERAL, "Unable to raise RLIMIT_MEMLOCK: %s",
  80. strerror(errno));
  81. return -1;
  82. }
  83. return 0;
  84. }
  85. #endif /* defined(HAVE_UNIX_MLOCKALL) */
  86. /** Attempt to lock all current and all future memory pages.
  87. * This should only be called once and while we're privileged.
  88. * Like mlockall() we return 0 when we're successful and -1 when we're not.
  89. * Unlike mlockall() we return 1 if we've already attempted to lock memory.
  90. */
  91. int
  92. tor_mlockall(void)
  93. {
  94. static int memory_lock_attempted = 0;
  95. if (memory_lock_attempted) {
  96. return 1;
  97. }
  98. memory_lock_attempted = 1;
  99. /*
  100. * Future consideration for Windows may be VirtualLock
  101. * VirtualLock appears to implement mlock() but not mlockall()
  102. *
  103. * http://msdn.microsoft.com/en-us/library/aa366895(VS.85).aspx
  104. */
  105. #ifdef HAVE_UNIX_MLOCKALL
  106. if (tor_set_max_memlock() == 0) {
  107. log_debug(LD_GENERAL, "RLIMIT_MEMLOCK is now set to RLIM_INFINITY.");
  108. }
  109. if (mlockall(MCL_CURRENT|MCL_FUTURE) == 0) {
  110. log_info(LD_GENERAL, "Insecure OS paging is effectively disabled.");
  111. return 0;
  112. } else {
  113. if (errno == ENOSYS) {
  114. /* Apple - it's 2009! I'm looking at you. Grrr. */
  115. log_notice(LD_GENERAL, "It appears that mlockall() is not available on "
  116. "your platform.");
  117. } else if (errno == EPERM) {
  118. log_notice(LD_GENERAL, "It appears that you lack the permissions to "
  119. "lock memory. Are you root?");
  120. }
  121. log_notice(LD_GENERAL, "Unable to lock all current and future memory "
  122. "pages: %s", strerror(errno));
  123. return -1;
  124. }
  125. #else /* !(defined(HAVE_UNIX_MLOCKALL)) */
  126. log_warn(LD_GENERAL, "Unable to lock memory pages. mlockall() unsupported?");
  127. return -1;
  128. #endif /* defined(HAVE_UNIX_MLOCKALL) */
  129. }