From 9c87a65ce91c38b60c19ae108a51a2e8ce46a85c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 17:44:19 +0000 Subject: * add new --system command line parameter to the daemon for running PulseAudio as system-wide instance * add PA_ prefixes to all global #defines * modify auth-by-creds: define a new group "pulse-access" which is used for authentication * add proper privilige dropping when running in --system mode * create runtime directory once on startup and not by each module seperately git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1105 fefdeb5f-60dc-0310-8127-8f9354f1896f --- bootstrap.sh | 2 +- configure.ac | 55 +++++++++++++++- src/Makefile.am | 14 ++-- src/daemon/cmdline.c | 12 +++- src/daemon/daemon-conf.c | 22 +++---- src/daemon/daemon-conf.h | 3 +- src/daemon/daemon.conf.in | 6 ++ src/daemon/main.c | 129 +++++++++++++++++++++++++++++++++++-- src/modules/module-match.c | 6 +- src/modules/module-protocol-stub.c | 55 ++++++++++------ src/modules/module-tunnel.c | 2 +- src/pulse/client-conf.c | 19 +++--- src/pulse/client-conf.h | 2 +- src/pulse/context.c | 24 ++++++- src/pulsecore/core-util.c | 86 +++++++++++++++++++------ src/pulsecore/core-util.h | 5 +- src/pulsecore/core.c | 5 +- src/pulsecore/core.h | 2 + src/pulsecore/iochannel.c | 17 +++-- src/pulsecore/iochannel.h | 2 +- src/pulsecore/pdispatch.c | 4 +- src/pulsecore/pdispatch.h | 6 +- src/pulsecore/pid.c | 15 +---- src/pulsecore/protocol-native.c | 2 +- src/pulsecore/pstream-util.c | 2 +- src/pulsecore/pstream-util.h | 4 +- src/pulsecore/pstream.c | 31 +++++---- src/pulsecore/pstream.h | 6 +- 28 files changed, 403 insertions(+), 135 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 1f8b29d0..b85f025e 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -57,7 +57,7 @@ else run_versioned automake "$VERSION" -a -c --foreign if test "x$NOCONFIGURE" = "x"; then - CFLAGS="-g -O0" ./configure --sysconfdir=/etc --enable-force-preopen "$@" + CFLAGS="-g -O0" ./configure --sysconfdir=/etc --localstatedir=/var --enable-force-preopen "$@" make clean fi fi diff --git a/configure.ac b/configure.ac index cf7b5534..a7f85ea0 100644 --- a/configure.ac +++ b/configure.ac @@ -239,7 +239,11 @@ AC_CHECK_FUNCS([lstat]) # Non-standard AC_CHECK_FUNCS(setresuid) +AC_CHECK_FUNCS(setresgid) AC_CHECK_FUNCS(setreuid) +AC_CHECK_FUNCS(setregid) +AC_CHECK_FUNCS(seteuid) +AC_CHECK_FUNCS(setegid) #### POSIX threads #### @@ -602,6 +606,48 @@ AC_SUBST(LIRC_CFLAGS) AC_SUBST(LIRC_LIBS) AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) +#### PulseAudio system group & user ##### + +AC_ARG_WITH(system_user, AS_HELP_STRING([--with-system-user=],[User for running the PulseAudio daemon as a system-wide instance (pulse)])) +if test -z "$with_system_user" ; then + PA_SYSTEM_USER=pulse +else + PA_SYSTEM_USER=$with_system_user +fi +AC_SUBST(PA_SYSTEM_USER) +AC_DEFINE_UNQUOTED(PA_SYSTEM_USER,"$PA_SYSTEM_USER", [User for running the PulseAudio system daemon]) + +AC_ARG_WITH(system_group,AS_HELP_STRING([--with-system-group=],[Group for running the PulseAudio daemon as a system-wide instance (pulse)])) +if test -z "$with_system_group" ; then + PA_SYSTEM_GROUP=pulse +else + PA_SYSTEM_GROUP=$with_system_group +fi +AC_SUBST(PA_SYSTEM_GROUP) +AC_DEFINE_UNQUOTED(PA_SYSTEM_GROUP,"$PA_SYSTEM_GROUP", [Group for the PulseAudio system daemon]) + +AC_ARG_WITH(realtime_group,AS_HELP_STRING([--with-realtime-group=],[Group for users that are allowed to start the PulseAudio daemon with realtime scheduling (realtime)])) +if test -z "$with_realtime_group" ; then + PA_REALTIME_GROUP=realtime +else + PA_REALTIME_GROUP=$with_realtime_group +fi +AC_SUBST(PA_REALTIME_GROUP) +AC_DEFINE_UNQUOTED(PA_REALTIME_GROUP,"$PA_REALTIME_GROUP", [Realtime group]) + +AC_ARG_WITH(access_group,AS_HELP_STRING([--with-access-group=],[Group which is allowed access to a system-wide PulseAudio daemon (pulse-access)])) +if test -z "$with_access_group" ; then + PA_ACCESS_GROUP=pulse-access +else + PA_ACCESS_GROUP=$with_access_group +fi +AC_SUBST(PA_ACCESS_GROUP) +AC_DEFINE_UNQUOTED(PA_ACCESS_GROUP,"$PA_ACCESS_GROUP", [Access group]) + +#### PulseAudio system runtime dir #### +PA_SYSTEM_RUNTIME_PATH="${localstatedir}/run/pulse" +AC_SUBST(PA_SYSTEM_RUNTIME_PATH) + ################################### # Output # ################################### @@ -709,8 +755,9 @@ echo " prefix: ${prefix} sysconfdir: ${sysconfdir} localstatedir: ${localstatedir} - compiler: ${CC} - cflags: ${CFLAGS} + System Runtime Path: ${PA_SYSTEM_RUNTIME_PATH} + Compiler: ${CC} + CFLAGS: ${CFLAGS} Have X11: ${ENABLE_X11} Enable OSS: ${ENABLE_OSS} Enable Alsa: ${ENABLE_ALSA} @@ -721,4 +768,8 @@ echo " Enable Async DNS: ${ENABLE_LIBASYNCNS} Enable LIRC: ${ENABLE_LIRC} Enable TCP Wrappers: ${ENABLE_TCPWRAP} + System User: ${PA_SYSTEM_USER} + System Group: ${PA_SYSTEM_GROUP} + Realtime Group: ${PA_REALTIME_GROUP} + Access Group: ${PA_ACCESS_GROUP} " diff --git a/src/Makefile.am b/src/Makefile.am index 0235741b..1a4bcb04 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,11 +30,11 @@ pulseconfdir=$(sysconfdir)/pulse # Defines # ################################### -PULSEAUDIO_BINARY=$(bindir)/pulseaudio$(EXEEXT) +PA_BINARY=$(bindir)/pulseaudio$(EXEEXT) if OS_IS_WIN32 -DEFAULT_CONFIG_DIR=%PULSE_ROOT% +PA_DEFAULT_CONFIG_DIR=%PULSE_ROOT% else -DEFAULT_CONFIG_DIR=$(pulseconfdir) +PA_DEFAULT_CONFIG_DIR=$(pulseconfdir) endif ################################### @@ -45,10 +45,10 @@ AM_CFLAGS = -I$(top_srcdir)/src AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibexecdir)\" -#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" -AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" -AM_CFLAGS += -DPULSEAUDIO_BINARY=\"$(PULSEAUDIO_BINARY)\" +AM_CFLAGS += -DPA_DLSEARCHPATH=\"$(modlibexecdir)\" +AM_CFLAGS += -DPA_DEFAULT_CONFIG_DIR=\"$(PA_DEFAULT_CONFIG_DIR)\" +AM_CFLAGS += -DPA_BINARY=\"$(PA_BINARY)\" +AM_CFLAGS += -DPA_SYSTEM_RUNTIME_PATH=\"$(PA_SYSTEM_RUNTIME_PATH)\" # This cool debug trap works on i386/gcc only AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")' diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index a106dc09..ab876edf 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -58,7 +58,8 @@ enum { ARG_RESAMPLE_METHOD, ARG_KILL, ARG_USE_PID_FILE, - ARG_CHECK + ARG_CHECK, + ARG_SYSTEM }; /* Tabel for getopt_long() */ @@ -84,6 +85,7 @@ static struct option long_options[] = { {"kill", 0, 0, ARG_KILL}, {"use-pid-file", 2, 0, ARG_USE_PID_FILE}, {"check", 0, 0, ARG_CHECK}, + {"system", 2, 0, ARG_SYSTEM}, {NULL, 0, 0, 0} }; @@ -105,6 +107,7 @@ void pa_cmdline_help(const char *argv0) { " --check Check for a running daemon\n\n" "OPTIONS:\n" + " --system[=BOOL] Run as system-wide instance\n" " -D, --daemonize[=BOOL] Daemonize after startup\n" " --fail[=BOOL] Quit when startup fails\n" " --high-priority[=BOOL] Try to set high process priority\n" @@ -276,6 +279,13 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d goto fail; } break; + + case ARG_SYSTEM: + if ((conf->system_instance = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log(__FILE__": --system expects boolean argument"); + goto fail; + } + break; default: goto fail; diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index d1afed7b..a5a62567 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -39,23 +39,15 @@ #include "daemon-conf.h" -#ifndef DEFAULT_CONFIG_DIR -# ifndef OS_IS_WIN32 -# define DEFAULT_CONFIG_DIR "/etc/pulse" -# else -# define DEFAULT_CONFIG_DIR "%PULSE_ROOT%" -# endif -#endif - #ifndef OS_IS_WIN32 # define PATH_SEP "/" #else # define PATH_SEP "\\" #endif -#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR PATH_SEP "default.pa" +#define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "default.pa" #define DEFAULT_SCRIPT_FILE_USER ".pulse" PATH_SEP "default.pa" -#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" +#define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" #define DEFAULT_CONFIG_FILE_USER ".pulse" PATH_SEP "daemon.conf" #define ENV_SCRIPT_FILE "PULSE_SCRIPT" @@ -79,7 +71,8 @@ static const pa_daemon_conf default_conf = { .log_level = PA_LOG_NOTICE, .resample_method = PA_RESAMPLER_SRC_SINC_FASTEST, .config_file = NULL, - .use_pid_file = 1 + .use_pid_file = 1, + .system_instance = 0 }; pa_daemon_conf* pa_daemon_conf_new(void) { @@ -89,9 +82,7 @@ pa_daemon_conf* pa_daemon_conf_new(void) { if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file, "r"))) fclose(f); -#ifdef DLSEARCHPATH - c->dl_search_path = pa_xstrdup(DLSEARCHPATH); -#endif + c->dl_search_path = pa_xstrdup(PA_DLSEARCHPATH); return c; } @@ -212,6 +203,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "verbose", parse_log_level, NULL }, { "resample-method", parse_resample_method, NULL }, { "use-pid-file", pa_config_parse_bool, NULL }, + { "system-instance", pa_config_parse_bool, NULL }, { NULL, NULL, NULL }, }; @@ -229,6 +221,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[11].data = c; table[12].data = c; table[13].data = &c->use_pid_file; + table[14].data = &c->system_instance; pa_xfree(c->config_file); c->config_file = NULL; @@ -295,6 +288,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file); + pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance); return pa_strbuf_tostring_free(s); } diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index c325495c..bfea7358 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -46,7 +46,8 @@ typedef struct pa_daemon_conf { module_idle_time, scache_idle_time, auto_log_target, - use_pid_file; + use_pid_file, + system_instance; char *script_commands, *dl_search_path, *default_script_file; pa_log_target_t log_target; pa_log_level_t log_level; diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 30bf3ca1..6e55c0ee 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -46,6 +46,9 @@ ## Unload autoloaded modules after being idle for this time ; module-idle-time = 20 +## Unload autoloaded sample cache entries after being idle for this time +; scache-idle-time = 20 + ## The path were to look for dynamic shared objects (DSOs aka ## plugins). You may specify more than one path seperated by ## colons. @@ -75,3 +78,6 @@ ## process per user, you better disable this option since it ## effectively disables multiple instances. ; use-pid-file = 1 + +## Run the daemon as system-wide instance, requires root priviliges +; system-instance = 0 diff --git a/src/daemon/main.c b/src/daemon/main.c index c41c69df..4961f0ca 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -37,6 +37,9 @@ #include #include #include +#include +#include + #include #ifdef HAVE_SYS_IOCTL_H @@ -149,6 +152,104 @@ static void close_pipe(int p[2]) { p[0] = p[1] = -1; } +#define set_env(key, value) putenv(pa_sprintf_malloc("%s=%s", (key), (value))) + +static int change_user(void) { + struct passwd *pw; + struct group * gr; + int r; + + if (!(pw = getpwnam(PA_SYSTEM_USER))) { + pa_log(__FILE__": Failed to find user '%s'.", PA_SYSTEM_USER); + return -1; + } + + if (!(gr = getgrnam(PA_SYSTEM_GROUP))) { + pa_log(__FILE__": Failed to find group '%s'.", PA_SYSTEM_GROUP); + return -1; + } + + pa_log_info(__FILE__": Found user '%s' (UID %lu) and group '%s' (GID %lu).", + PA_SYSTEM_USER, (unsigned long) pw->pw_uid, + PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid); + + if (pw->pw_gid != gr->gr_gid) { + pa_log(__FILE__": GID of user '%s' and of group '%s' don't match.", PA_SYSTEM_USER, PA_SYSTEM_GROUP); + return -1; + } + + if (strcmp(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH) != 0) + pa_log_warn(__FILE__": Warning: home directory of user '%s' is not '%s', ignoring.", PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH); + + if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid) < 0) { + pa_log(__FILE__": Failed to create '%s': %s", PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno)); + return -1; + } + + if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) { + pa_log(__FILE__": Failed to change group list: %s", pa_cstrerror(errno)); + return -1; + } + +#if defined(HAVE_SETRESGID) + r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid); +#elif defined(HAVE_SETEGID) + if ((r = setgid(gr->gr_gid)) >= 0) + r = setegid(gr->gr_gid); +#elif defined(HAVE_SETREGID) + r = setregid(gr->gr_gid, gr->gr_gid); +#else +#error "No API to drop priviliges" +#endif + + if (r < 0) { + pa_log(__FILE__": Failed to change GID: %s", pa_cstrerror(errno)); + return -1; + } + +#if defined(HAVE_SETRESUID) + r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid); +#elif defined(HAVE_SETEUID) + if ((r = setuid(pw->pw_uid)) >= 0) + r = seteuid(pw->pw_uid); +#elif defined(HAVE_SETREUID) + r = setreuid(pw->pw_uid, pw->pw_uid); +#else +#error "No API to drop priviliges" +#endif + + if (r < 0) { + pa_log(__FILE__": Failed to change UID: %s", pa_cstrerror(errno)); + return -1; + } + + set_env("USER", PA_SYSTEM_USER); + set_env("LOGNAME", PA_SYSTEM_GROUP); + set_env("HOME", PA_SYSTEM_RUNTIME_PATH); + + /* Relevant for pa_runtime_path() */ + set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH); + + pa_log_info(__FILE__": Successfully dropped root privileges."); + + return 0; +} + +static int create_runtime_dir(void) { + char fn[PATH_MAX]; + + pa_runtime_path(NULL, fn, sizeof(fn)); + + if (pa_make_secure_dir(fn, 0700, getuid(), getgid()) < 0) { + pa_log(__FILE__": Failed to create '%s': %s", fn, pa_cstrerror(errno)); + return -1; + } + + /* Relevant for pa_runtime_path() later on */ + set_env("PULSE_RUNTIME_PATH", fn); + return 0; +} + int main(int argc, char *argv[]) { pa_core *c; pa_strbuf *buf = NULL; @@ -172,13 +273,14 @@ int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); - pa_limit_caps(); + if (getuid() != 0) + pa_limit_caps(); #ifdef HAVE_GETUID suid_root = getuid() != 0 && geteuid() == 0; - if (suid_root && (pa_own_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) { - pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'."); + if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) { + pa_log_warn(__FILE__": WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'."); pa_drop_root(); } #else @@ -220,7 +322,8 @@ int main(int argc, char *argv[]) { if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) pa_raise_priority(); - pa_drop_caps(); + if (getuid() != 0) + pa_drop_caps(); if (suid_root) pa_drop_root(); @@ -278,6 +381,14 @@ int main(int argc, char *argv[]) { assert(conf->cmd == PA_CMD_DAEMON); } + if (getuid() == 0 && !conf->system_instance) { + pa_log(__FILE__": This program is not intended to be run as root (unless --system is specified)."); + goto finish; + } else if (getuid() != 0 && conf->system_instance) { + pa_log(__FILE__": Root priviliges required."); + goto finish; + } + if (conf->daemonize) { pid_t child; int tty_fd; @@ -362,6 +473,13 @@ int main(int argc, char *argv[]) { } chdir("/"); + umask(0022); + + if (conf->system_instance) { + if (change_user() < 0) + goto finish; + } else if (create_runtime_dir() < 0) + goto finish; if (conf->use_pid_file) { if (pa_pid_file_create() < 0) { @@ -379,12 +497,13 @@ int main(int argc, char *argv[]) { #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif - + mainloop = pa_mainloop_new(); assert(mainloop); c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); + c->is_system_instance = !!conf->system_instance; r = pa_signal_init(pa_mainloop_get_api(mainloop)); assert(r == 0); diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 28d6a08b..cd58a838 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -52,11 +52,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#ifndef DEFAULT_CONFIG_DIR -#define DEFAULT_CONFIG_DIR "/etc/pulse" -#endif - -#define DEFAULT_MATCH_TABLE_FILE DEFAULT_CONFIG_DIR"/match.table" +#define DEFAULT_MATCH_TABLE_FILE PA_DEFAULT_CONFIG_DIR"/match.table" #define DEFAULT_MATCH_TABLE_FILE_USER ".pulse/match.table" static const char* const valid_modargs[] = { diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 20728766..fa21b737 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -75,7 +75,14 @@ #include "module-simple-protocol-unix-symdef.h" #endif PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION) - PA_MODULE_USAGE("rate= format= channels= sink= source= playback= record= "SOCKET_USAGE) + PA_MODULE_USAGE("rate= " + "format= " + "channels= " + "sink= " + "source= " + "playback= " + "record= " + SOCKET_USAGE) #elif defined(USE_PROTOCOL_CLI) #include #define protocol_new pa_protocol_cli_new @@ -129,7 +136,10 @@ #endif PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) - PA_MODULE_USAGE("auth-anonymous= cookie= "AUTH_USAGE SOCKET_USAGE) + PA_MODULE_USAGE("auth-anonymous= " + "cookie= " + AUTH_USAGE + SOCKET_USAGE) #elif defined(USE_PROTOCOL_ESOUND) #include #include @@ -145,7 +155,11 @@ #include "module-esound-protocol-unix-symdef.h" #endif PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION) - PA_MODULE_USAGE("sink= source= auth-anonymous= cookie= "SOCKET_USAGE) + PA_MODULE_USAGE("sink= " + "source= " + "auth-anonymous= " + "cookie= " + SOCKET_USAGE) #else #error "Broken build system" #endif @@ -189,7 +203,6 @@ int pa__init(pa_core *c, pa_module*m) { #else pa_socket_server *s; int r; - const char *v; char tmp[PATH_MAX]; #endif @@ -241,15 +254,21 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; #else - v = pa_modargs_get_value(ma, "socket", UNIX_SOCKET); - pa_runtime_path(v, tmp, sizeof(tmp)); + + pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET), tmp, sizeof(tmp)); u->socket_path = pa_xstrdup(tmp); - if (pa_make_secure_parent_dir(tmp) < 0) { - pa_log(__FILE__": Failed to create secure socket directory."); +#if defined(USE_PROTOCOL_ESOUND) + + /* This socket doesn't reside in our own runtime dir but in + * /tmp/.esd/, hence we have to create the dir first */ + + if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, getuid(), getgid()) < 0) { + pa_log(__FILE__": Failed to create socket directory: %s\n", pa_cstrerror(errno)); goto fail; } - +#endif + if ((r = pa_unix_socket_remove_stale(tmp)) < 0) { pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s", tmp, pa_cstrerror(errno)); goto fail; @@ -324,19 +343,17 @@ void pa__done(pa_core *c, pa_module*m) { if (u->protocol_unix) protocol_free(u->protocol_unix); +#if defined(USE_PROTOCOL_ESOUND) if (u->socket_path) { - char *p; - - if ((p = pa_parent_dir(u->socket_path))) { - if (rmdir(p) < 0 && errno != ENOENT && errno != ENOTEMPTY) - pa_log(__FILE__": Failed to remove %s: %s.", u->socket_path, pa_cstrerror(errno)); - - pa_xfree(p); - } - - pa_xfree(u->socket_path); + char *p = pa_parent_dir(u->socket_path); + rmdir(p); + pa_xfree(p); } #endif + + + pa_xfree(u->socket_path); +#endif pa_xfree(u); } diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index bf2627a7..c018c520 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -611,7 +611,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void*creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { struct userdata *u = userdata; assert(p && packet && u); diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 5cebcf46..28b4f2d1 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -39,21 +39,13 @@ #include "client-conf.h" -#ifndef DEFAULT_CONFIG_DIR -# ifndef OS_IS_WIN32 -# define DEFAULT_CONFIG_DIR "/etc/pulse" -# else -# define DEFAULT_CONFIG_DIR "%PULSE_ROOT%" -# endif -#endif - #ifndef OS_IS_WIN32 # define PATH_SEP "/" #else # define PATH_SEP "\\" #endif -#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "client.conf" +#define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "client.conf" #define DEFAULT_CLIENT_CONFIG_FILE_USER ".pulse" PATH_SEP "client.conf" #define ENV_CLIENT_CONFIG_FILE "PULSE_CLIENTCONFIG" @@ -71,15 +63,17 @@ static const pa_client_conf default_conf = { .default_server = NULL, .autospawn = 0, .cookie_file = NULL, - .cookie_valid = 0 + .cookie_valid = 0, + .access_group = NULL }; pa_client_conf *pa_client_conf_new(void) { pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); - c->daemon_binary = pa_xstrdup(PULSEAUDIO_BINARY); + c->daemon_binary = pa_xstrdup(PA_BINARY); c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5"); c->cookie_file = pa_xstrdup(PA_NATIVE_COOKIE_FILE); + c->access_group = pa_xstrdup(PA_ACCESS_GROUP); return c; } @@ -92,6 +86,7 @@ void pa_client_conf_free(pa_client_conf *c) { pa_xfree(c->default_source); pa_xfree(c->default_server); pa_xfree(c->cookie_file); + pa_xfree(c->access_group); pa_xfree(c); } int pa_client_conf_load(pa_client_conf *c, const char *filename) { @@ -108,6 +103,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { { "default-server", pa_config_parse_string, NULL }, { "autospawn", pa_config_parse_bool, NULL }, { "cookie-file", pa_config_parse_string, NULL }, + { "access-group", pa_config_parse_string, NULL }, { NULL, NULL, NULL }, }; @@ -118,6 +114,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { table[4].data = &c->default_server; table[5].data = &c->autospawn; table[6].data = &c->cookie_file; + table[7].data = &c->access_group; f = filename ? fopen((fn = pa_xstrdup(filename)), "r") : diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index a532f0df..dfb1148d 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -27,7 +27,7 @@ /* A structure containing configuration data for PulseAudio clients. */ typedef struct pa_client_conf { - char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; + char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file, *access_group; int autospawn; uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; int cookie_valid; /* non-zero, when cookie is valid */ diff --git a/src/pulse/context.c b/src/pulse/context.c index 228053bc..a25e2f78 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #ifdef HAVE_SYS_WAIT_H #include @@ -270,7 +272,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { pa_context *c = userdata; assert(p); @@ -420,7 +422,23 @@ static void setup_context(pa_context *c, pa_iochannel *io) { t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); - pa_pstream_send_tagstruct_with_creds(c->pstream, t, 1); + +#ifdef SCM_CREDENTIALS +{ + struct ucred ucred; + + ucred.pid = getpid(); + ucred.uid = getuid(); + + if ((ucred.gid = pa_get_gid_of_group(PA_ACCESS_GROUP)) == (gid_t) -1) + ucred.gid = getgid(); + + pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); +} +#else + pa_pstream_send_tagstruct_with_creds(c->pstream, t, NULL); +#endif + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); @@ -680,7 +698,7 @@ int pa_context_connect( char lf[PATH_MAX]; pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); - pa_make_secure_parent_dir(lf); + pa_make_secure_parent_dir(lf, 0700, getuid(), getgid()); assert(c->autospawn_lock_fd <= 0); c->autospawn_lock_fd = pa_lock_lockfile(lf); diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 7cb85209..6375e5ef 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -84,10 +84,10 @@ #endif #ifndef OS_IS_WIN32 -#define PA_RUNTIME_PATH_PREFIX "/tmp/pulse-" +#define PA_USER_RUNTIME_PATH_PREFIX "/tmp/pulse-" #define PATH_SEP '/' #else -#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-" +#define PA_USER_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-" #define PATH_SEP '\\' #endif @@ -136,23 +136,32 @@ void pa_make_nonblock_fd(int fd) { } /** Creates a directory securely */ -int pa_make_secure_dir(const char* dir) { +int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { struct stat st; + int r; + assert(dir); #ifdef OS_IS_WIN32 - if (mkdir(dir) < 0) + r = mkdir(dir); #else - if (mkdir(dir, 0700) < 0) + { + mode_t u; + u = umask(~m); + r = mkdir(dir, m); + umask(u); + } #endif - if (errno != EEXIST) - return -1; + + if (r < 0 && errno != EEXIST) + return -1; #ifdef HAVE_CHOWN - chown(dir, getuid(), getgid()); + chown(dir, uid, gid); #endif + #ifdef HAVE_CHMOD - chmod(dir, 0700); + chmod(dir, m); #endif #ifdef HAVE_LSTAT @@ -163,8 +172,13 @@ int pa_make_secure_dir(const char* dir) { goto fail; #ifndef OS_IS_WIN32 - if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700)) + if (!S_ISDIR(st.st_mode) || + (st.st_uid != uid) || + (st.st_gid != gid) || + ((st.st_mode & 0777) != m)) { + errno = EACCES; goto fail; + } #else fprintf(stderr, "FIXME: pa_make_secure_dir()\n"); #endif @@ -180,23 +194,24 @@ fail: char *pa_parent_dir(const char *fn) { char *slash, *dir = pa_xstrdup(fn); - slash = (char*) pa_path_get_filename(dir); - if (slash == fn) + if ((slash = (char*) pa_path_get_filename(dir)) == dir) { + pa_xfree(dir); return NULL; + } *(slash-1) = 0; return dir; } /* Creates a the parent directory of the specified path securely */ -int pa_make_secure_parent_dir(const char *fn) { +int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) { int ret = -1; char *dir; if (!(dir = pa_parent_dir(fn))) goto finish; - if (pa_make_secure_dir(dir) < 0) + if (pa_make_secure_dir(dir, m, uid, gid) < 0) goto finish; ret = 0; @@ -669,6 +684,7 @@ finish: return r; } +/* Check whether the specifc user id is a member of the specified group */ int pa_uid_in_group(uid_t uid, const char *name) { char *g_buf, *p_buf; long g_n, p_n; @@ -705,6 +721,26 @@ finish: return r; } +/* Get the GID of a gfiven group, return (gid_t) -1 on failure. */ +gid_t pa_get_gid_of_group(const char *name) { + gid_t ret = (gid_t) -1; + char *g_buf; + long g_n; + struct group grbuf, *gr; + + g_n = sysconf(_SC_GETGR_R_SIZE_MAX); + g_buf = pa_xmalloc(g_n); + + if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) + goto finish; + + ret = gr->gr_gid; + +finish: + pa_xfree(g_buf); + return ret; +} + #else /* HAVE_GRP_H */ int pa_own_uid_in_group(const char *name, gid_t *gid) { @@ -1003,7 +1039,7 @@ int pa_endswith(const char *s, const char *sfx) { * if fn is non-null and starts with / return fn in s * otherwise append fn to the run time path and return it in s */ char *pa_runtime_path(const char *fn, char *s, size_t l) { - char u[256]; + const char *e; #ifndef OS_IS_WIN32 if (fn && *fn == '/') @@ -1012,10 +1048,22 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) { #endif return pa_strlcpy(s, fn, l); - if (fn) - snprintf(s, l, "%s%s%c%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn); - else - snprintf(s, l, "%s%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u))); + if ((e = getenv("PULSE_RUNTIME_PATH"))) { + + if (fn) + snprintf(s, l, "%s%c%s", e, PATH_SEP, fn); + else + snprintf(s, l, "%s", e); + + } else { + char u[256]; + + if (fn) + snprintf(s, l, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn); + else + snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u))); + } + #ifdef OS_IS_WIN32 { diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 864a96ec..db764de1 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -33,8 +33,8 @@ struct timeval; void pa_make_nonblock_fd(int fd); -int pa_make_secure_dir(const char* dir); -int pa_make_secure_parent_dir(const char *fn); +int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid); +int pa_make_secure_parent_dir(const char *fn, mode_t, uid_t uid, gid_t gid); ssize_t pa_read(int fd, void *buf, size_t count, int *type); ssize_t pa_write(int fd, const void *buf, size_t count, int *type); @@ -66,6 +66,7 @@ const char *pa_strsignal(int sig); int pa_own_uid_in_group(const char *name, gid_t *gid); int pa_uid_in_group(uid_t uid, const char *name); +gid_t pa_get_gid_of_group(const char *name); int pa_lock_fd(int fd, int b); diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 7c780ea8..d6af3ca9 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -46,7 +46,8 @@ pa_core* pa_core_new(pa_mainloop_api *m) { pa_core* c; - c = pa_xmalloc(sizeof(pa_core)); + + c = pa_xnew(pa_core, 1); c->mainloop = m; c->clients = pa_idxset_new(NULL, NULL); @@ -88,6 +89,8 @@ pa_core* pa_core_new(pa_mainloop_api *m) { c->resample_method = PA_RESAMPLER_SRC_SINC_FASTEST; + c->is_system_instance = 0; + pa_property_init(c); pa_random(&c->cookie, sizeof(c->cookie)); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 261c5f75..61f17432 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -71,6 +71,8 @@ struct pa_core { pa_time_event *scache_auto_unload_event; pa_resample_method_t resample_method; + + int is_system_instance; }; pa_core* pa_core_new(pa_mainloop_api *m); diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 15aa8e35..852e960e 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -263,12 +263,12 @@ int pa_iochannel_creds_enable(pa_iochannel *io) { return 0; } -ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l) { +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const struct ucred *ucred) { ssize_t r; struct msghdr mh; struct iovec iov; uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))]; - struct ucred *ucred; + struct ucred *u; struct cmsghdr *cmsg; assert(io); @@ -286,10 +286,15 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_CREDENTIALS; - ucred = (struct ucred*) CMSG_DATA(cmsg); - ucred->pid = getpid(); - ucred->uid = getuid(); - ucred->gid = getgid(); + u = (struct ucred*) CMSG_DATA(cmsg); + + if (ucred) + *u = *ucred; + else { + u->pid = getpid(); + u->uid = getuid(); + u->gid = getgid(); + } memset(&mh, 0, sizeof(mh)); mh.msg_name = NULL; diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h index 64cf331e..3b5cba1c 100644 --- a/src/pulsecore/iochannel.h +++ b/src/pulsecore/iochannel.h @@ -54,7 +54,7 @@ int pa_iochannel_creds_enable(pa_iochannel *io); struct ucred; -ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l); +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const struct ucred *ucred); ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid); int pa_iochannel_is_readable(pa_iochannel*io); diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 5b76b432..9bc20da4 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -180,7 +180,7 @@ static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command, pa_pdispatch_unref(pd); } -int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const void *creds, void *userdata) { +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const struct ucred *creds, void *userdata) { uint32_t tag, command; pa_tagstruct *ts = NULL; int ret = -1; @@ -310,7 +310,7 @@ pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd) { return pd; } -const void * pa_pdispatch_creds(pa_pdispatch *pd) { +const struct ucred * pa_pdispatch_creds(pa_pdispatch *pd) { assert(pd); assert(pd->ref >= 1); diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h index 07620e5a..18073502 100644 --- a/src/pulsecore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -28,6 +28,8 @@ #include #include +struct ucred; + typedef struct pa_pdispatch pa_pdispatch; typedef void (*pa_pdispatch_cb_t)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); @@ -37,7 +39,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_cb_t*table void pa_pdispatch_unref(pa_pdispatch *pd); pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); -int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const void*creds, void *userdata); +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const struct ucred*creds, void *userdata); void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t callback, void *userdata, pa_free_cb_t free_cb); @@ -48,6 +50,6 @@ void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, pa_pdispatch_drain_callba /* Remove all reply slots with the give userdata parameter */ void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata); -const void * pa_pdispatch_creds(pa_pdispatch *pd); +const struct ucred * pa_pdispatch_creds(pa_pdispatch *pd); #endif diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index 0ad76a6e..044d223d 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -79,13 +79,10 @@ static pid_t read_pid(const char *fn, int fd) { static int open_pid_file(const char *fn, int mode) { int fd = -1; - int lock = -1; for (;;) { struct stat st; - pa_make_secure_parent_dir(fn); - if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) { if (mode != O_RDONLY || errno != ENOENT) pa_log_warn(__FILE__": WARNING: failed to open PID file '%s': %s", @@ -123,10 +120,8 @@ static int open_pid_file(const char *fn, int mode) { fail: - if (fd < 0) { - if (lock >= 0) - pa_lock_fd(fd, 0); - + if (fd >= 0) { + pa_lock_fd(fd, 0); close(fd); } @@ -199,7 +194,6 @@ int pa_pid_file_remove(void) { char fn[PATH_MAX]; int ret = -1; pid_t pid; - char *p; pa_runtime_path("pid", fn, sizeof(fn)); @@ -235,11 +229,6 @@ int pa_pid_file_remove(void) { goto fail; } - if ((p = pa_parent_dir(fn))) { - rmdir(p); - pa_xfree(p); - } - ret = 0; fail: diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 784610bd..14f880d7 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2100,7 +2100,7 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC /*** pstream callbacks ***/ -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { struct connection *c = userdata; assert(p && packet && packet->data && c); diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c index 3a995324..09d6f2fa 100644 --- a/src/pulsecore/pstream-util.c +++ b/src/pulsecore/pstream-util.c @@ -29,7 +29,7 @@ #include "pstream-util.h" -void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, int creds) { +void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const struct ucred *creds) { size_t length; uint8_t *data; pa_packet *packet; diff --git a/src/pulsecore/pstream-util.h b/src/pulsecore/pstream-util.h index fc6d18c0..c60000a8 100644 --- a/src/pulsecore/pstream-util.h +++ b/src/pulsecore/pstream-util.h @@ -26,8 +26,10 @@ #include #include +struct ucred; + /* The tagstruct is freed!*/ -void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, int creds); +void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const struct ucred *creds); #define pa_pstream_send_tagstruct(p, t) pa_pstream_send_tagstruct_with_creds((p), (t), 0) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 7992ccb6..7ef49305 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #ifdef HAVE_NETINET_IN_H #include @@ -69,6 +71,7 @@ struct item_info { pa_packet *packet; #ifdef SCM_CREDENTIALS int with_creds; + struct ucred creds; #endif }; @@ -112,9 +115,8 @@ struct pa_pstream { pa_memblock_stat *memblock_stat; #ifdef SCM_CREDENTIALS - int send_creds_now; - struct ucred ucred; - int creds_valid; + struct ucred read_creds, write_creds; + int read_creds_valid, send_creds_now; #endif }; @@ -216,7 +218,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta #ifdef SCM_CREDENTIALS p->send_creds_now = 0; - p->creds_valid = 0; + p->read_creds_valid = 0; #endif return p; } @@ -256,7 +258,7 @@ static void pstream_free(pa_pstream *p) { pa_xfree(p); } -void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, int with_creds) { +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred *creds) { struct item_info *i; assert(p && packet && p->ref >= 1); @@ -269,7 +271,8 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, int with_creds) { i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); #ifdef SCM_CREDENTIALS - i->with_creds = with_creds; + if ((i->with_creds = !!creds)) + i->creds = *creds; #endif pa_queue_push(p->send_queue, i); @@ -332,7 +335,9 @@ static void prepare_next_write_item(pa_pstream *p) { } #ifdef SCM_CREDENTIALS - p->send_creds_now = p->write.current->with_creds; + if ((p->send_creds_now = p->write.current->with_creds)) + p->write_creds = p->write.current->creds; + #endif } @@ -362,7 +367,7 @@ static int do_write(pa_pstream *p) { #ifdef SCM_CREDENTIALS if (p->send_creds_now) { - if ((r = pa_iochannel_write_with_creds(p->io, d, l)) < 0) + if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0) return -1; p->send_creds_now = 0; @@ -403,12 +408,12 @@ static int do_read(pa_pstream *p) { #ifdef SCM_CREDENTIALS { - int b; + int b = 0; - if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->ucred, &b)) <= 0) + if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->read_creds, &b)) <= 0) return -1; - p->creds_valid = p->creds_valid || b; + p->read_creds_valid = p->read_creds_valid || b; } #else if ((r = pa_iochannel_read(p->io, d, l)) <= 0) @@ -491,7 +496,7 @@ static int do_read(pa_pstream *p) { if (p->recieve_packet_callback) #ifdef SCM_CREDENTIALS - p->recieve_packet_callback(p, p->read.packet, p->creds_valid ? &p->ucred : NULL, p->recieve_packet_callback_userdata); + p->recieve_packet_callback(p, p->read.packet, p->read_creds_valid ? &p->read_creds : NULL, p->recieve_packet_callback_userdata); #else p->recieve_packet_callback(p, p->read.packet, NULL, p->recieve_packet_callback_userdata); #endif @@ -502,7 +507,7 @@ static int do_read(pa_pstream *p) { p->read.index = 0; #ifdef SCM_CREDENTIALS - p->creds_valid = 0; + p->read_creds_valid = 0; #endif } } diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h index 1a2932d4..39cb7591 100644 --- a/src/pulsecore/pstream.h +++ b/src/pulsecore/pstream.h @@ -31,9 +31,11 @@ #include #include +struct ucred; + typedef struct pa_pstream pa_pstream; -typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata); +typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata); typedef void (*pa_pstream_memblock_cb_t)(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata); typedef void (*pa_pstream_notify_cb_t)(pa_pstream *p, void *userdata); @@ -41,7 +43,7 @@ pa_pstream* pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta void pa_pstream_unref(pa_pstream*p); pa_pstream* pa_pstream_ref(pa_pstream*p); -void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, int with_creds); +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred *creds); void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk); void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata); -- cgit