summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.exec.xml12
-rw-r--r--src/cgroup.c44
-rw-r--r--src/cgroup.h6
-rw-r--r--src/dbus-execute.h6
-rw-r--r--src/execute.c13
-rw-r--r--src/execute.h2
-rw-r--r--src/load-fragment.c3
7 files changed, 81 insertions, 5 deletions
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index ffc257383d..b9a37da38e 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -630,6 +630,18 @@
</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>
<listitem><para>Controls which
diff --git a/src/cgroup.c b/src/cgroup.c
index 0c6f20d4b7..a3491582be 100644
--- a/src/cgroup.c
+++ b/src/cgroup.c
@@ -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);
diff --git a/src/cgroup.h b/src/cgroup.h
index c6dff4313e..f33d8440e6 100644
--- a/src/cgroup.h
+++ b/src/cgroup.h
@@ -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);
diff --git a/src/dbus-execute.h b/src/dbus-execute.h
index 56c5bcd4f4..49ad6cb82a 100644
--- a/src/dbus-execute.h
+++ b/src/dbus-execute.h
@@ -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 }, \
diff --git a/src/execute.c b/src/execute.c
index b00ccde4d5..6f0f5d09d9 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -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);
diff --git a/src/execute.h b/src/execute.h
index 55bae24a21..a2d9072357 100644
--- a/src/execute.h
+++ b/src/execute.h
@@ -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
diff --git a/src/load-fragment.c b/src/load-fragment.c
index 352db6b385..0c2ef91652 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -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" },