commit eb43401bfb6d69db66d256582a99e63de7d222d8 Author: Nick Mathewson nickm@torproject.org Date: Wed Aug 9 10:42:37 2017 -0400
Add a 'NoExec' option that causes tor_spawn_background() to fail
Core of an implementation for 22976. --- changes/feature22976 | 7 +++++++ doc/tor.1.txt | 7 +++++++ src/common/util.c | 17 +++++++++++++++++ src/common/util.h | 2 ++ src/or/config.c | 11 +++++++++++ src/or/or.h | 4 ++++ 6 files changed, 48 insertions(+)
diff --git a/changes/feature22976 b/changes/feature22976 new file mode 100644 index 000000000..334f47ad0 --- /dev/null +++ b/changes/feature22976 @@ -0,0 +1,7 @@ + o Minor features (integration, hardening): + - Added a new NoExec option to . When this option is set to 1, + Tor will never try to run another program, regardless of + the settings of PortForwardingHelper, ClientTransportPlugin, + or ServerTransportPlugin. Once NoExec is set, it cannot be + disabled without restarting Tor. + Closes ticket 22976. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index b4a3cc5f7..fb19ce38b 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -773,6 +773,13 @@ GENERAL OPTIONS circuits. If the option is set to "default", we obey a parameter in the consensus document. (Default: auto)
+[[NoExec]] **NoExec** **0**|**1**:: + If this option is set to 1, then Tor will never launch another + executable, regardless of the settings of PortForwardingHelper, + ClientTransportPlugin, or ServerTransportPlugin. Once this + option has been set to 1, it cannot be set back to 0 without + restarting Tor. (Default: 0) + CLIENT OPTIONS --------------
diff --git a/src/common/util.c b/src/common/util.c index 0858d17fe..18108fc24 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -4142,6 +4142,20 @@ process_handle_waitpid_cb(int status, void *arg) #define CHILD_STATE_EXEC 8 #define CHILD_STATE_FAILEXEC 9 /** @} */ +/** + * Boolean. If true, then Tor may call execve or CreateProcess via + * tor_spawn_background. + **/ +static int may_spawn_background_process = 1; +/** + * Turn off may_spawn_background_process, so that all future calls to + * tor_spawn_background are guaranteed to fail. + **/ +void +tor_disable_spawning_background_processes(void) +{ + may_spawn_background_process = 0; +} /** Start a program in the background. If <b>filename</b> contains a '/', then * it will be treated as an absolute or relative path. Otherwise, on * non-Windows systems, the system path will be searched for <b>filename</b>. @@ -4166,6 +4180,9 @@ tor_spawn_background(const char *const filename, const char **argv, process_environment_t *env, process_handle_t **process_handle_out) { + if (may_spawn_background_process == 0) + return PROCESS_STATUS_ERROR; + #ifdef _WIN32 HANDLE stdout_pipe_read = NULL; HANDLE stdout_pipe_write = NULL; diff --git a/src/common/util.h b/src/common/util.h index df581d240..f50cf043a 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -396,6 +396,8 @@ void tor_check_port_forwarding(const char *filename, struct smartlist_t *ports_to_forward, time_t now);
+void tor_disable_spawning_background_processes(void); + typedef struct process_handle_t process_handle_t; typedef struct process_environment_t process_environment_t; int tor_spawn_background(const char *const filename, const char **argv, diff --git a/src/or/config.c b/src/or/config.c index 9b6bf40eb..16e4ded69 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -409,6 +409,7 @@ static config_var_t option_vars_[] = { OBSOLETE("PredictedPortsRelevanceTime"), OBSOLETE("WarnUnsafeSocks"), VAR("NodeFamily", LINELIST, NodeFamilies, NULL), + V(NoExec, BOOL, "0"), V(NumCPUs, UINT, "0"), V(NumDirectoryGuards, UINT, "0"), V(NumEntryGuards, UINT, "0"), @@ -1595,6 +1596,10 @@ options_act(const or_options_t *old_options) const int transition_affects_guards = old_options && options_transition_affects_guards(old_options, options);
+ if (options->NoExec) { + tor_disable_spawning_background_processes(); + } + /* disable ptrace and later, other basic debugging techniques */ { /* Remember if we already disabled debugger attachment */ @@ -4447,6 +4452,12 @@ options_transition_allowed(const or_options_t *old, return -1; }
+ if (old->NoExec && !new_val->NoExec) { + *msg = tor_strdup("While Tor is running, disabling " + "NoExec is not allowed."); + return -1; + } + if (sandbox_is_active()) { #define SB_NOCHANGE_STR(opt) \ do { \ diff --git a/src/or/or.h b/src/or/or.h index ff11c7279..e24bfd7cd 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4596,6 +4596,10 @@ typedef struct { * consensuses around so that we can generate diffs from them. If 0, * use the default. */ int MaxConsensusAgeForDiffs; + + /** Bool (default: 0). Tells Tor to never try to exec another program. + */ + int NoExec; } or_options_t;
/** Persistent state for an onion router, as saved to disk. */
tor-commits@lists.torproject.org