[CRIU] [PATCH 1/2] cgroup: treat devices as "special" properties
Tycho Andersen
tycho.andersen at canonical.com
Mon Sep 12 17:52:40 PDT 2016
v2: don't try to write "" to devices.allow, just skip it since we write 'a'
to devices.deny everywhere anyway.
v3: leave cgroup prop name as "devices.list" so it is caught in the later
tests for special-ness. also, don't write the last devices entry twice.
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
CC: Cyrill Gorcunov <gorcunov at openvz.org>
---
criu/cgroup.c | 133 ++++++++++++++++++++++++++++++++--------------------------
1 file changed, 73 insertions(+), 60 deletions(-)
diff --git a/criu/cgroup.c b/criu/cgroup.c
index 431ba30..51c6fa4 100644
--- a/criu/cgroup.c
+++ b/criu/cgroup.c
@@ -946,6 +946,7 @@ static int ctrl_dir_and_opt(CgControllerEntry *ctl, char *dir, int ds,
static const char *special_props[] = {
"cpuset.cpus",
"cpuset.mems",
+ "devices.list",
"memory.kmem.limit_in_bytes",
"memory.swappiness",
"memory.oom_control",
@@ -1319,64 +1320,7 @@ static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **e
if (special)
continue;
- /* The devices cgroup must be restored in a
- * special way: only the contents of
- * devices.list can be read, and it is a
- * whitelist of all the devices the cgroup is
- * allowed to create. To re-creat this
- * whitelist, we first deny everything via
- * devices.deny, and then write the list back
- * into devices.allow.
- *
- * Further, we must have a write() call for
- * each line, because the kernel only parses
- * the first line of any write().
- */
- if (!strcmp(e->properties[j]->name, "devices.list")) {
- CgroupPropEntry *pe = e->properties[j];
- char *old_val = pe->value, *old_name = pe->name;
- int ret;
- char *pos;
-
- /* A bit of a fudge here. These are
- * write only by owner by default, but
- * the container engine could have
- * changed the perms. We should come up
- * with a better way to restore all of
- * this stuff.
- */
- pe->perms->mode = 0200;
-
- pe->name = "devices.deny";
- pe->value = "a";
- ret = restore_cgroup_prop(e->properties[j], path, off2);
- pe->name = old_name;
- pe->value = old_val;
-
- if (ret < 0)
- return -1;
-
- pe->name = xstrdup("devices.allow");
- if (!pe->name) {
- pe->name = old_name;
- return -1;
- }
- xfree(old_name);
-
- pos = pe->value;
- while (*pos) {
- int offset = next_device_entry(pos);
- pe->value = pos;
- ret = restore_cgroup_prop(pe, path, off2);
- if (ret < 0) {
- pe->value = old_val;
- return -1;
- }
- pos += offset;
- }
- pe->value = old_val;
-
- } else if (restore_cgroup_prop(e->properties[j], path, off2) < 0) {
+ if (restore_cgroup_prop(e->properties[j], path, off2) < 0) {
return -1;
}
@@ -1435,7 +1379,74 @@ static int restore_special_props(char *paux, size_t off, CgroupDirEntry *e)
} else if (!strcmp(prop->name, "memory.oom_control") &&
!strcmp(prop->value, "0")) {
continue;
- } else if (restore_cgroup_prop(prop, paux, off) < 0) {
+ }
+
+ if (!strcmp(e->properties[j]->name, "devices.list")) {
+ /* The devices cgroup must be restored in a
+ * special way: only the contents of
+ * devices.list can be read, and it is a
+ * whitelist of all the devices the cgroup is
+ * allowed to create. To re-creat this
+ * whitelist, we first deny everything via
+ * devices.deny, and then write the list back
+ * into devices.allow.
+ *
+ * Further, we must have a write() call for
+ * each line, because the kernel only parses
+ * the first line of any write().
+ */
+ CgroupPropEntry *pe = e->properties[j];
+ char *old_val = pe->value, *old_name = pe->name;
+ int ret;
+ char *pos;
+
+ /* A bit of a fudge here. These are
+ * write only by owner by default, but
+ * the container engine could have
+ * changed the perms. We should come up
+ * with a better way to restore all of
+ * this stuff.
+ */
+ pe->perms->mode = 0200;
+
+ pe->name = "devices.deny";
+ pe->value = "a";
+ ret = restore_cgroup_prop(e->properties[j], paux, off);
+ pe->name = old_name;
+ pe->value = old_val;
+
+ /* an emptry string here means nothing
+ * is allowed, and the kernel disallows
+ * writing an "" to devices.allow, so
+ * let's just keep going.
+ */
+ if (!strcmp(pe->value, ""))
+ continue;
+
+ if (ret < 0)
+ return -1;
+
+ pe->name = "devices.allow";
+
+ pos = pe->value;
+ while (*pos) {
+ int offset = next_device_entry(pos);
+ pe->value = pos;
+ ret = restore_cgroup_prop(pe, paux, off);
+ if (ret < 0) {
+ pe->name = old_name;
+ pe->value = old_val;
+ return -1;
+ }
+ pos += offset;
+ }
+ pe->value = old_val;
+ pe->name = old_name;
+ continue;
+
+ }
+
+ if (restore_cgroup_prop(prop, paux, off) < 0) {
return -1;
}
}
@@ -1494,7 +1505,9 @@ static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux
return -1;
for (j = 0; j < n_controllers; j++) {
- if (!strcmp(controllers[j], "cpuset") || !strcmp(controllers[j], "memory")) {
+ if (!strcmp(controllers[j], "cpuset")
+ || !strcmp(controllers[j], "memory")
+ || !strcmp(controllers[j], "devices")) {
if (restore_special_props(paux, off2, e) < 0) {
pr_err("Restoring special cpuset props failed!\n");
return -1;
--
2.7.4
More information about the CRIU
mailing list