From 51434293031b9f3f115f3dbca9f39755080a2229 Mon Sep 17 00:00:00 2001 From: Andrea Bolognani Date: Fri, 8 Apr 2016 14:13:10 +0200 Subject: [PATCH] host-validate: Be more careful when checking for cgroup support Simply checking whether the cgroup name appears somewhere inside /proc/self/cgroup is enough most of the time, but there are some corner cases that require a more mindful parsing. --- tools/virt-host-validate-common.c | 43 ++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c index 95ae64a1db..e182d0c5ba 100644 --- a/tools/virt-host-validate-common.c +++ b/tools/virt-host-validate-common.c @@ -303,17 +303,48 @@ static int virHostValidateCGroupSupport(const char *hvname, goto error; while ((ret = getline(&line, &len, fp)) >= 0 && !matched) { - char *tmp = strstr(line, cg_name); - if (!tmp) + char **cgroups; + char *start; + char *end; + size_t ncgroups; + size_t i; + + /* Each line in this file looks like + * + * 4:cpu,cpuacct:/machine.slice/machine-qemu\x2dtest.scope/emulator + * + * Since multiple cgroups can be part of the same line and some cgroup + * names can appear as part of other cgroup names (eg. 'cpu' is a + * prefix for both 'cpuacct' and 'cpuset'), it's not enough to simply + * check whether the cgroup name is present somewhere inside the file. + * + * Moreover, there's nothing stopping the cgroup name from appearing + * in an unrelated mount point name as well */ + + /* Look for the first colon. + * The part we're interested in starts right after it */ + if (!(start = strchr(line, ':'))) + continue; + start++; + + /* Look for the second colon. + * The part we're interested in ends exactly there */ + if (!(end = strchr(start, ':'))) continue; + *end = '\0'; - tmp += strlen(cg_name); - if (*tmp != ',' && - *tmp != ':') + if (!(cgroups = virStringSplitCount(start, ",", 0, &ncgroups))) continue; - matched = true; + /* Look for the matching cgroup */ + for (i = 0; i < ncgroups; i++) { + if (STREQ(cgroups[i], cg_name)) + matched = true; + } + + virStringFreeListCount(cgroups, ncgroups); } + VIR_FREE(line); VIR_FORCE_FCLOSE(fp); if (!matched) -- 2.39.5