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.