From: Klemens Nanni Date: Mon, 12 Feb 2024 11:23:46 +0000 (+0100) Subject: initial pledge(2) on OpenBSD X-Git-Tag: 4.3.4-dev~44^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1803%2Fhead;p=thirdparty%2Fshairport-sync.git initial pledge(2) on OpenBSD Limit the set of system calls shairport-sync is allowed to make, most importantly fork(2)/execve(2) if and only if user defined commands are run. OpenBSD's official audio/shairport-sync port already ships with this patch. https://man.openbsd.org/pledge.2 --- diff --git a/shairport.c b/shairport.c index bded4165..bfa6e07f 100644 --- a/shairport.c +++ b/shairport.c @@ -1929,6 +1929,12 @@ void _display_config(const char *filename, const int linenumber, __attribute__(( #define display_config(argc, argv) _display_config(__FILE__, __LINE__, argc, argv) int main(int argc, char **argv) { +#ifdef COMPILE_FOR_OPENBSD + /* Start with the superset of all potentially required promises. */ + if (pledge("stdio rpath wpath cpath dpath inet unix dns proc exec audio", NULL) == -1) + die("pledge: %s", strerror(errno)); +#endif + memset(&config, 0, sizeof(config)); // also clears all strings, BTW /* Check if we are called with -V or --version parameter */ if (argc >= 2 && ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0))) { @@ -2102,6 +2108,16 @@ int main(int argc, char **argv) { // parse arguments into config -- needed to locate pid_dir int audio_arg = parse_options(argc, argv); +#ifdef COMPILE_FOR_OPENBSD + /* Any command to be executed at runtime? */ + int run_cmds = + config.cmd_active_start != NULL || + config.cmd_active_stop != NULL || + config.cmd_set_volume != NULL || + config.cmd_start != NULL || + config.cmd_stop != NULL; +#endif + // mDNS supports maximum of 63-character names (we append 13). if (strlen(config.service_name) > 50) { warn("The service name \"%s\" is too long (max 50 characters) and has been truncated.", @@ -2237,6 +2253,16 @@ int main(int argc, char **argv) { #endif +#ifdef COMPILE_FOR_OPENBSD + /* Past daemon(3)'s double fork(2). */ + + /* Only user-defined commands are executed. */ + if (!run_cmds) + /* Drop "proc exec". */ + if (pledge("stdio rpath wpath cpath dpath inet unix dns audio", NULL) == -1) + die("pledge: %s", strerror(errno)); +#endif + #ifdef CONFIG_AIRPLAY_2 if (has_fltp_capable_aac_decoder() == 0) { @@ -2352,6 +2378,26 @@ int main(int argc, char **argv) { } config.output->init(argc - audio_arg, argv + audio_arg); +#ifdef COMPILE_FOR_OPENBSD + /* Past first and last sio_open(3), sndio(7) only needs "audio". */ + +# ifdef CONFIG_METADATA + /* Only coverart cache is created. + * Only metadata pipe is special. */ + if (!config.metadata_enabled) +# endif + { + /* Drop "cpath dpath". */ + if (run_cmds) { + if (pledge("stdio rpath wpath inet unix dns proc exec audio", NULL) == -1) + die("pledge: %s", strerror(errno)); + } else { + if (pledge("stdio rpath wpath inet unix dns audio", NULL) == -1) + die("pledge: %s", strerror(errno)); + } + } +#endif + // pthread_cleanup_push(main_cleanup_handler, NULL); // daemon_log(LOG_NOTICE, "startup");