From: Christoph Liebender Subject: net/wstunnel: add unveil(2) restrictions To: ports@openbsd.org Date: Sat, 24 May 2025 18:18:15 +0200 Hello ports@, this patch adds unveil restrictions to the server part of net/wstunnel. It seems quite straightforward as the only files that are opened are specified in the commandline. Additionally, the server may use the libc resolver, therefore, /etc/{hosts, resolv.conf} are required as well. Reason being that either the user has configured the usage of the libc resolver, or the server falls back to it... At least that's what the code seems to be doing. I haven't added client restrictions as I'm not using that on OpenBSD right now. Fortunately, there is a crate that makes unveil(2) somewhat comforable to use in rust, which is an additional dependency now. Running with bad args gets you: # wstunnel server ws://0.0.0.0:4444 --restrict-config /asdf/jk.l thread 'main' panicked at wstunnel-cli/src/main.rs:122:69: unveil(/asdf/jk.l, r) failed: No such file or directory (os error 2) Otherwise, it works fine on my machine. :) testers, comments, ok? - Christoph diff --git a/net/wstunnel/Makefile b/net/wstunnel/Makefile index 51d79bfb1ea..c812de49650 100644 --- a/net/wstunnel/Makefile +++ b/net/wstunnel/Makefile @@ -6,16 +6,16 @@ COMMENT = tunnel all your traffic over Websocket or HTTP2 GH_ACCOUNT = erebe GH_PROJECT = wstunnel GH_TAGNAME = v10.3.0 +REVISION = 0 CATEGORIES = net MAINTAINER = Christoph Liebender -HOMEPAGE = https://github.com/erebe/wstunnel - # BSD-3 PERMIT_PACKAGE = Yes +# uses unveil(2) WANTLIB = ${MODCARGO_WANTLIB} m MODULES = devel/cargo diff --git a/net/wstunnel/crates.inc b/net/wstunnel/crates.inc index 7714b5bd591..fe788c9766d 100644 --- a/net/wstunnel/crates.inc +++ b/net/wstunnel/crates.inc @@ -318,6 +318,7 @@ MODCARGO_CRATES += unicode-segmentation 1.12.0 # MIT OR Apache-2.0 MODCARGO_CRATES += unicode-xid 0.2.6 # MIT OR Apache-2.0 MODCARGO_CRATES += unsafe-libyaml 0.2.11 # MIT MODCARGO_CRATES += untrusted 0.9.0 # ISC +MODCARGO_CRATES += unveil 0.3.2 # MIT/Apache-2.0 MODCARGO_CRATES += url 2.5.4 # MIT OR Apache-2.0 MODCARGO_CRATES += urlencoding 2.1.3 # MIT MODCARGO_CRATES += utf-8 0.7.6 # MIT OR Apache-2.0 diff --git a/net/wstunnel/distinfo b/net/wstunnel/distinfo index 7c92399f0c2..d02792215b7 100644 --- a/net/wstunnel/distinfo +++ b/net/wstunnel/distinfo @@ -318,6 +318,7 @@ SHA256 (cargo/unicode-segmentation-1.12.0.tar.gz) = 9szyUSEhFLVEM+yUn9anhBJ1+a2i SHA256 (cargo/unicode-xid-0.2.6.tar.gz) = 68HATHFRDH9wK1K3w1BzTJ/xKVxGSgMzWwC7hPxU+FM= SHA256 (cargo/unsafe-libyaml-0.2.11.tar.gz) = ZzqsWfrLq4qQB8f2EI0R9jtgP3yr/5n6v2UP6lwyuGE= SHA256 (cargo/untrusted-0.9.0.tar.gz) = jsttoouKNR13O2jVglrDkBfmgHUPmA86GoXNjdKKR8E= +SHA256 (cargo/unveil-0.3.2.tar.gz) = Xn+oZ9VZECAB7GlBZe0X1fgulSEwYKZfnItigAhLv+w= SHA256 (cargo/url-2.5.4.tar.gz) = Mvi2hsrdFHP0vQEXpdKNNrGt44Tqm1BpocQK7+1/2mA= SHA256 (cargo/urlencoding-2.1.3.tar.gz) = 2vjbo7frhwyvHd7te8nSoEnzz9+ufLUhsIfMM65MSdo= SHA256 (cargo/utf-8-0.7.6.tar.gz) = CcyO5y0qm+zy8v6+AgW77Y/GYVt8tCmtBi3Ht93QNqk= @@ -732,6 +733,7 @@ SIZE (cargo/unicode-segmentation-1.12.0.tar.gz) = 106323 SIZE (cargo/unicode-xid-0.2.6.tar.gz) = 15744 SIZE (cargo/unsafe-libyaml-0.2.11.tar.gz) = 62101 SIZE (cargo/untrusted-0.9.0.tar.gz) = 14447 +SIZE (cargo/unveil-0.3.2.tar.gz) = 7280 SIZE (cargo/url-2.5.4.tar.gz) = 81097 SIZE (cargo/urlencoding-2.1.3.tar.gz) = 6538 SIZE (cargo/utf-8-0.7.6.tar.gz) = 10422 diff --git a/net/wstunnel/patches/patch-Cargo_lock b/net/wstunnel/patches/patch-Cargo_lock new file mode 100644 index 00000000000..433a8ccfbe7 --- /dev/null +++ b/net/wstunnel/patches/patch-Cargo_lock @@ -0,0 +1,27 @@ +Index: Cargo.lock +--- Cargo.lock.orig ++++ Cargo.lock +@@ -3201,6 +3201,15 @@ source = "registry+https://github.com/rust-lang/crates + checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + + [[package]] ++name = "unveil" ++version = "0.3.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "5e7fa867d559102001ec694165ed17d5f82e95213060a65f9c8b6280084bbfec" ++dependencies = [ ++ "libc", ++] ++ ++[[package]] + name = "url" + version = "2.5.4" + source = "registry+https://github.com/rust-lang/crates.io-index" +@@ -3925,6 +3934,7 @@ dependencies = [ + "tokio", + "tracing", + "tracing-subscriber", ++ "unveil", + "wstunnel", + ] + diff --git a/net/wstunnel/patches/patch-wstunnel-cli_Cargo_toml b/net/wstunnel/patches/patch-wstunnel-cli_Cargo_toml new file mode 100644 index 00000000000..9b02c41479c --- /dev/null +++ b/net/wstunnel/patches/patch-wstunnel-cli_Cargo_toml @@ -0,0 +1,11 @@ +Index: wstunnel-cli/Cargo.toml +--- wstunnel-cli/Cargo.toml.orig ++++ wstunnel-cli/Cargo.toml +@@ -13,6 +13,7 @@ tracing-subscriber = { version = "0.3.19", features = + wstunnel = { path = ".." , features = ["clap"] } + + tikv-jemallocator = { version = "0.6", optional = true } ++unveil = "0.3.2" + + [features] + default = [] diff --git a/net/wstunnel/patches/patch-wstunnel-cli_src_main_rs b/net/wstunnel/patches/patch-wstunnel-cli_src_main_rs new file mode 100644 index 00000000000..8dd046d86f2 --- /dev/null +++ b/net/wstunnel/patches/patch-wstunnel-cli_src_main_rs @@ -0,0 +1,43 @@ +Index: wstunnel-cli/src/main.rs +--- wstunnel-cli/src/main.rs.orig ++++ wstunnel-cli/src/main.rs +@@ -8,6 +8,8 @@ use wstunnel::LocalProtocol; + use wstunnel::config::{Client, Server}; + use wstunnel::{run_client, run_server}; + ++use unveil::unveil; ++ + #[cfg(feature = "jemalloc")] + use tikv_jemallocator::Jemalloc; + +@@ -96,6 +98,30 @@ async fn main() -> anyhow::Result<()> { + run_client(*args).await?; + } + Commands::Server(args) => { ++ [ ++ args.restrict_config.as_ref(), ++ args.tls_certificate.as_ref(), ++ args.tls_private_key.as_ref(), ++ args.tls_client_ca_certs.as_ref(), ++ ] ++ .iter() ++ .flatten() ++ .filter_map(|path| path.as_os_str().to_str()) ++ .chain(["/etc/resolv.conf", "/etc/hosts"]) ++ .map(|rpath| { ++ ( ++ rpath, ++ unveil(rpath, "r").map_err(|err| -> anyhow::Error { ++ match err { ++ unveil::Error::Os(errno) => io::Error::from_raw_os_error(errno).into(), ++ _ => err.into(), ++ } ++ }), ++ ) ++ }) ++ .for_each(|(rpath, result)| result.unwrap_or_else(|err| panic!("unveil({}, r) failed: {}", rpath, err))); ++ ++ unveil::unveil("", "").expect("unveil(NULL, NULL) failed"); + run_server(*args).await?; + } + }