]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
tools/cgxget: free controller tokens and revert cgroup on -g failure
authorKamalesh Babulal <kamalesh.babulal@oracle.com>
Tue, 3 Mar 2026 04:34:06 +0000 (10:04 +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 cgxget "-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/cgxget.c:269)

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

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/cgxget.c

index 0fc9ed10a2520d3ed091a469f7e8962f227ebbdd..a8feb579776f018eced47cf9c0220e68ccb327da 100644 (file)
@@ -254,7 +254,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);
@@ -287,6 +287,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;
 }
 
@@ -296,9 +304,11 @@ static int parse_g_flag_with_colon(struct cgroup **cgrp_list[], int * const cgrp
        struct cgroup_controller *cgc;
        struct cgroup *cg = 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_cg(cgrp_list, cgrp_list_len);
        if (ret)
                goto out;
@@ -327,6 +337,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;
 }