[libvirt] [PATCH 1/2] host-validate: Be more careful when checking for cgroup support

Andrea Bolognani abologna at redhat.com
Mon Apr 4 14:46:58 UTC 2016


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.

As a bonus, after the rewrite 'line' is no longer leaked.
---
 tools/virt-host-validate-common.c | 49 +++++++++++++++++++++++++++++++++------
 1 file changed, 42 insertions(+), 7 deletions(-)

diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c
index 8ebf73e..18b9f20 100644
--- a/tools/virt-host-validate-common.c
+++ b/tools/virt-host-validate-common.c
@@ -265,18 +265,53 @@ 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
+         */
+
+        /* Look for the first colon.
+         * The part we're interested in starts right after it */
+        if (!(start = strstr(line, ":"))) {
+            VIR_FREE(line);
             continue;
+        }
+        start++;
 
-        tmp += strlen(cg_name);
-        if (*tmp != ',' &&
-            *tmp != ':')
+        /* Look for the second colon.
+         * The part we're interested in ends exactly there */
+        if (!(end = strstr(start, ":"))) {
+            VIR_FREE(line);
             continue;
+        }
+        *end = '\0';
 
-        matched = true;
+        if (!(cgroups = virStringSplitCount(start, ",", 0, &ncgroups))) {
+            VIR_FREE(line);
+            continue;
+        }
+
+        /* 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_FREE(line);
+
     VIR_FORCE_FCLOSE(fp);
     if (!matched)
         goto error;
-- 
2.5.5




More information about the libvir-list mailing list