From: Christopher Faulet Date: Fri, 5 Jun 2020 06:18:56 +0000 (+0200) Subject: BUG/MEDIUM: contrib/prometheus-exporter: Properly set flags to dump metrics X-Git-Tag: v2.2-dev9~154 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=efde955bdb7b7479267cfcd823cce26bb3f5c4d3;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: contrib/prometheus-exporter: Properly set flags to dump metrics When the metrics are dumped, in the main function promex_dump_metrics(), the appctx flags are set before entering in a new scope, among others things to know which metrics names and descriptions to use. But, those flags are not restored when the dump is interrupted because of a full output buffer. If this happens after the dump of global metrics, it may only lead to extra #TYPE and #HELP lines. But if this happens during the dump of global metrics, the following dumps of frontends, backends and servers metrics use names and descriptions of global ones with the unmatching indexes. This first leads to unexisting metrics names. For instance, "haproxy_frontend_nbproc". But also to out-of-bound accesses to name and description arrays because there are more stats fields than info fields. It is easy to reproduce the bug using small buffers, setting tune.bufsize to 8192 for instance. This patch should fix the issue #666. It must be backported as far as 2.0. --- diff --git a/contrib/prometheus-exporter/service-prometheus.c b/contrib/prometheus-exporter/service-prometheus.c index f7542d26bc..dfd5e1a43c 100644 --- a/contrib/prometheus-exporter/service-prometheus.c +++ b/contrib/prometheus-exporter/service-prometheus.c @@ -2149,13 +2149,12 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx) static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *si, struct htx *htx) { int ret; - int flags = appctx->ctx.stats.flags; switch (appctx->st1) { case PROMEX_DUMPER_INIT: appctx->ctx.stats.px = NULL; appctx->ctx.stats.sv = NULL; - appctx->ctx.stats.flags = (flags|PROMEX_FL_METRIC_HDR|PROMEX_FL_INFO_METRIC); + appctx->ctx.stats.flags |= (PROMEX_FL_METRIC_HDR|PROMEX_FL_INFO_METRIC); appctx->st2 = promex_global_metrics[INF_NAME]; appctx->st1 = PROMEX_DUMPER_GLOBAL; /* fall through */ @@ -2172,7 +2171,8 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s appctx->ctx.stats.px = proxies_list; appctx->ctx.stats.sv = NULL; - appctx->ctx.stats.flags = (flags|PROMEX_FL_METRIC_HDR|PROMEX_FL_STATS_METRIC); + appctx->ctx.stats.flags &= ~PROMEX_FL_INFO_METRIC; + appctx->ctx.stats.flags |= (PROMEX_FL_METRIC_HDR|PROMEX_FL_STATS_METRIC); appctx->st2 = promex_front_metrics[ST_F_PXNAME]; appctx->st1 = PROMEX_DUMPER_FRONT; /* fall through */ @@ -2189,7 +2189,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s appctx->ctx.stats.px = proxies_list; appctx->ctx.stats.sv = NULL; - appctx->ctx.stats.flags = (flags|PROMEX_FL_METRIC_HDR|PROMEX_FL_STATS_METRIC); + appctx->ctx.stats.flags |= PROMEX_FL_METRIC_HDR; appctx->st2 = promex_back_metrics[ST_F_PXNAME]; appctx->st1 = PROMEX_DUMPER_BACK; /* fall through */ @@ -2206,7 +2206,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s appctx->ctx.stats.px = proxies_list; appctx->ctx.stats.sv = (appctx->ctx.stats.px ? appctx->ctx.stats.px->srv : NULL); - appctx->ctx.stats.flags = (flags|PROMEX_FL_METRIC_HDR|PROMEX_FL_STATS_METRIC); + appctx->ctx.stats.flags |= PROMEX_FL_METRIC_HDR; appctx->st2 = promex_srv_metrics[ST_F_PXNAME]; appctx->st1 = PROMEX_DUMPER_SRV; /* fall through */ @@ -2223,7 +2223,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s appctx->ctx.stats.px = NULL; appctx->ctx.stats.sv = NULL; - appctx->ctx.stats.flags = flags; + appctx->ctx.stats.flags &= ~(PROMEX_FL_METRIC_HDR|PROMEX_FL_INFO_METRIC|PROMEX_FL_STATS_METRIC); appctx->st2 = 0; appctx->st1 = PROMEX_DUMPER_DONE; /* fall through */