[CRIU] [PATCH 1/6] cgroup: restore cgroup property perms as well

Tycho Andersen tycho.andersen at canonical.com
Wed Jan 20 09:27:33 PST 2016


Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 cgroup.c              | 58 +++++++++++++++++++++++++++++++++++++++++++++++++--
 include/cgroup.h      |  3 +++
 protobuf/cgroup.proto |  7 +++++++
 3 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/cgroup.c b/cgroup.c
index 27be045..25f03c8 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -307,6 +307,7 @@ static int read_cgroup_prop(struct cgroup_prop *property, const char *fullpath)
 {
 	char buf[1024];
 	int fd, ret;
+	struct stat sb;
 
 	fd = open(fullpath, O_RDONLY);
 	if (fd == -1) {
@@ -315,6 +316,16 @@ static int read_cgroup_prop(struct cgroup_prop *property, const char *fullpath)
 		return -1;
 	}
 
+	if (fstat(fd, &sb) < 0) {
+		pr_perror("failed statting cgroup prop %s", fullpath);
+		close(fd);
+		return -1;
+	}
+
+	property->mode = sb.st_mode;
+	property->uid = sb.st_uid;
+	property->gid = sb.st_gid;
+
 	ret = read(fd, buf, sizeof(buf) - 1);
 	if (ret == -1) {
 		pr_err("Failed scanning %s\n", fullpath);
@@ -331,7 +342,6 @@ static int read_cgroup_prop(struct cgroup_prop *property, const char *fullpath)
 	property->value = xstrdup(strip(buf));
 	if (!property->value)
 		return -1;
-
 	return 0;
 }
 
@@ -664,10 +674,20 @@ static int dump_cg_dir_props(struct list_head *props, size_t n_props,
 
 	list_for_each_entry(prop_cur, props, list) {
 		cgroup_prop_entry__init(cpe);
+
+		cpe->perms = xmalloc(sizeof(*cpe->perms));
+		if (!cpe->perms)
+			goto error;
+		cgroup_perms__init(cpe->perms);
+
 		cpe->name = xstrdup(prop_cur->name);
 		cpe->value = xstrdup(prop_cur->value);
 		if (!cpe->name || !cpe->value)
 			goto error;
+		cpe->perms->mode = prop_cur->mode;
+		cpe->perms->uid = prop_cur->uid;
+		cpe->perms->gid = prop_cur->gid;
+
 		(*ents)[i++] = cpe++;
 	}
 
@@ -1001,7 +1021,9 @@ static int restore_cgroup_prop(const CgroupPropEntry * cg_prop_entry_p,
 			       char *path, int off)
 {
 	FILE *f;
-	int cg;
+	int cg, fd;
+	struct stat sb;
+	CgroupPerms *perms = cg_prop_entry_p->perms;
 
 	if (!cg_prop_entry_p->value) {
 		pr_err("cg_prop_entry->value was empty when should have had a value\n");
@@ -1022,6 +1044,38 @@ static int restore_cgroup_prop(const CgroupPropEntry * cg_prop_entry_p,
 		return -1;
 	}
 
+	fd = fileno(f);
+	if (fd < 0) {
+		fclose(f);
+		pr_err("bad file stream?");
+		return -1;
+	}
+
+	if (fstat(fd, &sb) < 0) {
+		fclose(f);
+		pr_perror("stat of property %s failed", path);
+		return -1;
+	}
+
+	if (perms) {
+		/* only chmod/chown if the perms are actually different: we aren't
+		 * allowed to chmod some cgroup props (e.g. the read only ones), so we
+		 * don't want to try if the perms already match.
+		 */
+		if (sb.st_mode != (mode_t) perms->mode && fchmod(fd, perms->mode) < 0) {
+			fclose(f);
+			pr_perror("chmod of %s failed", path);
+			return -1;
+		}
+
+		if ((sb.st_uid != perms->uid || sb.st_gid != perms->gid) &&
+		    fchown(fd, perms->uid, perms->gid)) {
+			fclose(f);
+			pr_perror("chown of %s failed", path);
+			return -1;
+		}
+	}
+
 	if (fprintf(f, "%s", cg_prop_entry_p->value) < 0) {
 		fclose(f);
 		pr_err("Failed writing %s to %s\n", cg_prop_entry_p->value, path);
diff --git a/include/cgroup.h b/include/cgroup.h
index 58bbd63..97bf5b3 100644
--- a/include/cgroup.h
+++ b/include/cgroup.h
@@ -17,6 +17,9 @@ struct cg_controller;
 struct cgroup_prop {
 	char			*name;
 	char			*value;
+	mode_t			mode;
+	uid_t			uid;
+	gid_t			gid;
 	struct list_head	list;
 };
 
diff --git a/protobuf/cgroup.proto b/protobuf/cgroup.proto
index 2084388..36c5950 100644
--- a/protobuf/cgroup.proto
+++ b/protobuf/cgroup.proto
@@ -1,6 +1,13 @@
+message cgroup_perms {
+	required uint32			mode		= 1;
+	required uint32			uid		= 2;
+	required uint32			gid		= 3;
+}
+
 message cgroup_prop_entry {
 	required string			name		= 1;
 	required string			value		= 2;
+	optional cgroup_perms		perms		= 3;
 }
 
 message cgroup_dir_entry {
-- 
2.5.0



More information about the CRIU mailing list