[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