BUG/MINOR: peers: Use after free of "peers" section.
When a "peers" section has not any local peer, it is removed of the list
of "peers" sections by check_config_validity(). But a stick-table which
refers to a "peers" section stores a pointer to this peers section.
These pointer must be reset to NULL value for each stick-table refering to
such a "peers" section to prevent stktable_init() to start the peers frontend
attached to the peers section dereferencing the invalid pointer.
Furthemore this patch stops the peers frontend as this is done for other
configurations invalidated by check_config_validity().
Thank you to Olivier D for having reported this issue with such a
simple configuration file which made haproxy crash when started with
-c option for configuration file validation.
defaults
mode http
peers mypeers
peer toto 127.0.0.1:1024
backend test
stick-table type ip size 10k expire 1h store http_req_rate(1h) peers mypeers
Must be backported to 2.1 and 2.0.
(cherry picked from commit 87eacbb12fb819adb3acd68a221ead27c70efb43)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 26ca3d4aa8d6e18add3ca4c4b472c6e12be6f99b)
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/cfgparse.c b/src/cfgparse.c
index ff086be..a3cbca5 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -3962,6 +3962,7 @@
*/
last = &cfg_peers;
while (*last) {
+ struct stktable *t;
curpeers = *last;
if (curpeers->state == PR_STSTOPPED) {
@@ -3973,6 +3974,9 @@
else if (!curpeers->peers_fe || !curpeers->peers_fe->id) {
ha_warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
curpeers->id, localpeer);
+ if (curpeers->peers_fe)
+ stop_proxy(curpeers->peers_fe);
+ curpeers->peers_fe = NULL;
}
else if (atleast2(curpeers->peers_fe->bind_proc)) {
/* either it's totally stopped or too much used */
@@ -4035,6 +4039,11 @@
*/
free(curpeers->id);
curpeers = curpeers->next;
+ /* Reset any refereance to this peers section in the list of stick-tables */
+ for (t = stktables_list; t; t = t->next) {
+ if (t->peers.p && t->peers.p == *last)
+ t->peers.p = NULL;
+ }
free(*last);
*last = curpeers;
}