Monday, January 01, 2024

spotifyd: pledge

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 <kn@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 {

No comments:

Post a Comment