BUG/MINOR: auth: free user groups on error paths in userlist_postinit()

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.
This commit is contained in:
Willy Tarreau 2026-05-11 15:06:41 +02:00
parent 0995c914bd
commit fdfecc5589

View 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;