[CRIU] [PATCH 1/2] cgroup: restore devices.deny line by line

Tycho Andersen tycho.andersen at canonical.com
Fri Jul 1 10:23:43 PDT 2016


The kernel only reads the first line of any write(), so let's write line by
line.

Right now as far as I know devices.deny is the only cgroup property which
must be written line by line. I could move this code to restore_cgroup_prop
if we expect more of these, though.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 criu/cgroup.c | 38 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/criu/cgroup.c b/criu/cgroup.c
index 5641bfd..c0f561c 100644
--- a/criu/cgroup.c
+++ b/criu/cgroup.c
@@ -1246,6 +1246,24 @@ static void add_freezer_state_for_restore(CgroupPropEntry *entry, char *path, si
 	freezer_path[path_len] = 0;
 }
 
+static void advance_device_entry(char **buf)
+{
+	char *pos = *buf;
+
+	while (1) {
+		if (*pos == '\n') {
+			pos++;
+			break;
+		} else if (*pos == '\0') {
+			break;
+		}
+
+		pos++;
+	}
+
+	*buf = pos;
+}
+
 static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **ents,
 					 unsigned int n_ents)
 {
@@ -1292,11 +1310,16 @@ static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **e
 				 * 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
@@ -1322,10 +1345,21 @@ static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **e
 						return -1;
 					}
 					xfree(old_name);
-				}
 
-				if (restore_cgroup_prop(e->properties[j], path, off2) < 0)
+					for (pos = pe->value; *pos; advance_device_entry(&pos)) {
+						pe->value = pos;
+						ret = restore_cgroup_prop(pe, path, off2);
+						if (ret < 0) {
+							pe->value = old_val;
+							return -1;
+						}
+					}
+					pe->value = old_val;
+
+				} else if (restore_cgroup_prop(e->properties[j], path, off2) < 0) {
 					return -1;
+				}
+
 			}
 		}
 skip:
-- 
2.7.4



More information about the CRIU mailing list