From: Ivan Suzdal Date: Mon, 8 Aug 2016 15:20:01 +0000 (+0300) Subject: Fix show server state through socket X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=ac06bc583798fd1f860823e63c254056abe540ae;p=packages%2Fxenial%2Fhaproxy.git Fix show server state through socket Change-Id: Ie1979fd39f8893acbe3b2059e91e544584ecca1d Related-Bug: #1608561 --- diff --git a/debian/changelog b/debian/changelog index 171089e..ed06bdd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +haproxy (1.6.3-1~u16.04+mos3) mos; urgency=medium + + * BUGFIX: show servers state may show an empty or incomplete result + - debian/patches/MIRA0002-Fix-show-server-state-through-socket.patch + Closes: #LP1608561 + + -- Ivan Suzdal Mon, 08 Aug 2016 15:19:24 +0000 + haproxy (1.6.3-1~u16.04+mos2) mos10.0; urgency=medium * SECURITY UPDATE: denial of service via reqdeny diff --git a/debian/patches/MIRA0002-Fix-show-server-state-through-socket.patch b/debian/patches/MIRA0002-Fix-show-server-state-through-socket.patch new file mode 100644 index 0000000..257a136 --- /dev/null +++ b/debian/patches/MIRA0002-Fix-show-server-state-through-socket.patch @@ -0,0 +1,155 @@ +--- a/include/types/applet.h ++++ b/include/types/applet.h +@@ -131,7 +131,9 @@ + struct dns_resolvers *ptr; + } resolvers; + struct { +- struct proxy *backend; ++ int iid; /* if >= 0, ID of the proxy to filter on */ ++ struct proxy *px; /* current proxy being dumped, NULL = not started yet. */ ++ struct server *sv; /* current server being dumped, NULL = not started yet. */ + } server_state; + } ctx; /* used by stats I/O handlers to dump the stats */ + }; +--- a/src/dumpstats.c ++++ b/src/dumpstats.c +@@ -148,7 +148,7 @@ + #endif + static void cli_release_handler(struct appctx *appctx); + +-static void dump_servers_state(struct proxy *backend, struct chunk *buf); ++static int dump_servers_state(struct stream_interface *si, struct chunk *buf); + + /* + * cli_io_handler() +@@ -1200,18 +1200,21 @@ + appctx->st0 = STAT_CLI_O_INFO; // stats_dump_info_to_buffer + } + else if (strcmp(args[1], "servers") == 0 && strcmp(args[2], "state") == 0) { +- appctx->ctx.server_state.backend = NULL; ++ appctx->ctx.server_state.iid = 0; ++ appctx->ctx.server_state.px = NULL; ++ appctx->ctx.server_state.sv = NULL; + + /* check if a backend name has been provided */ + if (*args[3]) { + /* read server state from local file */ +- appctx->ctx.server_state.backend = proxy_be_by_name(args[3]); ++ appctx->ctx.server_state.px = proxy_be_by_name(args[3]); + +- if (appctx->ctx.server_state.backend == NULL) { ++ if (!appctx->ctx.server_state.px) { + appctx->ctx.cli.msg = "Can't find backend.\n"; + appctx->st0 = STAT_CLI_PRINT; + return 1; + } ++ appctx->ctx.server_state.iid = appctx->ctx.server_state.px->uuid; + } + appctx->st2 = STAT_ST_INIT; + appctx->st0 = STAT_CLI_O_SERVERS_STATE; // stats_dump_servers_state_to_buffer +@@ -2736,20 +2739,24 @@ + * By default, we only export to the last known server state file format. + * These information can be used at next startup to recover same level of server state. + */ +-static void dump_servers_state(struct proxy *backend, struct chunk *buf) ++static int dump_servers_state(struct stream_interface *si, struct chunk *buf) + { ++ struct appctx *appctx = __objt_appctx(si->end); + struct server *srv; + char srv_addr[INET6_ADDRSTRLEN + 1]; + time_t srv_time_since_last_change; + int bk_f_forced_id, srv_f_forced_id; + ++ + /* we don't want to report any state if the backend is not enabled on this process */ +- if (backend->bind_proc && !(backend->bind_proc & (1UL << (relative_pid - 1)))) +- return; ++ if (appctx->ctx.server_state.px->bind_proc && !(appctx->ctx.server_state.px->bind_proc & (1UL << (relative_pid - 1)))) ++ return 1; + +- srv = backend->srv; ++ if (!appctx->ctx.server_state.sv) ++ appctx->ctx.server_state.sv = appctx->ctx.server_state.px->srv; + +- while (srv) { ++ for (; appctx->ctx.server_state.sv != NULL; appctx->ctx.server_state.sv = srv->next) { ++ srv = appctx->ctx.server_state.sv; + srv_addr[0] = '\0'; + srv_time_since_last_change = 0; + bk_f_forced_id = 0; +@@ -2766,7 +2773,7 @@ + break; + } + srv_time_since_last_change = now.tv_sec - srv->last_change; +- bk_f_forced_id = backend->options & PR_O_FORCED_ID ? 1 : 0; ++ bk_f_forced_id = appctx->ctx.server_state.px->options & PR_O_FORCED_ID ? 1 : 0; + srv_f_forced_id = srv->flags & SRV_F_FORCED_ID ? 1 : 0; + + chunk_appendf(buf, +@@ -2776,14 +2783,17 @@ + "%d %d %d %d %d " + "%d %d" + "\n", +- backend->uuid, backend->id, ++ appctx->ctx.server_state.px->uuid, appctx->ctx.server_state.px->id, + srv->puid, srv->id, srv_addr, + srv->state, srv->admin, srv->uweight, srv->iweight, (long int)srv_time_since_last_change, + srv->check.status, srv->check.result, srv->check.health, srv->check.state, srv->agent.state, + bk_f_forced_id, srv_f_forced_id); +- +- srv = srv->next; ++ if (bi_putchk(si_ic(si), &trash) == -1) { ++ si_applet_cant_put(si); ++ return 0; ++ } + } ++ return 1; + } + + /* Parses backend list and simply report backend names */ +@@ -2826,24 +2836,30 @@ + + chunk_reset(&trash); + +- chunk_printf(&trash, "%d\n# %s\n", SRV_STATE_FILE_VERSION, SRV_STATE_FILE_FIELD_NAMES); +- +- if (appctx->ctx.server_state.backend) { +- dump_servers_state(appctx->ctx.server_state.backend, &trash); +- } +- else { +- for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) { +- /* servers are only in backends */ +- if (!(curproxy->cap & PR_CAP_BE)) +- continue; +- +- dump_servers_state(curproxy, &trash); ++ if (!appctx->ctx.server_state.px) { ++ chunk_printf(&trash, "%d\n# %s\n", SRV_STATE_FILE_VERSION, SRV_STATE_FILE_FIELD_NAMES); ++ if (bi_putchk(si_ic(si), &trash) == -1) { ++ si_applet_cant_put(si); ++ return 0; + } ++ appctx->ctx.server_state.px = proxy; + } + +- if (bi_putchk(si_ic(si), &trash) == -1) { +- si_applet_cant_put(si); +- return 0; ++ for (; appctx->ctx.server_state.px != NULL; appctx->ctx.server_state.px = curproxy->next) { ++ curproxy = appctx->ctx.server_state.px; ++ /* servers are only in backends */ ++ if (curproxy->cap & PR_CAP_BE) { ++ if (!dump_servers_state(si, &trash)) ++ return 0; ++ ++ if (bi_putchk(si_ic(si), &trash) == -1) { ++ si_applet_cant_put(si); ++ return 0; ++ } ++ } ++ /* only the selected proxy is dumped */ ++ if (appctx->ctx.server_state.iid) ++ break; + } + + return 1; diff --git a/debian/patches/series b/debian/patches/series index 280e126..7ce1c9a 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -5,3 +5,4 @@ haproxy.service-check-config-before-reload.patch haproxy.service-use-environment-variables.patch CVE-2016-5360.patch MIRA0001-Adding-include-configuration-statement-to-haproxy.patch +MIRA0002-Fix-show-server-state-through-socket.patch