]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stick-tables: Make sure not to free a pending entry
authorOlivier Houchard <ohouchard@haproxy.com>
Tue, 30 Sep 2025 13:16:44 +0000 (15:16 +0200)
committerOlivier Houchard <cognet@ci0.org>
Tue, 30 Sep 2025 14:25:07 +0000 (16:25 +0200)
There is a race condition, an entry can be free'd by stksess_kill()
between the time stktable_add_pend_updates() gets the entry from the
mt_list, and the time it adds it to the ebtree.
To prevent this, use the newly implemented MT_LIST_POP_LOCKED() to keep
the stksess locked until it is added to the tree. That way,
__stksess_kill() will wait until we're done with it.

This should be backported to 3.2.

src/stick_table.c

index a7f16b5bad08084b2c97e24d8aced2597ea46821..9a0809cb361a11dab682f74a41f2494451c605f0 100644 (file)
@@ -811,7 +811,7 @@ struct task *stktable_add_pend_updates(struct task *t, void *ctx, unsigned int s
                goto leave;
 
        for (i = 0; i < STKTABLE_MAX_UPDATES_AT_ONCE; i++) {
-               struct stksess *stksess = MT_LIST_POP(&table->pend_updts[cur_tgid], typeof(stksess), pend_updts);
+               struct stksess *stksess = MT_LIST_POP_LOCKED(&table->pend_updts[cur_tgid], typeof(stksess), pend_updts);
 
                if (!stksess) {
                        empty_tgid++;
@@ -848,6 +848,13 @@ struct task *stktable_add_pend_updates(struct task *t, void *ctx, unsigned int s
                        eb32_delete(eb);
                        eb32_insert(&table->updates, &stksess->upd);
                }
+               /*
+                * Now that we're done inserting the stksess, unlock it.
+                * It is kept locked here to prevent a race condition
+                * when stksess_kill() could free() it after we removed
+                * it from the list, but before we inserted it into the tree
+                */
+               MT_LIST_INIT(&stksess->pend_updts);
        }
 
        HA_RWLOCK_WRUNLOCK(STK_TABLE_UPDT_LOCK, &table->updt_lock);