Pascal Stumpf wrote:
The pledge does not consider pluggable transports (fork + exec).

However, I am not against introducing unveil.


On Thu, 22 Oct 2026 20:30:00 +0000, David Uhden Collado wrote:
Hello,

Please find attached a patch adding pledge/unveil sandbox support
to net/tor 0.4.9.14.

The patch implements an OpenBSD-specific sandbox using pledge()
to restrict system calls and unveil() to restrict filesystem access.

It also enables Sandbox 1 in the default torrc, using the paths
provided by the OpenBSD port, including /etc/tor/torrc and /var/tor.

The sandbox is designed for the packaged default configuration.
Custom filesystem paths are not included in its unveil policy.

The patch also adjusts the configuration include test, which uses
temporary paths incompatible with this sandbox.

I would appreciate review of the sandbox implementation and its
pledge/unveil restrictions.

Thanks,
David.

You're right that pledge does not support managed pluggable transports that require fork() and execve(). I investigated possible workarounds, but couldn't find a simple and safe solution without granting additional execution privileges.

However, I still think pledge is worth keeping. Even with the relatively broad set of promises Tor requires, it restricts access to system interfaces and prevents the daemon from executing other programs or creating new processes. Combined with unveil, this provides additional protection for the default configuration.

Tor already explicitly rejects Sandbox 1 when managed pluggable transports using exec are configured, so this limitation does not introduce a silent failure. Users who need these transports can explicitly set Sandbox 0, while external SOCKS4/SOCKS5 transports remain compatible with the sandbox.

I've attached an updated patch (v2) that retains Sandbox 1 in the default torrc and documents these limitations in pkg/DESCR. It deliberately avoids the exec and error promises, as well as execpromises.

I understand that this is a trade-off between additional confinement and compatibility with managed transports, but I think enabling the sandbox for the common configuration is preferable to removing pledge entirely.
Index: net/tor/Makefile
===================================================================
RCS file: /cvs/ports/net/tor/Makefile,v
diff -u -p -u -p -r1.184 Makefile
--- net/tor/Makefile	9 Oct 2026 17:51:21 -0000	1.184
+++ net/tor/Makefile	23 Oct 2026 11:07:27 -0000
@@ -9,9 +9,12 @@ MAINTAINER=	Pascal Stumpf <pascal@stumpf
 # GPLv3
 PERMIT_PACKAGE=	Yes
 
+# uses pledge() and unveil()
 WANTLIB += c crypto event_core event_extra execinfo m pthread ssl z
 
 SITES=		https://www.torproject.org/dist/
+
+BUILD_DEPENDS=	devel/metaauto
 
 AUTOCONF_VERSION=2.69
 CONFIGURE_STYLE=autoconf
Index: net/tor/patches/patch-configure_ac
===================================================================
RCS file: /cvs/ports/net/tor/patches/patch-configure_ac,v
diff -u -p -u -p -r1.23 patch-configure_ac
--- net/tor/patches/patch-configure_ac	20 Feb 2026 18:57:18 -0000	1.23
+++ net/tor/patches/patch-configure_ac	23 Oct 2026 11:07:27 -0000
@@ -1,4 +1,5 @@
 disable -fasynchronous-unwind-tables as it breaks build on armv7
+
 Index: configure.ac
 --- configure.ac.orig
 +++ configure.ac
Index: net/tor/patches/patch-src_config_torrc_sample_in
===================================================================
RCS file: /cvs/ports/net/tor/patches/patch-src_config_torrc_sample_in,v
diff -u -p -u -p -r1.25 patch-src_config_torrc_sample_in
--- net/tor/patches/patch-src_config_torrc_sample_in	11 Mar 2022 19:47:53 -0000	1.25
+++ net/tor/patches/patch-src_config_torrc_sample_in	23 Oct 2026 11:07:27 -0000
@@ -1,7 +1,11 @@
+# Use packaged OpenBSD defaults and enable the sandbox by default.
+# Managed transports remain rejected because pledge's exec promise is
+# intentionally not granted.
+
 Index: src/config/torrc.sample.in
 --- src/config/torrc.sample.in.orig
 +++ src/config/torrc.sample.in
-@@ -39,18 +39,18 @@
+@@ -39,18 +39,21 @@
  ## Send every possible message to @LOCALSTATEDIR@/log/tor/debug.log
  #Log debug file @LOCALSTATEDIR@/log/tor/debug.log
  ## Use the system log instead of Tor's logfiles
@@ -20,10 +24,13 @@ Index: src/config/torrc.sample.in
  ## things in $HOME/.tor on Unix, and in Application Data\tor on Windows.
 -#DataDirectory @LOCALSTATEDIR@/lib/tor
 +DataDirectory /var/tor
