diff options
-rw-r--r-- | doc/mpdconf.example | 7 | ||||
-rw-r--r-- | src/conf.c | 1 | ||||
-rw-r--r-- | src/conf.h | 1 | ||||
-rw-r--r-- | src/daemon.c | 48 | ||||
-rw-r--r-- | src/daemon.h | 2 | ||||
-rw-r--r-- | src/main.c | 1 |
6 files changed, 42 insertions, 18 deletions
diff --git a/doc/mpdconf.example b/doc/mpdconf.example index 7574ffc87..1dce635b2 100644 --- a/doc/mpdconf.example +++ b/doc/mpdconf.example @@ -61,6 +61,13 @@ # #user "nobody" # +# This setting specifies the group that MPD will run as. If not specified +# primary group of user specified with "user" setting will be used (if set). +# This is useful if MPD needs to be a member of group such as "audio" to +# have permission to use sound card. +# +#group "nogroup" +# # This setting sets the address for the daemon to listen on. Careful attention # should be paid if this is assigned to anything other then the default, any. # This setting can deny access to control of the daemon. diff --git a/src/conf.c b/src/conf.c index 777cbe6ed..a423b5d2d 100644 --- a/src/conf.c +++ b/src/conf.c @@ -61,6 +61,7 @@ static struct config_entry config_entries[] = { { .name = CONF_PID_FILE, false, false }, { .name = CONF_STATE_FILE, false, false }, { .name = CONF_USER, false, false }, + { .name = CONF_GROUP, false, false }, { .name = CONF_BIND_TO_ADDRESS, true, false }, { .name = CONF_PORT, false, false }, { .name = CONF_LOG_LEVEL, false, false }, diff --git a/src/conf.h b/src/conf.h index 669542167..fda3a12b9 100644 --- a/src/conf.h +++ b/src/conf.h @@ -34,6 +34,7 @@ #define CONF_PID_FILE "pid_file" #define CONF_STATE_FILE "state_file" #define CONF_USER "user" +#define CONF_GROUP "group" #define CONF_BIND_TO_ADDRESS "bind_to_address" #define CONF_PORT "port" #define CONF_LOG_LEVEL "log_level" diff --git a/src/daemon.c b/src/daemon.c index 33b2953a9..e7fcd0986 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -45,14 +45,17 @@ static char *user_name; /** the Unix user id which MPD runs as */ -static uid_t user_uid; +static uid_t user_uid = (uid_t)-1; /** the Unix group id which MPD runs as */ -static gid_t user_gid; +static gid_t user_gid = (pid_t)-1; /** the absolute path of the pidfile */ static char *pidfile; +/* whether "group" conf. option was given */ +static bool had_group = false; + #endif void @@ -107,16 +110,19 @@ daemonize_set_user(void) if (user_name == NULL) return; - /* get uid */ - if (setgid(user_gid) == -1) { - g_error("cannot setgid for user \"%s\": %s", - user_name, g_strerror(errno)); + /* set gid */ + if (user_gid != (gid_t)-1 && user_gid != getgid()) { + if (setgid(user_gid) == -1) { + g_error("cannot setgid to %d: %s", + (int)user_gid, g_strerror(errno)); + } } + #ifdef _BSD_SOURCE /* init suplementary groups * (must be done before we change our uid) */ - if (initgroups(user_name, user_gid) == -1) { + if (!had_group && initgroups(user_name, user_gid) == -1) { g_warning("cannot init supplementary groups " "of user \"%s\": %s", user_name, g_strerror(errno)); @@ -124,7 +130,8 @@ daemonize_set_user(void) #endif /* set uid */ - if (setuid(user_uid) == -1) { + if (user_uid != (uid_t)-1 && user_uid != getuid() && + setuid(user_uid) == -1) { g_error("cannot change to uid of user \"%s\": %s", user_name, g_strerror(errno)); } @@ -196,25 +203,32 @@ daemonize(bool detach) } void -daemonize_init(const char *user, const char *_pidfile) +daemonize_init(const char *user, const char *group, const char *_pidfile) { #ifndef WIN32 - if (user != NULL && strcmp(user, g_get_user_name()) != 0) { - struct passwd *pwd; - - user_name = g_strdup(user); - - pwd = getpwnam(user_name); - if (pwd == NULL) - g_error("no such user \"%s\"", user_name); + if (user) { + struct passwd *pwd = getpwnam(user); + if (!pwd) + g_error("no such user \"%s\"", user); user_uid = pwd->pw_uid; user_gid = pwd->pw_gid; + user_name = g_strdup(user); + /* this is needed by libs such as arts */ g_setenv("HOME", pwd->pw_dir, true); } + if (group) { + struct group *grp = grp = getgrnam(group); + if (!grp) + g_error("no such group \"%s\"", group); + user_gid = grp->gr_gid; + had_group = true; + } + + pidfile = g_strdup(_pidfile); #else (void)user; diff --git a/src/daemon.h b/src/daemon.h index 5b3f9a7dc..46a4c4f71 100644 --- a/src/daemon.h +++ b/src/daemon.h @@ -23,7 +23,7 @@ #include <stdbool.h> void -daemonize_init(const char *user, const char *pidfile); +daemonize_init(const char *user, const char *group, const char *pidfile); void daemonize_finish(void); diff --git a/src/main.c b/src/main.c index 3d0aaabc9..54b31c1f8 100644 --- a/src/main.c +++ b/src/main.c @@ -94,6 +94,7 @@ static void glue_daemonize_init(const struct options *options) { daemonize_init(config_get_string(CONF_USER, NULL), + config_get_string(CONF_GROUP, NULL), config_get_path(CONF_PID_FILE)); if (options->kill) |