aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--doc/tor.1.in13
-rw-r--r--src/common/compat.c99
-rw-r--r--src/common/compat.h2
-rw-r--r--src/config/torrc.complete.in3
-rw-r--r--src/or/config.c18
-rw-r--r--src/or/or.h3
7 files changed, 148 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 6d9535f03..0109ff505 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -14,6 +14,16 @@ Changes in version 0.2.2.6-alpha - 2009-10-??
algorithms for signatures and resource selection. Newer formats are
signed with SHA256, with a possibility for moving to a better hash
algorithm in the future.
+ - New DisableAllSwap option. If set to 1, Tor will attempt to lock all
+ current and future memory pages. On supported platforms, this should
+ effectively disable any and all attempts to page out memory. Under the
+ hood, DisableAllSwap uses mlockall() on unix-like platforms. Windows is
+ currently unsupported. We believe that this feature works on modern
+ Gnu/Linux distributions. Mac OS X appears to be broken by design. On
+ reasonable *BSD systems it should also be supported but this is untested.
+ This option requires that you start your Tor as root. If you use
+ DisableAllSwap, please consider using the User option to properly reduce
+ the privileges of your Tor.
o Code simplifications and refactorings:
- Numerous changes, bugfixes, and workarounds from Nathan Freitas
diff --git a/doc/tor.1.in b/doc/tor.1.in
index 739b889fb..1a71026aa 100644
--- a/doc/tor.1.in
+++ b/doc/tor.1.in
@@ -234,6 +234,19 @@ the default hidden service authorities, but not the directory or
bridge authorities.
.LP
.TP
+\fBDisableAllSwap \fR\fB0\fR|\fB1\fR\fP
+If set to 1, Tor will attempt to lock all current and future memory pages.
+On supported platforms, this should effectively disable any and all attempts
+to page out memory. Under the hood, DisableAllSwap uses mlockall() on unix-like
+platforms. Windows is currently unsupported. We believe that this feature works
+on modern Gnu/Linux distributions. Mac OS X appears to be broken by design. On
+reasonable *BSD systems it should also be supported but this is untested. This
+option requires that you start your Tor as root. If you use DisableAllSwap,
+please consider using the User option to properly reduce the privileges of
+your Tor.
+(Default: 0)
+.LP
+.TP
\fBFetchDirInfoEarly \fR\fB0\fR|\fB1\fR\fP
If set to 1, Tor will always fetch directory information like other
directory caches, even if you don't meet the normal criteria for
diff --git a/src/common/compat.c b/src/common/compat.c
index e1a275de1..9e5dca352 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -2204,6 +2204,105 @@ tor_threads_init(void)
}
#endif
+#ifdef HAVE_SYS_MMAN_H
+/** Attempt to raise the current and max rlimit to infinity for our process.
+ * This only needs to be done once and can probably only be done when we have
+ * not already dropped privileges.
+ */
+static int
+tor_set_max_memlock(void)
+{
+ /* Future consideration for Windows is probably SetProcessWorkingSetSize
+ * This is similar to setting the memory rlimit of RLIMIT_MEMLOCK
+ * http://msdn.microsoft.com/en-us/library/ms686234(VS.85).aspx
+ */
+
+ struct rlimit limit;
+ int ret;
+
+ /* Do we want to report current limits first? This is not really needed. */
+ ret = getrlimit(RLIMIT_MEMLOCK, &limit);
+ if (ret == -1) {
+ log_warn(LD_GENERAL, "Could not get RLIMIT_MEMLOCK: %s", strerror(errno));
+ return -1;
+ }
+
+ /* RLIM_INFINITY is -1 on some platforms. */
+ limit.rlim_cur = RLIM_INFINITY;
+ limit.rlim_max = RLIM_INFINITY;
+
+ ret = setrlimit(RLIMIT_MEMLOCK, &limit);
+ if (ret == -1) {
+ if (errno == EPERM) {
+ log_warn(LD_GENERAL, "You appear to lack permissions to change memory "
+ "limits. Are you root?");
+ log_warn(LD_GENERAL, "Unable to raise RLIMIT_MEMLOCK: %s",
+ strerror(errno));
+ } else {
+ log_warn(LD_GENERAL, "Could not raise RLIMIT_MEMLOCK: %s",
+ strerror(errno));
+ }
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+/** Attempt to lock all current and all future memory pages.
+ * This should only be called once and while we're privileged.
+ * Like mlockall() we return 0 when we're successful and -1 when we're not.
+ * Unlike mlockall() we return 1 if we've already attempted to lock memory.
+ */
+int
+tor_mlockall(void)
+{
+ static int memory_lock_attempted = 0;
+ int ret;
+
+ if (memory_lock_attempted) {
+ return 1;
+ }
+
+ memory_lock_attempted = 1;
+
+ /*
+ * Future consideration for Windows may be VirtualLock
+ * VirtualLock appears to implement mlock() but not mlockall()
+ *
+ * http://msdn.microsoft.com/en-us/library/aa366895(VS.85).aspx
+ */
+
+#ifdef HAVE_SYS_MMAN_H
+ ret = tor_set_max_memlock();
+ if (ret == 0) {
+ /* Perhaps we only want to log this if we're in a verbose mode? */
+ log_notice(LD_GENERAL, "RLIMIT_MEMLOCK is now set to RLIM_INFINITY.");
+ }
+
+ ret = mlockall(MCL_CURRENT|MCL_FUTURE);
+ if (ret == 0) {
+ log_notice(LD_GENERAL, "Insecure OS paging is effectively disabled.");
+ return 0;
+ } else {
+ if (errno == ENOSYS) {
+ /* Apple - it's 2009! I'm looking at you. Grrr. */
+ log_notice(LD_GENERAL, "It appears that mlockall() is not available on "
+ "your platform.");
+ } else if (errno == EPERM) {
+ log_notice(LD_GENERAL, "It appears that you lack the permissions to "
+ "lock memory. Are you root?");
+ }
+ log_notice(LD_GENERAL, "Unable to lock all current and future memory "
+ "pages: %s", strerror(errno));
+ return -1;
+ }
+#else
+ log_warn(LD_GENERAL, "Unable to lock memory pages. mlockall() unsupported?");
+ return -1;
+#endif
+}
+
/** Identity of the "main" thread */
static unsigned long main_thread_id = -1;
diff --git a/src/common/compat.h b/src/common/compat.h
index edd09d868..554ae8919 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -509,6 +509,8 @@ typedef struct tor_mutex_t {
#endif
} tor_mutex_t;
+int tor_mlockall(void);
+
#ifdef TOR_IS_MULTITHREADED
tor_mutex_t *tor_mutex_new(void);
void tor_mutex_init(tor_mutex_t *m);
diff --git a/src/config/torrc.complete.in b/src/config/torrc.complete.in
index 2fbf494e5..6dbec2fbf 100644
--- a/src/config/torrc.complete.in
+++ b/src/config/torrc.complete.in
@@ -79,6 +79,9 @@
#DirServer moria2 v1 18.244.0.114:80 719B E45D E224 B607 C537 07D0 E214 3E2D 423E 74CF
#DirServer tor26 v1 86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D
+## Attempt to lock current and future memory pages and effectively disable swap
+# DisableAllSwap 0|1
+
## On startup, setgid to this user.
#Group GID
diff --git a/src/or/config.c b/src/or/config.c
index 5a0ced29d..b6a52a85d 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -195,6 +195,7 @@ static config_var_t _option_vars[] = {
OBSOLETE("DirRecordUsageSaveInterval"),
V(DirReqStatistics, BOOL, "0"),
VAR("DirServer", LINELIST, DirServers, NULL),
+ V(DisableAllSwap, BOOL, "0"),
V(DNSPort, UINT, "0"),
V(DNSListenAddress, LINELIST, NULL),
V(DownloadExtraInfo, BOOL, "0"),
@@ -456,6 +457,8 @@ static config_var_description_t options_description[] = {
{ "DirServer", "Tor only trusts directories signed with one of these "
"servers' keys. Used to override the standard list of directory "
"authorities." },
+ { "DisableAllSwap", "Tor will attempt a simple memory lock that "
+ "will prevent leaking of all information in memory to the swap file." },
/* { "FastFirstHopPK", "" }, */
/* FetchServerDescriptors, FetchHidServDescriptors,
* FetchUselessDescriptors */
@@ -1115,6 +1118,15 @@ options_act_reversible(or_options_t *old_options, char **msg)
}
#endif
+ /* Attempt to lock all current and future memory with mlockall() only once */
+ if (options->DisableAllSwap) {
+ if (tor_mlockall() == -1) {
+ *msg = tor_strdup("DisableAllSwap failure. Do you have proper "
+ "permissions?");
+ goto done;
+ }
+ }
+
/* Setuid/setgid as appropriate */
if (options->User) {
if (switch_id(options->User) != 0) {
@@ -3834,6 +3846,12 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val,
return -1;
}
+ if (old->DisableAllSwap != new_val->DisableAllSwap) {
+ *msg = tor_strdup("While Tor is running, changing DisableAllSwap "
+ "is not allowed.");
+ return -1;
+ }
+
return 0;
}
diff --git a/src/or/or.h b/src/or/or.h
index bf415d839..767ad9572 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2287,6 +2287,9 @@ typedef struct {
* stop building circuits? */
int StrictEntryNodes; /**< Boolean: When none of our EntryNodes are up, do we
* stop building circuits? */
+ int DisableAllSwap; /**< Boolean: Attempt to call mlockall() on our
+ * process for all current and future memory. */
+
routerset_t *ExcludeNodes;/**< Structure containing nicknames, digests,
* country codes and IP address patterns of ORs
* not to use in circuits. */