From: Olivier Houchard Date: Mon, 8 Jun 2026 13:48:42 +0000 (+0200) Subject: BUG/MEDIUM: checks: Dequeue checks on purge X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=a4520229a77eae2c33df7a003a07b95f162482e0;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: checks: Dequeue checks on purge When tune.max-checks-per-thread is used, checks that should run are queued, to avoid having too many checks running at the same time. But if the check is about to be purged, because the server is being deleted, we have to explicitly remove it from the queue as that memory is about to be freed, otherwise it will cause a use-after-free. Also, queued checks have not yet incremented th_ctx->running_checks, so don't decrement it if we're queued. This should be backported up to 3.0. --- diff --git a/src/check.c b/src/check.c index 3864e7c77..8d0effa4c 100644 --- a/src/check.c +++ b/src/check.c @@ -1407,7 +1407,20 @@ struct task *process_chk_conn(struct task *t, void *context, unsigned int state) check_release_buf(check, &check->bi); check_release_buf(check, &check->bo); - _HA_ATOMIC_DEC(&th_ctx->running_checks); + + if (unlikely(LIST_INLIST(&check->check_queue))) { + /* + * If that check is still queued, and we're about to + * purge it, then remove it from the queue, as it is + * about to be freed. + * This can happen if a server is deleted while the check + * is queued. + */ + if (check->state & CHK_ST_PURGE) + LIST_DEL_INIT(&check->check_queue); + } + else + _HA_ATOMIC_DEC(&th_ctx->running_checks); _HA_ATOMIC_DEC(&th_ctx->active_checks); check->state &= ~(CHK_ST_INPROGRESS|CHK_ST_IN_ALLOC|CHK_ST_OUT_ALLOC); check->state &= ~CHK_ST_READY; @@ -1566,6 +1579,7 @@ void free_check(struct check *check) ha_free(&check->tcpcheck); } + LIST_DEL_INIT(&check->check_queue); pool_free(pool_head_uniqueid, istptr(check->unique_id)); check->unique_id = IST_NULL; ha_free(&check->pool_conn_name);