exec: add ControlGroupModify= switch to allow changing access mode to cgroups fs

This commit is contained in:
Lennart Poettering 2011-06-30 00:11:25 +02:00
parent 8585357a0e
commit 64747e2d4b
7 changed files with 81 additions and 5 deletions

View File

@ -629,6 +629,18 @@
for details.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ControlGroupModify=</varname></term>
<listitem><para>Takes a boolean
argument. If true, the control groups
created for this unit will be owned by
ther user specified with
<varname>User=</varname> (and the
configured group), and he can create
subgroups as well as add processes to
the group.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>CapabilityBoundingSet=</varname></term>

View File

@ -140,6 +140,50 @@ int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid) {
return 0;
}
int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid) {
assert(b);
if (!b->realized)
return -EINVAL;
return cg_set_group_access(b->controller, b->path, mode, uid, gid);
}
int cgroup_bonding_set_group_access_list(CGroupBonding *first, mode_t mode, uid_t uid, gid_t gid) {
CGroupBonding *b;
int r;
LIST_FOREACH(by_unit, b, first) {
r = cgroup_bonding_set_group_access(b, mode, uid, gid);
if (r < 0)
return r;
}
return 0;
}
int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid) {
assert(b);
if (!b->realized)
return -EINVAL;
return cg_set_task_access(b->controller, b->path, mode, uid, gid);
}
int cgroup_bonding_set_task_access_list(CGroupBonding *first, mode_t mode, uid_t uid, gid_t gid) {
CGroupBonding *b;
int r;
LIST_FOREACH(by_unit, b, first) {
r = cgroup_bonding_set_task_access(b, mode, uid, gid);
if (r < 0)
return r;
}
return 0;
}
int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s) {
assert(b);
assert(sig >= 0);

View File

@ -59,6 +59,12 @@ void cgroup_bonding_free_list(CGroupBonding *first, bool remove_or_trim);
int cgroup_bonding_install(CGroupBonding *b, pid_t pid);
int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid);
int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
int cgroup_bonding_set_group_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
int cgroup_bonding_set_task_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s);
int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s);

View File

@ -91,7 +91,8 @@
" <property name=\"SameProcessGroup\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n" \
" <property name=\"UtmpIdentifier\" type=\"s\" access=\"read\"/>\n"
" <property name=\"UtmpIdentifier\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"ControlGroupModify\" type=\"b\" access=\"read\"/>\n"
#define BUS_EXEC_COMMAND_INTERFACE(name) \
" <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n"
@ -153,7 +154,8 @@
{ interface, "SameProcessGroup", bus_property_append_bool, "b", &(context).same_pgrp }, \
{ interface, "KillMode", bus_execute_append_kill_mode, "s", &(context).kill_mode }, \
{ interface, "KillSignal", bus_property_append_int, "i", &(context).kill_signal }, \
{ interface, "UtmpIdentifier", bus_property_append_string, "s", (context).utmp_id }
{ interface, "UtmpIdentifier", bus_property_append_string, "s", (context).utmp_id }, \
{ interface, "ControlGroupModify", bus_property_append_bool, "b", &(context).control_group_modify }
#define BUS_EXEC_STATUS_PROPERTIES(interface, estatus, prefix) \
{ interface, prefix "StartTimestamp", bus_property_append_usec, "t", &(estatus).start_timestamp.realtime }, \

View File

@ -1246,6 +1246,13 @@ int exec_spawn(ExecCommand *command,
r = EXIT_STDIN;
goto fail_child;
}
if (cgroup_bondings && context->control_group_modify)
if (cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid) < 0 ||
cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid) < 0) {
r = EXIT_CGROUP;
goto fail_child;
}
}
#ifdef HAVE_PAM
@ -1649,12 +1656,14 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
"%sWorkingDirectory: %s\n"
"%sRootDirectory: %s\n"
"%sNonBlocking: %s\n"
"%sPrivateTmp: %s\n",
"%sPrivateTmp: %s\n"
"%sControlGroupModify: %s\n",
prefix, c->umask,
prefix, c->working_directory ? c->working_directory : "/",
prefix, c->root_directory ? c->root_directory : "/",
prefix, yes_no(c->non_blocking),
prefix, yes_no(c->private_tmp));
prefix, yes_no(c->private_tmp),
prefix, yes_no(c->control_group_modify));
STRV_FOREACH(e, c->environment)
fprintf(f, "%sEnvironment: %s\n", prefix, *e);

View File

@ -160,6 +160,8 @@ struct ExecContext {
bool non_blocking;
bool private_tmp;
bool control_group_modify;
/* This is not exposed to the user but available
* internally. We need it to make sure that whenever we spawn
* /bin/mount it is run in the same process group as us so

View File

@ -1911,7 +1911,8 @@ static int load_from_path(Unit *u, const char *path) {
{ "KillMode", config_parse_kill_mode, 0, &(context).kill_mode, section }, \
{ "KillSignal", config_parse_kill_signal, 0, &(context).kill_signal, section }, \
{ "SendSIGKILL", config_parse_bool, 0, &(context).send_sigkill, section }, \
{ "UtmpIdentifier", config_parse_string_printf, 0, &(context).utmp_id, section }
{ "UtmpIdentifier", config_parse_string_printf, 0, &(context).utmp_id, section }, \
{ "ControlGroupModify", config_parse_bool, 0, &(context).control_group_modify, section }
const ConfigItem items[] = {
{ "Names", config_parse_names, 0, u, "Unit" },