Skip to content

Commit e74881e

Browse files
src/config: free namespace table on success and failure
The per-thread namespace table (cg_namespace_table[]) is populated by config_order_namespace_table() / config_validate_namespaces() under cg_mount_table_lock and then consumed by cg_build_path_locked(). Before this patch we reset the array with a bespoke loop + memset at the front of config_order_namespace_table(), but error paths relied on the call chain eventually unwinding into cgroup_free_config() to release any partially populated entries. That worked, yet it meant the table could briefly hold dangling pointers after an error while the lock was already dropped, one subtle slip or new return path would have left stale namespaces visible to the rest of the library. This change introduces a small helper, cgroup_config_free_namespaces_table(), that walks the thread-local array, frees each string, and nulls the slot. We invoke it in three places: - right at the start of config_order_namespace_table(), so every run begins with a clean slate. - from the error branches of both namespace helpers, guaranteeing that even a mid-stream failure leaves the table empty before the lock is released. - and (unchanged) from cgroup_free_config(), so the happy path tears everything down once the config work finishes. The end result is both cleaner and safer: we delete the redundant set-to-NULL/memset sequence and the namespace table is always in a known state no matter how the parser exits. Signed-off-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
1 parent 58d73eb commit e74881e

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

src/config.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,19 @@ static int cgroup_config_unmount_controllers(void)
963963
return 0;
964964
}
965965

966+
/*
967+
* Free namespaces table
968+
*/
969+
static void cgroup_config_free_namespaces_table(void)
970+
{
971+
int i;
972+
973+
for (i = 0; i < CG_CONTROLLER_MAX; i++) {
974+
free(cg_namespace_table[i]);
975+
cg_namespace_table[i] = NULL;
976+
}
977+
}
978+
966979
static int config_validate_namespaces(void)
967980
{
968981
char *namespace = NULL;
@@ -1050,6 +1063,8 @@ static int config_validate_namespaces(void)
10501063
i = subsys_count - 1;
10511064
}
10521065
out_error:
1066+
if (error)
1067+
cgroup_config_free_namespaces_table();
10531068
pthread_rwlock_unlock(&cg_mount_table_lock);
10541069

10551070
return error;
@@ -1073,11 +1088,7 @@ static int config_order_namespace_table(void)
10731088
int i = 0;
10741089

10751090
pthread_rwlock_wrlock(&cg_mount_table_lock);
1076-
/* Set everything to NULL */
1077-
for (i = 0; i < CG_CONTROLLER_MAX; i++)
1078-
cg_namespace_table[i] = NULL;
1079-
1080-
memset(cg_namespace_table, 0, CG_CONTROLLER_MAX * sizeof(cg_namespace_table[0]));
1091+
cgroup_config_free_namespaces_table();
10811092

10821093
/* Now fill up the namespace table looking at the table we have otherwise. */
10831094
for (i = 0; i < namespace_table_index; i++) {
@@ -1110,6 +1121,8 @@ static int config_order_namespace_table(void)
11101121
}
11111122
}
11121123
error_out:
1124+
if (error)
1125+
cgroup_config_free_namespaces_table();
11131126
pthread_rwlock_unlock(&cg_mount_table_lock);
11141127

11151128
return error;

0 commit comments

Comments
 (0)