++
++## Restrict filesystem and system call access on OpenBSD.
++Sandbox 1
  
  ## The port on which Tor will listen for local connections from Tor
  ## controller applications, as documented in control-spec.txt.
-@@ -69,10 +69,10 @@
+@@ -69,10 +72,10 @@
  ## HiddenServicePort x y:z says to redirect requests on port x to the
  ## address y:z.
  
@@ -36,7 +43,7 @@ Index: src/config/torrc.sample.in
  #HiddenServicePort 80 127.0.0.1:80
  #HiddenServicePort 22 127.0.0.1:22
  
-@@ -218,6 +218,8 @@
+@@ -218,6 +221,8 @@
  ## and any public IPv4 and IPv6 addresses on any interface on the relay.
  ## See the man page entry for ExitPolicyRejectPrivate if you want to allow
  ## "exit enclaving".
Index: net/tor/patches/patch-src_ext_ed25519_donna_ed25519-donna-portable_h
===================================================================
RCS file: /cvs/ports/net/tor/patches/patch-src_ext_ed25519_donna_ed25519-donna-portable_h,v
diff -u -p -u -p -r1.2 patch-src_ext_ed25519_donna_ed25519-donna-portable_h
--- net/tor/patches/patch-src_ext_ed25519_donna_ed25519-donna-portable_h	11 Mar 2022 19:47:53 -0000	1.2
+++ net/tor/patches/patch-src_ext_ed25519_donna_ed25519-donna-portable_h	23 Oct 2026 11:07:27 -0000
@@ -1,5 +1,9 @@
---- src/ext/ed25519/donna/ed25519-donna-portable.h.orig	Fri Dec 11 14:53:44 2015
-+++ src/ext/ed25519/donna/ed25519-donna-portable.h	Fri Dec 11 14:53:57 2015
+Allow GCC 4.2 to select its mode(TI) implementation for 128-bit Ed25519
+arithmetic; upstream only enables that compiler path from GCC 4.4.
+
+Index: src/ext/ed25519/donna/ed25519-donna-portable.h
+--- src/ext/ed25519/donna/ed25519-donna-portable.h.orig
++++ src/ext/ed25519/donna/ed25519-donna-portable.h
 @@ -50,7 +50,7 @@
  		#if defined(__SIZEOF_INT128__)
  			#define HAVE_NATIVE_UINT128
