MEDIUM: mworker-prog: Add user/group options to program section

This patch adds "user" and "group" config options to the "program"
section so the configured command can be run as a different user.
This commit is contained in:
Andrew Heberle 2019-07-12 11:50:26 +08:00 committed by William Lallemand
parent 7df8ca6296
commit 9723696759
3 changed files with 80 additions and 0 deletions

View File

@ -2232,6 +2232,14 @@ command <command> [arguments*]
mandatory option of the program section. Arguments containing spaces must mandatory option of the program section. Arguments containing spaces must
be enclosed in quotes or double quotes or be prefixed by a backslash. be enclosed in quotes or double quotes or be prefixed by a backslash.
user <user name>
Changes the executed command user ID to the <user name> from /etc/passwd.
See also "group".
group <group name>
Changes the executed command group ID to the <group name> from /etc/group.
See also "user".
option start-on-reload option start-on-reload
no option start-on-reload no option start-on-reload
Start (or not) a new instance of the program upon a reload of the master. Start (or not) a new instance of the program upon a reload of the master.

View File

@ -215,6 +215,8 @@ struct mworker_proc {
int timestamp; int timestamp;
struct server *srv; /* the server entry in the master proxy */ struct server *srv; /* the server entry in the master proxy */
struct list list; struct list list;
int uid;
int gid;
}; };
extern struct global global; extern struct global global;

View File

@ -15,6 +15,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <grp.h> #include <grp.h>
#include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -91,6 +92,23 @@ int mworker_ext_launch_all()
mworker_cleanlisteners(); mworker_cleanlisteners();
mworker_cleantasks(); mworker_cleantasks();
/* setgid / setuid */
if (child->gid != -1) {
if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
" without 'uid'/'user' is generally useless.\n", child->command[0]);
if (setgid(child->gid) == -1) {
ha_alert("[%s.main()] Cannot set gid %d.\n", child->command[0], child->gid);
exit(1);
}
}
if (child->uid != -1 && setuid(child->uid) == -1) {
ha_alert("[%s.main()] Cannot set uid %d.\n", child->command[0], child->gid);
exit(1);
}
execvp(child->command[0], child->command); execvp(child->command[0], child->command);
ha_alert("Cannot execute %s: %s\n", child->command[0], strerror(errno)); ha_alert("Cannot execute %s: %s\n", child->command[0], strerror(errno));
@ -143,6 +161,8 @@ int cfg_parse_program(const char *file, int linenum, char **args, int kwm)
ext_child->ipc_fd[0] = -1; ext_child->ipc_fd[0] = -1;
ext_child->ipc_fd[1] = -1; ext_child->ipc_fd[1] = -1;
ext_child->options |= PROC_O_START_RELOAD; /* restart the programs by default */ ext_child->options |= PROC_O_START_RELOAD; /* restart the programs by default */
ext_child->uid = -1;
ext_child->gid = -1;
LIST_INIT(&ext_child->list); LIST_INIT(&ext_child->list);
list_for_each_entry(child, &proc_list, list) { list_for_each_entry(child, &proc_list, list) {
@ -219,6 +239,56 @@ int cfg_parse_program(const char *file, int linenum, char **args, int kwm)
err_code |= ERR_ALERT | ERR_FATAL; err_code |= ERR_ALERT | ERR_FATAL;
goto error; goto error;
} }
} else if (!strcmp(args[0], "user")) {
struct passwd *ext_child_user;
if (*(args[1]) == '\0') {
ha_alert("parsing [%s:%d]: '%s' expects a user name.\n",
file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto error;
}
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto error;
if (ext_child->uid != -1) {
ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
err_code |= ERR_ALERT;
goto out;
}
ext_child_user = getpwnam(args[1]);
if (ext_child_user != NULL) {
ext_child->uid = (int)ext_child_user->pw_uid;
} else {
ha_alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
err_code |= ERR_ALERT | ERR_FATAL;
}
} else if (!strcmp(args[0], "group")) {
struct group *ext_child_group;
if (*(args[1]) == '\0') {
ha_alert("parsing [%s:%d]: '%s' expects a group name.\n",
file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto error;
}
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto error;
if (ext_child->gid != -1) {
ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
err_code |= ERR_ALERT;
goto out;
}
ext_child_group = getgrnam(args[1]);
if (ext_child_group != NULL) {
ext_child->gid = (int)ext_child_group->gr_gid;
} else {
ha_alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
err_code |= ERR_ALERT | ERR_FATAL;
}
} else { } else {
ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "program"); ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "program");
err_code |= ERR_ALERT | ERR_FATAL; err_code |= ERR_ALERT | ERR_FATAL;