Code comments explain the promises a bit more, tl;dr: main() { pledge("stdio rpath wpath cpath inet mcast flock chown unix dns proc exec audio", NULL) [CLI arg and config parsing] if (on-song-change-hook) pledge("stdio rpath wpath cpath inet mcast unix dns proc exec audio", NULL) else pledge("stdio rpath wpath cpath inet mcast unix dns audio", NULL) [...] }
Daemon or in foreground, static credentials or --*-cmd or zeroconf discovery, cache or no persistent files, rc.d script or manually run, MPRIS interaction via playerctl(1): it all works for me. Unveil looks viable and doable, but as a second step. Please try to break this. Feedback? OK? Only REVISION conflicts with 'spotifyd: add user and rc.d script". Index: Makefile =================================================================== RCS file: /cvs/ports/audio/spotifyd/Makefile,v diff -u -p -r1.4 Makefile --- Makefile 31 Dec 2023 18:45:17 -0000 1.4 +++ Makefile 1 Jan 2024 00:08:15 -0000 @@ -4,7 +4,7 @@ NOT_FOR_ARCHS = powerpc64 riscv6 COMMENT = Spotify client running as UNIX daemon DIST_TUPLE = github Spotifyd spotifyd v0.3.5 . CATEGORIES = audio net -REVISION = 2 +REVISION = 4 MAINTAINER = Klemens Nanni <k...@openbsd.org> @@ -13,6 +13,7 @@ HOMEPAGE = https://spotifyd.rs # GPLv3.0 PERMIT_PACKAGE = Yes +# uses pledge() WANTLIB = ${MODCARGO_WANTLIB} dbus-1 m portaudio MODULES = devel/cargo Index: crates.inc =================================================================== RCS file: /cvs/ports/audio/spotifyd/crates.inc,v diff -u -p -r1.2 crates.inc --- crates.inc 31 Dec 2023 18:45:17 -0000 1.2 +++ crates.inc 1 Jan 2024 00:39:11 -0000 @@ -218,6 +218,7 @@ MODCARGO_CRATES += petgraph 0.6.3 # MIT MODCARGO_CRATES += pin-project-lite 0.2.9 # Apache-2.0 OR MIT MODCARGO_CRATES += pin-utils 0.1.0 # MIT OR Apache-2.0 MODCARGO_CRATES += pkg-config 0.3.26 # MIT OR Apache-2.0 +MODCARGO_CRATES += pledge 0.4.2 # MIT MODCARGO_CRATES += polling 2.6.0 # Apache-2.0 OR MIT MODCARGO_CRATES += portaudio-rs 0.3.2 # MIT MODCARGO_CRATES += portaudio-sys 0.1.1 # MIT Index: distinfo =================================================================== RCS file: /cvs/ports/audio/spotifyd/distinfo,v diff -u -p -r1.2 distinfo --- distinfo 31 Dec 2023 18:45:17 -0000 1.2 +++ distinfo 1 Jan 2024 00:38:30 -0000 @@ -219,6 +219,7 @@ SHA256 (cargo/petgraph-0.6.3.tar.gz) = T SHA256 (cargo/pin-project-lite-0.2.9.tar.gz) = 4KeuOsLxFzCF05hTHHBXVslKTFaEN4XfhaYMGgr6wRY= SHA256 (cargo/pin-utils-0.1.0.tar.gz) = i4cNjBUbby+5PoShMUYTjwXQLtEcfnxU+IJqqvfJ8YQ= SHA256 (cargo/pkg-config-0.3.26.tar.gz) = asmln3NHPxuNhSQh5Z5kgJ8CWZSDfvdDYVxtDFswUWA= +SHA256 (cargo/pledge-0.4.2.tar.gz) = JSWZQXt9mkO3/cY915CwhIZmqJELLr4aJRGDCcPJgeU= SHA256 (cargo/polling-2.6.0.tar.gz) = fh+HmymYCZwtaauWBdFF1bZhGVYn7MxoAALEkYp/tvo= SHA256 (cargo/portaudio-rs-0.3.2.tar.gz) = zba17/lszJv0TTTDeasDrpREJtg9FpQ0W9+BWdVh1WI= SHA256 (cargo/portaudio-sys-0.1.1.tar.gz) = UZSk+pU7T/2FHDIO9vBITNcnjLcWnqnWxDPkmyP3t/U= @@ -595,6 +596,7 @@ SIZE (cargo/petgraph-0.6.3.tar.gz) = 185 SIZE (cargo/pin-project-lite-0.2.9.tar.gz) = 27713 SIZE (cargo/pin-utils-0.1.0.tar.gz) = 7580 SIZE (cargo/pkg-config-0.3.26.tar.gz) = 18662 +SIZE (cargo/pledge-0.4.2.tar.gz) = 4779 SIZE (cargo/polling-2.6.0.tar.gz) = 41714 SIZE (cargo/portaudio-rs-0.3.2.tar.gz) = 13267 SIZE (cargo/portaudio-sys-0.1.1.tar.gz) = 2327 Index: patches/patch-Cargo_lock =================================================================== RCS file: /cvs/ports/audio/spotifyd/patches/patch-Cargo_lock,v diff -u -p -r1.1 patch-Cargo_lock --- patches/patch-Cargo_lock 31 Dec 2023 18:45:18 -0000 1.1 +++ patches/patch-Cargo_lock 1 Jan 2024 02:10:26 -0000 @@ -1,6 +1,8 @@ Bump keyring to latest release 2.3.0 to add OpenBSD support https://github.com/Spotifyd/spotifyd/pull/1254 +use pledge(2) + Index: Cargo.lock --- Cargo.lock.orig +++ Cargo.lock @@ -16,3 +18,27 @@ Index: Cargo.lock dependencies = [ "byteorder", "lazy_static", +@@ -2277,6 +2277,15 @@ source = "registry+https://github.com/rust-lang/crates + checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + + [[package]] ++name = "pledge" ++version = "0.4.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "252599417b7d9a43b7fdc63dd790b0848666a8910b2ebe1a25118309c3c981e5" ++dependencies = [ ++ "libc", ++] ++ ++[[package]] + name = "polling" + version = "2.6.0" + source = "registry+https://github.com/rust-lang/crates.io-index" +@@ -2905,6 +2914,7 @@ dependencies = [ + "librespot-discovery", + "librespot-playback", + "log", ++ "pledge", + "rspotify", + "serde", + "sha-1 0.10.1", Index: patches/patch-Cargo_toml =================================================================== RCS file: patches/patch-Cargo_toml diff -N patches/patch-Cargo_toml --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-Cargo_toml 1 Jan 2024 00:43:51 -0000 @@ -0,0 +1,13 @@ +Index: Cargo.toml +--- Cargo.toml.orig ++++ Cargo.toml +@@ -39,6 +39,9 @@ librespot-connect = { version = "0.4" } + toml = "0.7" + color-eyre = "0.6" + ++[target."cfg(target_os = \"openbsd\")".dependencies] ++pledge = "0.4.2" ++ + [target."cfg(target_os = \"macos\")".dependencies] + whoami = "1" + Index: patches/patch-src_main_rs =================================================================== RCS file: patches/patch-src_main_rs diff -N patches/patch-src_main_rs --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_main_rs 1 Jan 2024 13:48:11 -0000 @@ -0,0 +1,61 @@ +use pledge(2) + +Index: src/main.rs +--- src/main.rs.orig ++++ src/main.rs +@@ -9,6 +9,7 @@ use daemonize::Daemonize; + use log::{error, info, trace, LevelFilter}; + use structopt::StructOpt; + use tokio::runtime::Runtime; ++use pledge::{pledge, pledge_promises, Promise, ToPromiseString}; + + #[cfg(feature = "alsa_backend")] + mod alsa_mixer; +@@ -60,6 +61,10 @@ fn setup_logger(log_target: LogTarget, verbose: bool) + } + + fn main() -> eyre::Result<()> { ++ // Start with superset of all potential promises. ++ // Drop later after CLI arguments and configuration files were parsed. ++ pledge_promises![Stdio Rpath Wpath Cpath Inet Mcast Flock Chown Unix Dns Proc Exec Audio].unwrap(); ++ + color_eyre::install().wrap_err("Couldn't initialize error reporting")?; + + let mut cli_config: CliConfig = CliConfig::from_args(); +@@ -101,6 +106,36 @@ fn main() -> eyre::Result<()> { + Err(e) => error!("Something went wrong while daemonizing: {}", e), + }; + } ++ ++ // At this point: ++ // * --username-cmd, --password-cmd were handled ++ // => no "proc exec" ++ // * --pid, daemon(3) were handled ++ // => no "cpath flock chown" for PID file ++ // => no "proc" for double-fork(2) ++ // ++ // Minimum subset of permanent promises: ++ let mut promises = vec![ ++ Promise::Stdio, // logging ++ Promise::Rpath, // 1. ${TMPDIR}/.tmp* O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC ++ Promise::Wpath, // ... ++ Promise::Cpath, // 2. --cache-path aka. "cache_path" ++ Promise::Inet, // internet Spotify ++ Promise::Mcast, // local Zeroconf Discovery ++ Promise::Unix, // sndio(7), D-Bus (keyring, MPRIS) ++ Promise::Dns, // internet Spotify ++ Promise::Audio, // sndio(7) ++ ]; ++ ++ // --on-song-change-hook aka. "onevent" ++ if internal_config.onevent.is_some() { ++ promises.push(Promise::Proc); // always run through --shell aka. "shell" ++ promises.push(Promise::Exec); // defaults to "sh" ++ } ++ ++ // Second and final pledge before runtime starts. ++ // "mcast" could go if a) username is given and b) password/keyring worked. ++ pledge(&*promises.to_promise_string(), None).unwrap(); + + let runtime = Runtime::new().unwrap(); + runtime.block_on(async {