[CRIU] [PATCH 1/2] cgroup: treat devices as "special" properties
Tycho Andersen
tycho.andersen at canonical.com
Mon Sep 12 17:34:02 PDT 2016
Hi Cyrill,
I don't think this one is quite right. I'll try to send an updated one
shortly.
Tycho
On Mon, Sep 12, 2016 at 09:47:08AM -0600, Tycho Andersen wrote:
> v2: don't try to write "" to devices.allow, just skip it since we write 'a'
> to devices.deny everywhere anyway.
>
> Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
> CC: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
> criu/cgroup.c | 135 ++++++++++++++++++++++++++++++++--------------------------
> 1 file changed, 75 insertions(+), 60 deletions(-)
>
> diff --git a/criu/cgroup.c b/criu/cgroup.c
> index 431ba30..993c1aa 100644
> --- a/criu/cgroup.c
> +++ b/criu/cgroup.c
> @@ -946,6 +946,7 @@ static int ctrl_dir_and_opt(CgControllerEntry *ctl, char *dir, int ds,
> static const char *special_props[] = {
> "cpuset.cpus",
> "cpuset.mems",
> + "devices.list",
> "memory.kmem.limit_in_bytes",
> "memory.swappiness",
> "memory.oom_control",
> @@ -1319,64 +1320,7 @@ static int prepare_cgroup_dir_properties(char *path, int off, CgroupDirEntry **e
> if (special)
> continue;
>
> - /* The devices cgroup must be restored in a
> - * special way: only the contents of
> - * devices.list can be read, and it is a
> - * whitelist of all the devices the cgroup is
> - * allowed to create. To re-creat this
> - * whitelist, we first deny everything via
> - * devices.deny, and then write the list back
> - * into devices.allow.
> - *
> - * Further, we must have a write() call for
> - * each line, because the kernel only parses
> - * the first line of any write().
> - */
> - if (!strcmp(e->properties[j]->name, "devices.list")) {
> - CgroupPropEntry *pe = e->properties[j];
> - char *old_val = pe->value, *old_name = pe->name;
> - int ret;
> - char *pos;
> -
> - /* A bit of a fudge here. These are
> - * write only by owner by default, but
> - * the container engine could have
> - * changed the perms. We should come up
> - * with a better way to restore all of
> - * this stuff.
> - */
> - pe->perms->mode = 0200;
> -
> - pe->name = "devices.deny";
> - pe->value = "a";
> - ret = restore_cgroup_prop(e->properties[j], path, off2);
> - pe->name = old_name;
> - pe->value = old_val;
> -
> - if (ret < 0)
> - return -1;
> -
> - pe->name = xstrdup("devices.allow");
> - if (!pe->name) {
> - pe->name = old_name;
> - return -1;
> - }
> - xfree(old_name);
> -
> - pos = pe->value;
> - while (*pos) {
> - int offset = next_device_entry(pos);
> - pe->value = pos;
> - ret = restore_cgroup_prop(pe, path, off2);
> - if (ret < 0) {
> - pe->value = old_val;
> - return -1;
> - }
> - pos += offset;
> - }
> - pe->value = old_val;
> -
> - } else if (restore_cgroup_prop(e->properties[j], path, off2) < 0) {
> + if (restore_cgroup_prop(e->properties[j], path, off2) < 0) {
> return -1;
> }
>
> @@ -1435,7 +1379,76 @@ static int restore_special_props(char *paux, size_t off, CgroupDirEntry *e)
> } else if (!strcmp(prop->name, "memory.oom_control") &&
> !strcmp(prop->value, "0")) {
> continue;
> - } else if (restore_cgroup_prop(prop, paux, off) < 0) {
> + }
> +
> + if (!strcmp(e->properties[j]->name, "devices.list")) {
> + /* The devices cgroup must be restored in a
> + * special way: only the contents of
> + * devices.list can be read, and it is a
> + * whitelist of all the devices the cgroup is
> + * allowed to create. To re-creat this
> + * whitelist, we first deny everything via
> + * devices.deny, and then write the list back
> + * into devices.allow.
> + *
> + * Further, we must have a write() call for
> + * each line, because the kernel only parses
> + * the first line of any write().
> + */
> + CgroupPropEntry *pe = e->properties[j];
> + char *old_val = pe->value, *old_name = pe->name;
> + int ret;
> + char *pos;
> +
> + /* A bit of a fudge here. These are
> + * write only by owner by default, but
> + * the container engine could have
> + * changed the perms. We should come up
> + * with a better way to restore all of
> + * this stuff.
> + */
> + pe->perms->mode = 0200;
> +
> + pe->name = "devices.deny";
> + pe->value = "a";
> + ret = restore_cgroup_prop(e->properties[j], paux, off);
> + pe->name = old_name;
> + pe->value = old_val;
> +
> + /* an emptry string here means nothing
> + * is allowed, and the kernel disallows
> + * writing an "" to devices.allow, so
> + * let's just keep going.
> + */
> + if (!strcmp(pe->value, ""))
> + continue;
> +
> + if (ret < 0)
> + return -1;
> +
> + pe->name = xstrdup("devices.allow");
> + if (!pe->name) {
> + pe->name = old_name;
> + return -1;
> + }
> + xfree(old_name);
> +
> + pos = pe->value;
> + while (*pos) {
> + int offset = next_device_entry(pos);
> + pe->value = pos;
> + ret = restore_cgroup_prop(pe, paux, off);
> + if (ret < 0) {
> + pe->value = old_val;
> + return -1;
> + }
> + pos += offset;
> + }
> + pe->value = old_val;
> +
> + }
> +
> + if (restore_cgroup_prop(prop, paux, off) < 0) {
> return -1;
> }
> }
> @@ -1494,7 +1507,9 @@ static int prepare_cgroup_dirs(char **controllers, int n_controllers, char *paux
> return -1;
>
> for (j = 0; j < n_controllers; j++) {
> - if (!strcmp(controllers[j], "cpuset") || !strcmp(controllers[j], "memory")) {
> + if (!strcmp(controllers[j], "cpuset")
> + || !strcmp(controllers[j], "memory")
> + || !strcmp(controllers[j], "devices")) {
> if (restore_special_props(paux, off2, e) < 0) {
> pr_err("Restoring special cpuset props failed!\n");
> return -1;
> --
> 2.7.4
>
More information about the CRIU
mailing list