mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
cgroup: restore cgroup property perms as well
Signed-off-by: Tycho Andersen <tycho.andersen@canonical.com> Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
3c18439ebd
commit
cbe8ef4fe7
58
cgroup.c
58
cgroup.c
@@ -307,6 +307,7 @@ static int read_cgroup_prop(struct cgroup_prop *property, const char *fullpath)
|
|||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
fd = open(fullpath, O_RDONLY);
|
fd = open(fullpath, O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
@@ -315,6 +316,16 @@ static int read_cgroup_prop(struct cgroup_prop *property, const char *fullpath)
|
|||||||
return -1;
|
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);
|
ret = read(fd, buf, sizeof(buf) - 1);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
pr_err("Failed scanning %s\n", fullpath);
|
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));
|
property->value = xstrdup(strip(buf));
|
||||||
if (!property->value)
|
if (!property->value)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
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) {
|
list_for_each_entry(prop_cur, props, list) {
|
||||||
cgroup_prop_entry__init(cpe);
|
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->name = xstrdup(prop_cur->name);
|
||||||
cpe->value = xstrdup(prop_cur->value);
|
cpe->value = xstrdup(prop_cur->value);
|
||||||
if (!cpe->name || !cpe->value)
|
if (!cpe->name || !cpe->value)
|
||||||
goto error;
|
goto error;
|
||||||
|
cpe->perms->mode = prop_cur->mode;
|
||||||
|
cpe->perms->uid = prop_cur->uid;
|
||||||
|
cpe->perms->gid = prop_cur->gid;
|
||||||
|
|
||||||
(*ents)[i++] = cpe++;
|
(*ents)[i++] = cpe++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1001,7 +1021,9 @@ static int restore_cgroup_prop(const CgroupPropEntry * cg_prop_entry_p,
|
|||||||
char *path, int off)
|
char *path, int off)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int cg;
|
int cg, fd;
|
||||||
|
struct stat sb;
|
||||||
|
CgroupPerms *perms = cg_prop_entry_p->perms;
|
||||||
|
|
||||||
if (!cg_prop_entry_p->value) {
|
if (!cg_prop_entry_p->value) {
|
||||||
pr_err("cg_prop_entry->value was empty when should have had a value\n");
|
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;
|
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) {
|
if (fprintf(f, "%s", cg_prop_entry_p->value) < 0) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
pr_err("Failed writing %s to %s\n", cg_prop_entry_p->value, path);
|
pr_err("Failed writing %s to %s\n", cg_prop_entry_p->value, path);
|
||||||
|
@@ -17,6 +17,9 @@ struct cg_controller;
|
|||||||
struct cgroup_prop {
|
struct cgroup_prop {
|
||||||
char *name;
|
char *name;
|
||||||
char *value;
|
char *value;
|
||||||
|
mode_t mode;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,6 +1,13 @@
|
|||||||
|
message cgroup_perms {
|
||||||
|
required uint32 mode = 1;
|
||||||
|
required uint32 uid = 2;
|
||||||
|
required uint32 gid = 3;
|
||||||
|
}
|
||||||
|
|
||||||
message cgroup_prop_entry {
|
message cgroup_prop_entry {
|
||||||
required string name = 1;
|
required string name = 1;
|
||||||
required string value = 2;
|
required string value = 2;
|
||||||
|
optional cgroup_perms perms = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message cgroup_dir_entry {
|
message cgroup_dir_entry {
|
||||||
|
Reference in New Issue
Block a user