Index: net/tor/patches/patch-src_lib_sandbox_sandbox_c
===================================================================
RCS file: net/tor/patches/patch-src_lib_sandbox_sandbox_c
diff -N net/tor/patches/patch-src_lib_sandbox_sandbox_c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ net/tor/patches/patch-src_lib_sandbox_sandbox_c	23 Oct 2026 11:07:27 -0000
@@ -0,0 +1,99 @@
+# Add OpenBSD unveil and pledge support for Tor's Sandbox option.
+# The profile covers packaged defaults and does not grant pledge's exec.
+
+Index: src/lib/sandbox/sandbox.c
+--- src/lib/sandbox/sandbox.c.orig
++++ src/lib/sandbox/sandbox.c
+@@ -33,6 +33,10 @@
+ #include <stdlib.h>
+ #include <errno.h>
+ 
++#ifdef __OpenBSD__
++#include <unistd.h>
++#endif
++
+ #include "lib/sandbox/sandbox.h"
+ #include "lib/container/map.h"
+ #include "lib/err/torerr.h"
+@@ -47,6 +51,58 @@
+ 
+ #define DEBUGGING_CLOSE
+ 
++#ifdef __OpenBSD__
++static int openbsd_sandbox_active = 0;
++
++static int
++openbsd_unveil_path(const char *path, const char *permissions)
++{
++  if (unveil(path, permissions) == -1) {
++    log_warn(LD_GENERAL, "unveil(%s) failed: %s",
++             path, strerror(errno));
++    return -1;
++  }
++  return 0;
++}
++
++static int
++openbsd_sandbox_init(void)
++{
++  static const struct {
++    const char *path;
++    const char *permissions;
++  } rules[] = {
++    /*
++     * This profile covers only OpenBSD port defaults. Custom paths must
++     * not enable Sandbox; those paths are deliberately not unveiled here.
++     */
++    { "/etc/tor/torrc", "r" },
++    { "/var/tor", "rwc" },
++    { "/etc/resolv.conf", "r" },
++    { "/etc/hosts", "r" },
++    { "/etc/services", "r" },
++    { "/dev/urandom", "r" },
++    { "/dev/log", "w" },
++  };
++
++  for (size_t i = 0; i < sizeof(rules) / sizeof(rules[0]); ++i) {
++    if (openbsd_unveil_path(rules[i].path, rules[i].permissions) < 0)
++      return -1;
++  }
++  if (unveil(NULL, NULL) == -1) {
++    log_warn(LD_GENERAL, "unveil lock failed: %s", strerror(errno));
++    return -1;
++  }
++  if (pledge("stdio rpath wpath cpath dpath fattr flock inet dns unix",
++             NULL) == -1) {
++    log_warn(LD_GENERAL, "pledge failed: %s", strerror(errno));
++    return -1;
++  }
++  openbsd_sandbox_active = 1;
++  return 0;
++}
++#endif
++
+ #if defined(USE_LIBSECCOMP)
+ 
+ #include <sys/mman.h>
+@@ -2308,6 +2364,10 @@ sandbox_init(sandbox_cfg_t *cfg)
+            "libseccomp and its necessary header files (e.g. seccomp.h).");
+   return 0;
+ 
++#elif defined(__OpenBSD__)
++  (void)cfg;
++  return openbsd_sandbox_init();
++
+ #else
+   (void)cfg;
+   log_warn(LD_GENERAL,
+@@ -2370,7 +2430,11 @@ sandbox_cfg_allow_rename(sandbox_cfg_t *
+ int
+ sandbox_is_active(void)
+ {
++#ifdef __OpenBSD__
++  return openbsd_sandbox_active != 0;
++#else
+   return 0;
++#endif
+ }
+ 
+ #endif /* !defined(USE_LIBSECCOMP) */
Index: net/tor/patches/patch-src_test_test_include_sh
===================================================================
RCS file: net/tor/patches/patch-src_test_test_include_sh
diff -N net/tor/patches/patch-src_test_test_include_sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ net/tor/patches/patch-src_test_test_include_sh	23 Oct 2026 11:07:27 -0000
@@ -0,0 +1,20 @@
+The OpenBSD sandbox in this port is restricted to package paths such as
+/var/tor.  This test uses a temporary data directory, so do not enable that
+sandbox while testing configuration includes.
+
+Index: src/test/test_include.sh
+--- src/test/test_include.sh.orig
++++ src/test/test_include.sh
+@@ -99,7 +99,11 @@
+ echo "NodeFamily 4" > "$torrcd/folder/04_four.conf"
+ echo "NodeFamily 5" > "$torrcd/folder/05_five.conf"
+ torrc="$configdir/torrc"
+-echo "Sandbox 1" > "$torrc"
++if test "$UNAME_OS" = 'OpenBSD'; then
++    echo "Sandbox 0" > "$torrc"
++else
++    echo "Sandbox 1" > "$torrc"
++fi
+ echo "
+ %include $torrcd/*.conf
+ %include $torrcd/f*
Index: net/tor/patches/patch-src_test_test_tortls_openssl_c
===================================================================
RCS file: /cvs/ports/net/tor/patches/patch-src_test_test_tortls_openssl_c,v
diff -u -p -u -p -r1.1 patch-src_test_test_tortls_openssl_c
--- net/tor/patches/patch-src_test_test_tortls_openssl_c	20 Feb 2026 18:57:18 -0000	1.1
+++ net/tor/patches/patch-src_test_test_tortls_openssl_c	23 Oct 2026 11:07:27 -0000
@@ -1,3 +1,6 @@
+Use the LibreSSL TLS state text in the OpenSSL compatibility tests,
+while retaining OpenSSL’s own state string for upstream OpenSSL builds.
+
 Index: src/test/test_tortls_openssl.c
 --- src/test/test_tortls_openssl.c.orig
 +++ src/test/test_tortls_openssl.c
Index: net/tor/pkg/DESCR
===================================================================
RCS file: /cvs/ports/net/tor/pkg/DESCR,v
diff -u -p -u -p -r1.1.1.1 DESCR
--- net/tor/pkg/DESCR	26 Sep 2004 10:06:29 -0000	1.1.1.1
+++ net/tor/pkg/DESCR	23 Oct 2026 11:07:27 -0000
@@ -1,2 +1,10 @@
 Tor is a connection-based low-latency anonymous communication system that
 protects TCP streams: web browsing, instant messaging, irc, ssh, etc.
+
+On OpenBSD, the packaged default torrc enables Sandbox 1, which applies
+unveil(2) and pledge(2). The process running Tor does not receive pledge's
+exec or error promise. Managed pluggable transports (ClientTransportPlugin
+or ServerTransportPlugin with exec) are therefore rejected by Tor while
+Sandbox is enabled. External SOCKS4/SOCKS5 client proxies and external server
+proxies do not require Tor to execute a program and remain supported under
+the sandbox profile when their endpoints are accessible.

Reply via email to