Commit fa433b75 authored by Tycho Andersen's avatar Tycho Andersen Committed by Pavel Emelyanov

cgroup: restore perms on cgroup dirs as well

Signed-off-by: 's avatarTycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 142f2c8e
...@@ -483,6 +483,10 @@ static int add_cgroup(const char *fpath, const struct stat *sb, int typeflag) ...@@ -483,6 +483,10 @@ static int add_cgroup(const char *fpath, const struct stat *sb, int typeflag)
if (!ncd) if (!ncd)
goto out; 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 */ /* chop off the first "/proc/self/fd/N" str */
if (fpath[path_pref_len] == '\0') if (fpath[path_pref_len] == '\0')
ncd->path = xstrdup("/"); ncd->path = xstrdup("/");
...@@ -746,6 +750,16 @@ static int dump_cg_dirs(struct list_head *dirs, size_t n_dirs, CgroupDirEntry ** ...@@ -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) { list_for_each_entry(cur, dirs, siblings) {
cgroup_dir_entry__init(cde); 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; cde->dir_name = cur->path + poff;
if (poff != 1) /* parent isn't "/" */ if (poff != 1) /* parent isn't "/" */
cde->dir_name++; /* leading / */ cde->dir_name++; /* leading / */
...@@ -1042,12 +1056,40 @@ void fini_cgroup(void) ...@@ -1042,12 +1056,40 @@ void fini_cgroup(void)
cg_yard = NULL; 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, 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, fd; int cg, fd;
struct stat sb;
CgroupPerms *perms = cg_prop_entry_p->perms; CgroupPerms *perms = cg_prop_entry_p->perms;
if (!cg_prop_entry_p->value) { if (!cg_prop_entry_p->value) {
...@@ -1076,31 +1118,11 @@ static int restore_cgroup_prop(const CgroupPropEntry * cg_prop_entry_p, ...@@ -1076,31 +1118,11 @@ static int restore_cgroup_prop(const CgroupPropEntry * cg_prop_entry_p,
return -1; return -1;
} }
if (fstat(fd, &sb) < 0) { if (restore_perms(fd, path, perms) < 0) {
fclose(f); fclose(f);
pr_perror("stat of property %s failed", path);
return -1; 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);
...@@ -1213,6 +1235,21 @@ static int restore_special_cpuset_props(char *paux, size_t off, CgroupDirEntry * ...@@ -1213,6 +1235,21 @@ static int restore_special_cpuset_props(char *paux, size_t off, CgroupDirEntry *
return 0; 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, static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux, size_t off,
CgroupDirEntry **ents, size_t n_ents) CgroupDirEntry **ents, size_t n_ents)
{ {
...@@ -1243,6 +1280,9 @@ static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux ...@@ -1243,6 +1280,9 @@ static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux
} }
pr_info("Created cgroup dir %s\n", 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++) { for (j = 0; j < n_controllers; j++) {
if (strcmp(controllers[j], "cpuset") == 0) { if (strcmp(controllers[j], "cpuset") == 0) {
if (restore_special_cpuset_props(paux, off2, e) < 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 ...@@ -1267,6 +1307,10 @@ static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux
e->n_properties = 0; 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, if (prepare_cgroup_dirs(controllers, n_controllers, paux, off2,
......
...@@ -28,6 +28,9 @@ struct cgroup_prop { ...@@ -28,6 +28,9 @@ struct cgroup_prop {
*/ */
struct cgroup_dir { struct cgroup_dir {
char *path; char *path;
mode_t mode;
uid_t uid;
gid_t gid;
struct list_head properties; struct list_head properties;
unsigned int n_properties; unsigned int n_properties;
......
...@@ -14,6 +14,7 @@ message cgroup_dir_entry { ...@@ -14,6 +14,7 @@ message cgroup_dir_entry {
required string dir_name = 1; required string dir_name = 1;
repeated cgroup_dir_entry children = 2; repeated cgroup_dir_entry children = 2;
repeated cgroup_prop_entry properties = 3; repeated cgroup_prop_entry properties = 3;
optional cgroup_perms dir_perms = 4;
} }
message cg_controller_entry { message cg_controller_entry {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment