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
This commit is contained in:
Klemens Nanni
2024-02-12 12:23:46 +01:00
parent 00a4758404
commit 5cdde02c9a
+46
View 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");