diff --git a/changes/disable_debugger_attachment b/changes/disable_debugger_attachment new file mode 100644 index 0000000000..366f97224e --- /dev/null +++ b/changes/disable_debugger_attachment @@ -0,0 +1,14 @@ + o Minor features: + - If set to 1, Tor will attempt to prevent basic debugging attachment + attempts by other processes. It has no impact for users who wish to + attach if they have CAP_SYS_PTRACE or if they are root. We believe that + this feature works on modern Gnu/Linux distributions, and that it may + also work on *BSD systems (untested). Some modern Gnu/Linux systems such + as Ubuntu have the kernel.yama.ptrace_scope sysctl and by default enable + it as an attempt to limit the PTRACE scope for all user processes by + default. This feature will attempt to limit the PTRACE scope for Tor + specifically - it will not attempt to alter the system wide ptrace scope + as it may not even exist. If you wish to attach to Tor with a debugger + such as gdb or strace you will want to set this to 0 for the duration of + your debugging. Normal users should leave it on. (Default: 1) + diff --git a/doc/tor.1.txt b/doc/tor.1.txt index f5be391052..7f9bfbbf9a 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -258,6 +258,20 @@ Other options can be specified either on the command-line (--option option requires that you start your Tor as root, and you should use the **User** option to properly reduce Tor's privileges. (Default: 0) +**DisableDebuggerAttachment** **0**|**1**:: + If set to 1, Tor will attempt to prevent basic debugging attachment attempts + by other processes. It has no impact for users who wish to attach if they + have CAP_SYS_PTRACE or if they are root. We believe that this feature + works on modern Gnu/Linux distributions, and that it may also work on *BSD + systems (untested). Some modern Gnu/Linux systems such as Ubuntu have the + kernel.yama.ptrace_scope sysctl and by default enable it as an attempt to + limit the PTRACE scope for all user processes by default. This feature will + attempt to limit the PTRACE scope for Tor specifically - it will not attempt + to alter the system wide ptrace scope as it may not even exist. If you wish + to attach to Tor with a debugger such as gdb or strace you will want to set + this to 0 for the duration of your debugging. Normal users should leave it + on. (Default: 1) + **FetchDirInfoEarly** **0**|**1**:: If set to 1, Tor will always fetch directory information like other directory caches, even if you don't meet the normal criteria for fetching diff --git a/src/or/config.c b/src/or/config.c index ef9e4ecee4..b8ff6e8481 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -45,6 +45,14 @@ /* From main.c */ extern int quiet_level; +/* Includes for the process attaching prevention */ +#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__) +#include +#elif defined(__APPLE__) +#include +#include +#endif + /** Enumeration of types which option values can take */ typedef enum config_type_t { CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */ @@ -246,6 +254,7 @@ static config_var_t _option_vars[] = { V(DirReqStatistics, BOOL, "1"), VAR("DirServer", LINELIST, DirServers, NULL), V(DisableAllSwap, BOOL, "0"), + V(DisableDebuggerAttachment, BOOL, "1"), V(DisableIOCP, BOOL, "1"), V(DNSPort, LINELIST, NULL), V(DNSListenAddress, LINELIST, NULL), @@ -678,6 +687,47 @@ get_dirportfrontpage(void) return global_dirfrontpagecontents; } +/* We only use the linux prctl for now. There is no Win32 support; this may + * also work on various BSD systems and Mac OS X - send testing feedback! + * + * On recent Gnu/Linux kernels it is possible to create a system-wide policy + * that will prevent non-root processes from attaching to other processes + * unless they are the parent process; thus gdb can attach to programs that + * they execute but they cannot attach to other processes running as the same + * user. The system wide policy may be set with the sysctl + * kernel.yama.ptrace_scope or by inspecting /proc/sys/kernel/yama/ptrace_scope + * and it is 1 by default on Ubuntu 11.04. + * + * This ptrace scope will be ignored on Gnu/Linux for users with + * CAP_SYS_PTRACE and so it is very likely that root will still be able to + * attach to the Tor process. +*/ +/** Attempt to disable debugger attachment. */ +static int tor_disable_debugger_attach(void) { + int r; + r = -1; + log_debug(LD_CONFIG, + "Attemping to disable debugger attachment to Tor for unprivileged users."); +#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && defined(HAVE_PRCTL) +#ifdef PR_SET_DUMPABLE + r = prctl(PR_SET_DUMPABLE, 0); +#endif +#endif +#if defined(__APPLE__) && defined(PT_DENY_ATTACH) + r = ptrace(PT_DENY_ATTACH, 0, 0, 0); +#endif + +// XXX: TODO - Mac OS X has dtrace and this may be disabled - implement it here +// XXX: TODO - Windows probably has something similar - implement it here + if (r == 0) { + log_debug(LD_CONFIG,"Debugger attachment disabled for unprivileged users."); + } else { + log_warn(LD_CONFIG, "Unable to disable ptrace attach: %s", + strerror(errno)); + } + return r; +} + /** Allocate an empty configuration object of a given format type. */ static void * config_alloc(const config_format_t *fmt) @@ -1286,6 +1336,13 @@ options_act(const or_options_t *old_options) const int transition_affects_workers = old_options && options_transition_affects_workers(old_options, options); + /* disable ptrace and later, other basic debugging techniques */ + if (options->DisableDebuggerAttachment) { + tor_disable_debugger_attach(); + } else { + log_notice(LD_CONFIG,"Debugger attachment enabled for unprivileged users."); + } + if (running_tor && !have_lockfile()) { if (try_locking(options, 1) < 0) return -1; diff --git a/src/or/or.h b/src/or/or.h index f186eac7bd..546fe17bf3 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3248,6 +3248,8 @@ typedef struct { disclaimer. This allows a server administrator to show that they're running Tor and anyone visiting their server will know this without any specialized knowledge. */ + int DisableDebuggerAttachment; /**< Currently Linux only specific attempt to + disable ptrace; needs BSD testing. */ /** Boolean: if set, we start even if our resolv.conf file is missing * or broken. */ int ServerDNSAllowBrokenConfig;