From 49db9739d0591d15907e0241f3bcc8e7adb4fd3a Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Tue, 26 Aug 2025 15:49:15 +0200 Subject: [PATCH] BUG/MEDIUM: spoe: Improve error detection in SPOE applet on client abort It is possible to interrupt a SPOE applet without reporting an error. For instance, when the client of the parent stream aborts. Thanks to this patch, we take care to report an error on the SPOE applet to be sure to interrupt the processing. It is especially important if the connection to the agent is queued. Thanks to 886a248be ("BUG/MEDIUM: mux-spop: Reject connection attempts from a non-spop frontend"), it is no longer an issue. But there is no reason to continue to process if the parent stream is gone. In addition, in the SPOE filter, if the processing is interrupted when the filter is destroyed, no specific status code was set. It is not a big deal because it cannot be logged at this stage. But it can be used to notify the SPOE applet. So better to set it. This patch should be backported as far as 3.1. --- src/flt_spoe.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 371037129..a1147665a 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -434,6 +434,7 @@ static void spoe_release_appctx(struct appctx *appctx) /* Shutdown the server connection, if needed */ if (appctx->st0 != SPOE_APPCTX_ST_END) { appctx->st0 = SPOE_APPCTX_ST_END; + applet_set_error(appctx); if (spoe_appctx->status_code == SPOP_ERR_NONE) spoe_appctx->status_code = SPOP_ERR_IO; } @@ -504,14 +505,15 @@ static void spoe_handle_appctx(struct appctx *appctx) goto out; } - if (!SPOE_APPCTX(appctx)->spoe_ctx) - appctx->st0 = SPOE_APPCTX_ST_EXIT; - switchstate: switch (appctx->st0) { /* case SPOE_APPCTX_ST_PROCESSING: */ case SPOE_APPCTX_ST_WAITING_ACK: - if (!spoe_handle_receiving_frame_appctx(appctx)) + if (!SPOE_APPCTX(appctx)->spoe_ctx) { + appctx->st0 = SPOE_APPCTX_ST_END; + applet_set_error(appctx); + } + else if (!spoe_handle_receiving_frame_appctx(appctx)) break; goto switchstate; @@ -1184,6 +1186,10 @@ static void spoe_destroy_context(struct filter *filter) if (!ctx) return; + if (ctx->state != SPOE_CTX_ST_NONE || ctx->state == SPOE_CTX_ST_READY) { + ctx->status_code = SPOE_CTX_ERR_INTERRUPT; + _HA_ATOMIC_INC(&conf->agent->counters.nb_errors); + } spoe_stop_processing(conf->agent, ctx); pool_free(pool_head_spoe_ctx, ctx); filter->ctx = NULL;