daemon: added "group" configuration option
The "group" configuration option is similar to "user" as it sets user set what group MPD shall run as. With "user" option, MPD changed GID to the GID of the user, however, more control could be desired. Moreover, the patch changes the way of checking whether no setuid(2)/setgid(2) is required -- previously user names were compered, now UID and GIDs are compered (ie. the one we already have (getuid(2)/getgid(2)) with the one we want to change to).
This commit is contained in:

committed by
Max Kellermann

parent
4100035b19
commit
d718a8b59d
@@ -61,6 +61,13 @@
|
|||||||
#
|
#
|
||||||
#user "nobody"
|
#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
|
# 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.
|
# should be paid if this is assigned to anything other then the default, any.
|
||||||
# This setting can deny access to control of the daemon.
|
# This setting can deny access to control of the daemon.
|
||||||
|
@@ -61,6 +61,7 @@ static struct config_entry config_entries[] = {
|
|||||||
{ .name = CONF_PID_FILE, false, false },
|
{ .name = CONF_PID_FILE, false, false },
|
||||||
{ .name = CONF_STATE_FILE, false, false },
|
{ .name = CONF_STATE_FILE, false, false },
|
||||||
{ .name = CONF_USER, false, false },
|
{ .name = CONF_USER, false, false },
|
||||||
|
{ .name = CONF_GROUP, false, false },
|
||||||
{ .name = CONF_BIND_TO_ADDRESS, true, false },
|
{ .name = CONF_BIND_TO_ADDRESS, true, false },
|
||||||
{ .name = CONF_PORT, false, false },
|
{ .name = CONF_PORT, false, false },
|
||||||
{ .name = CONF_LOG_LEVEL, false, false },
|
{ .name = CONF_LOG_LEVEL, false, false },
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#define CONF_PID_FILE "pid_file"
|
#define CONF_PID_FILE "pid_file"
|
||||||
#define CONF_STATE_FILE "state_file"
|
#define CONF_STATE_FILE "state_file"
|
||||||
#define CONF_USER "user"
|
#define CONF_USER "user"
|
||||||
|
#define CONF_GROUP "group"
|
||||||
#define CONF_BIND_TO_ADDRESS "bind_to_address"
|
#define CONF_BIND_TO_ADDRESS "bind_to_address"
|
||||||
#define CONF_PORT "port"
|
#define CONF_PORT "port"
|
||||||
#define CONF_LOG_LEVEL "log_level"
|
#define CONF_LOG_LEVEL "log_level"
|
||||||
|
48
src/daemon.c
48
src/daemon.c
@@ -45,14 +45,17 @@
|
|||||||
static char *user_name;
|
static char *user_name;
|
||||||
|
|
||||||
/** the Unix user id which MPD runs as */
|
/** 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 */
|
/** 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 */
|
/** the absolute path of the pidfile */
|
||||||
static char *pidfile;
|
static char *pidfile;
|
||||||
|
|
||||||
|
/* whether "group" conf. option was given */
|
||||||
|
static bool had_group = false;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -107,16 +110,19 @@ daemonize_set_user(void)
|
|||||||
if (user_name == NULL)
|
if (user_name == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* get uid */
|
/* set gid */
|
||||||
if (setgid(user_gid) == -1) {
|
if (user_gid != (gid_t)-1 && user_gid != getgid()) {
|
||||||
g_error("cannot setgid for user \"%s\": %s",
|
if (setgid(user_gid) == -1) {
|
||||||
user_name, g_strerror(errno));
|
g_error("cannot setgid to %d: %s",
|
||||||
|
(int)user_gid, g_strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _BSD_SOURCE
|
#ifdef _BSD_SOURCE
|
||||||
/* init suplementary groups
|
/* init suplementary groups
|
||||||
* (must be done before we change our uid)
|
* (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 "
|
g_warning("cannot init supplementary groups "
|
||||||
"of user \"%s\": %s",
|
"of user \"%s\": %s",
|
||||||
user_name, g_strerror(errno));
|
user_name, g_strerror(errno));
|
||||||
@@ -124,7 +130,8 @@ daemonize_set_user(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* set uid */
|
/* 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",
|
g_error("cannot change to uid of user \"%s\": %s",
|
||||||
user_name, g_strerror(errno));
|
user_name, g_strerror(errno));
|
||||||
}
|
}
|
||||||
@@ -196,25 +203,32 @@ daemonize(bool detach)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
daemonize_init(const char *user, const char *_pidfile)
|
daemonize_init(const char *user, const char *group, const char *_pidfile)
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if (user != NULL && strcmp(user, g_get_user_name()) != 0) {
|
if (user) {
|
||||||
struct passwd *pwd;
|
struct passwd *pwd = getpwnam(user);
|
||||||
|
if (!pwd)
|
||||||
user_name = g_strdup(user);
|
g_error("no such user \"%s\"", user);
|
||||||
|
|
||||||
pwd = getpwnam(user_name);
|
|
||||||
if (pwd == NULL)
|
|
||||||
g_error("no such user \"%s\"", user_name);
|
|
||||||
|
|
||||||
user_uid = pwd->pw_uid;
|
user_uid = pwd->pw_uid;
|
||||||
user_gid = pwd->pw_gid;
|
user_gid = pwd->pw_gid;
|
||||||
|
|
||||||
|
user_name = g_strdup(user);
|
||||||
|
|
||||||
/* this is needed by libs such as arts */
|
/* this is needed by libs such as arts */
|
||||||
g_setenv("HOME", pwd->pw_dir, true);
|
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);
|
pidfile = g_strdup(_pidfile);
|
||||||
#else
|
#else
|
||||||
(void)user;
|
(void)user;
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
daemonize_init(const char *user, const char *pidfile);
|
daemonize_init(const char *user, const char *group, const char *pidfile);
|
||||||
|
|
||||||
void
|
void
|
||||||
daemonize_finish(void);
|
daemonize_finish(void);
|
||||||
|
@@ -94,6 +94,7 @@ static void
|
|||||||
glue_daemonize_init(const struct options *options)
|
glue_daemonize_init(const struct options *options)
|
||||||
{
|
{
|
||||||
daemonize_init(config_get_string(CONF_USER, NULL),
|
daemonize_init(config_get_string(CONF_USER, NULL),
|
||||||
|
config_get_string(CONF_GROUP, NULL),
|
||||||
config_get_path(CONF_PID_FILE));
|
config_get_path(CONF_PID_FILE));
|
||||||
|
|
||||||
if (options->kill)
|
if (options->kill)
|
||||||
|
Reference in New Issue
Block a user