]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: auth: free user groups on error paths in userlist_postinit()
authorWilly Tarreau <w@1wt.eu>
Mon, 11 May 2026 13:06:41 +0000 (15:06 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 11 May 2026 14:04:19 +0000 (16:04 +0200)
In userlist_postinit(), when an error occurs (missing group, missing user, or
allocation failure), the function returned immediately without freeing the
auth_groups_list linked lists that were built for all users in the first loop.
Each user's curuser->u.groups pointed to these allocated nodes, which leaked
on every error path.

Fix by replacing direct returns with a goto to a centralized cleanup label
that frees all users' groups lists before returning the error. Also fix a
trailing double space in one error return statement while refactoring.

Note that the impact is very low since we're supposed to fail to boo after
such errors.

src/auth.c

index 92f5bc2baf8161f03185f322bdccf7963f747ef3..f2380753a0eb82ca46f7fe6ecb065d95d2975b90 100644 (file)
@@ -129,7 +129,7 @@ int userlist_postinit()
        for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
                struct auth_groups *ag;
                struct auth_users *curuser;
-               struct auth_groups_list *grl;
+               struct auth_groups_list *grl, *tmp;
 
                for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
                        char *group = NULL;
@@ -152,7 +152,7 @@ int userlist_postinit()
                                                groups = groups->next;
                                                free(grl);
                                        }
-                                       return ERR_ALERT | ERR_FATAL;
+                                       goto free_groups;
                                }
 
                                /* Add this group at the group userlist. */
@@ -165,7 +165,7 @@ int userlist_postinit()
                                                groups = groups->next;
                                                free(grl);
                                        }
-                                       return ERR_ALERT | ERR_FATAL;
+                                       goto free_groups;
                                }
 
                                grl->group = ag;
@@ -192,7 +192,7 @@ int userlist_postinit()
                                if (!curuser) {
                                        ha_alert("userlist '%s': no such user '%s' specified in group '%s'\n",
                                                 curuserlist->name, user, ag->name);
-                                       return ERR_ALERT | ERR_FATAL;
+                                       goto free_groups;
                                }
 
                                /* Add this group at the group userlist. */
@@ -200,7 +200,7 @@ int userlist_postinit()
                                if (!grl) {
                                        ha_alert("userlist '%s': no more memory when trying to allocate the user groups.\n",
                                                 curuserlist->name);
-                                       return  ERR_ALERT | ERR_FATAL;
+                                       goto free_groups;
                                }
 
                                grl->group = ag;
@@ -211,6 +211,22 @@ int userlist_postinit()
                        ha_free(&ag->groupusers);
                }
 
+               goto next_userlist;
+
+        free_groups:
+               /* Free already-assigned groups for all users in this userlist. */
+               for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
+                       grl = curuser->u.groups;
+                       while (grl) {
+                               tmp = grl;
+                               grl = grl->next;
+                               free(tmp);
+                       }
+                       curuser->u.groups = NULL;
+               }
+               return ERR_ALERT | ERR_FATAL;
+
+       next_userlist:;
 #ifdef DEBUG_AUTH
                for (ag = curuserlist->groups; ag; ag = ag->next) {
                        struct auth_groups_list *agl;