[CRIU] [PATCH 3/6] cgroup: restore perms on cgroup dirs as well
Tycho Andersen
tycho.andersen at canonical.com
Wed Jan 20 09:27:35 PST 2016
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
cgroup.c | 88 ++++++++++++++++++++++++++++++++++++++-------------
include/cgroup.h | 3 ++
protobuf/cgroup.proto | 1 +
3 files changed, 70 insertions(+), 22 deletions(-)
diff --git a/cgroup.c b/cgroup.c
index 85085b1..3ddf33a 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -483,6 +483,10 @@ static int add_cgroup(const char *fpath, const struct stat *sb, int typeflag)
if (!ncd)
goto out;
+ ncd->mode = sb->st_mode;
+ ncd->uid = sb->st_uid;
+ ncd->gid = sb->st_gid;
+
/* chop off the first "/proc/self/fd/N" str */
if (fpath[path_pref_len] == '\0')
ncd->path = xstrdup("/");
@@ -746,6 +750,16 @@ static int dump_cg_dirs(struct list_head *dirs, size_t n_dirs, CgroupDirEntry **
list_for_each_entry(cur, dirs, siblings) {
cgroup_dir_entry__init(cde);
+
+ cde->dir_perms = xmalloc(sizeof(*cde->dir_perms));
+ if (!cde->dir_perms)
+ return -1;
+ cgroup_perms__init(cde->dir_perms);
+
+ cde->dir_perms->mode = cur->mode;
+ cde->dir_perms->uid = cur->uid;
+ cde->dir_perms->gid = cur->gid;
+
cde->dir_name = cur->path + poff;
if (poff != 1) /* parent isn't "/" */
cde->dir_name++; /* leading / */
@@ -1042,12 +1056,40 @@ void fini_cgroup(void)
cg_yard = NULL;
}
+static int restore_perms(int fd, const char *path, CgroupPerms *perms)
+{
+ struct stat sb;
+
+ if (perms) {
+ if (fstat(fd, &sb) < 0) {
+ pr_perror("stat of property %s failed", path);
+ return -1;
+ }
+
+ /* 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) {
+ 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)) {
+ pr_perror("chown of %s failed", path);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static int restore_cgroup_prop(const CgroupPropEntry * cg_prop_entry_p,
char *path, int off)
{
FILE *f;
int cg, fd;
- struct stat sb;
CgroupPerms *perms = cg_prop_entry_p->perms;
if (!cg_prop_entry_p->value) {
@@ -1076,31 +1118,11 @@ static int restore_cgroup_prop(const CgroupPropEntry * cg_prop_entry_p,
return -1;
}
- if (fstat(fd, &sb) < 0) {
+ if (restore_perms(fd, path, perms) < 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);
@@ -1213,6 +1235,21 @@ static int restore_special_cpuset_props(char *paux, size_t off, CgroupDirEntry *
return 0;
}
+static int prepare_dir_perms(int cg, char *path, CgroupPerms *perms)
+{
+ int fd, ret;
+
+ fd = openat(cg, path, O_DIRECTORY);
+ if (fd < 0) {
+ pr_perror("failed to open cg dir fd (%s) for chowning", path);
+ return -1;
+ }
+
+ ret = restore_perms(fd, path, perms);
+ close(fd);
+ return ret;
+}
+
static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux, size_t off,
CgroupDirEntry **ents, size_t n_ents)
{
@@ -1243,6 +1280,9 @@ static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux
}
pr_info("Created cgroup dir %s\n", paux);
+ if (prepare_dir_perms(cg, paux, e->dir_perms) < 0)
+ return -1;
+
for (j = 0; j < n_controllers; j++) {
if (strcmp(controllers[j], "cpuset") == 0) {
if (restore_special_cpuset_props(paux, off2, e) < 0) {
@@ -1267,6 +1307,10 @@ static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux
e->n_properties = 0;
}
}
+
+ if (!(opts.manage_cgroups & CG_MODE_NONE) &&
+ prepare_dir_perms(cg, paux, e->dir_perms) < 0)
+ return -1;
}
if (prepare_cgroup_dirs(controllers, n_controllers, paux, off2,
diff --git a/include/cgroup.h b/include/cgroup.h
index 97bf5b3..393ee3d 100644
--- a/include/cgroup.h
+++ b/include/cgroup.h
@@ -28,6 +28,9 @@ struct cgroup_prop {
*/
struct cgroup_dir {
char *path;
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
struct list_head properties;
unsigned int n_properties;
diff --git a/protobuf/cgroup.proto b/protobuf/cgroup.proto
index 36c5950..dcd2fe8 100644
--- a/protobuf/cgroup.proto
+++ b/protobuf/cgroup.proto
@@ -14,6 +14,7 @@ message cgroup_dir_entry {
required string dir_name = 1;
repeated cgroup_dir_entry children = 2;
repeated cgroup_prop_entry properties = 3;
+ optional cgroup_perms dir_perms = 4;
}
message cg_controller_entry {
--
2.5.0
More information about the CRIU
mailing list