]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
initial pledge(2) on OpenBSD 1803/head
authorKlemens Nanni <kn@openbsd.org>
Mon, 12 Feb 2024 11:23:46 +0000 (12:23 +0100)
committerKlemens Nanni <kn@openbsd.org>
Mon, 12 Feb 2024 11:23:46 +0000 (12:23 +0100)
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

shairport.c

index bded416524abae2322631251a09c956cb7327884..bfa6e07f6f3ad67afd26acd4e4e428af90fadc65 100644 (file)
@@ -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");