From: Christopher Faulet Date: Tue, 26 Aug 2025 13:49:15 +0000 (+0200) Subject: BUG/MEDIUM: spoe: Improve error detection in SPOE applet on client abort X-Git-Tag: v3.3-dev8~104 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=49db9739d0591d15907e0241f3bcc8e7adb4fd3a;p=thirdparty%2Fhaproxy.git 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. --- 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;