]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
tools/cgget: free controller tokens and revert cgroup on -g failure
authorKamalesh Babulal <kamalesh.babulal@oracle.com>
Sat, 21 Feb 2026 02:48:30 +0000 (08:18 +0530)
committerTom Hromatka <tom.hromatka@oracle.com>
Thu, 19 Mar 2026 19:07:17 +0000 (13:07 -0600)
AddressSanitizer reported two 8-byte leaks when handling cgget -g
controller:<cgroup>:

Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x... in __interceptor_realloc
    #1 split_controllers (<libcgroup-source>/src/tools/cgget.c:257)

Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x... in __interceptor_realloc
    #1 create_cgrp (<libcgroup-source>/src/tools/cgget.c:76)

split_controllers() grew the controller array with realloc()/strdup()
but on failure it leaked every already-duplicated token, and the caller
never freed the temporary array even on success.

parse_g_flag_with_colon() also pushed a new struct cgroup onto the list
and left it behind whenever a later step bailed out, so the cgroup object
stayed allocated. The helper now frees the duplicated controller tokens
on error, releases the scratch array after use, and if parsing fails it
frees the freshly appended cgroup and drops the length so the caller
ignores it. With these changes the ASan leak report disappears.

Signed-off-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
src/tools/cgget.c

index 2bf73fc3c9f28de091e35903b6291b1265a2a8a5..40e37f740762df25d97bf977f8a76b38e3a616e0 100644 (file)
@@ -242,7 +242,7 @@ static int split_cgroup_name(const char * const ctrl_str, char *cgrp_name)
 static int split_controllers(const char * const in, char **ctrl[], int * const ctrl_len)
 {
        char *copy, *tok, *colon, *saveptr = NULL;
-       int ret = 0;
+       int i, ret = 0;
        char **tmp;
 
        copy = strdup(in);
@@ -275,6 +275,14 @@ out:
        if (saveptr)
                free(saveptr);
 
+       if (ret) {
+               for (i = 0; i < *ctrl_len; i++)
+                       free((*ctrl)[i]);
+               free(*ctrl);
+               *ctrl = NULL;
+               *ctrl_len = 0;
+       }
+
        return ret;
 }
 
@@ -284,9 +292,11 @@ static int parse_g_flag_with_colon(struct cgroup **cgrp_list[], int * const cgrp
        struct cgroup_controller *cgc;
        struct cgroup *cgrp = NULL;
        char **controllers = NULL;
-       int controllers_len = 0;
+       int orig_len, controllers_len = 0;
        int i, ret = 0;
 
+       orig_len = *cgrp_list_len;
+
        ret = create_cgrp(cgrp_list, cgrp_list_len);
        if (ret)
                goto out;
@@ -316,6 +326,14 @@ static int parse_g_flag_with_colon(struct cgroup **cgrp_list[], int * const cgrp
 out:
        for (i = 0; i < controllers_len; i++)
                free(controllers[i]);
+       free(controllers);
+
+       if (ret && *cgrp_list_len > orig_len) {
+               /* Remove the cgroup we just appended */
+               cgroup_free(&(*cgrp_list)[(*cgrp_list_len) - 1]);
+               (*cgrp_list)[(*cgrp_list_len) - 1] = NULL;
+               (*cgrp_list_len)--;
+       }
 
        return ret;
 }