From 151e1ca989968f5092baa593efd9f485e4947d17 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 5 Feb 2019 11:38:38 +0100 Subject: [PATCH] BUG/MAJOR: config: verify that targets of track-sc and stick rules are present Stick and track-sc rules may optionally designate a table in a different proxy. In this case, a number of verifications are made such as validating that this proxy actually exists. However, in multi-process mode, the target table might indeed exist but not be bound to the set of processes the rules will execute on. This will definitely result in a random behaviour especially if these tables do require peer synchronization, because some tasks will be started to try to synchronize form uninitialized areas. The typical issue looks like this : peers my-peers peer foo ... listen proxy bind-process 1 stick on src table ip ... backend ip bind-process 2 stick-table type ip size 1k peers my-peers While it appears obvious that the example above will not work, there are less obvious situations, such as having bind-process in a defaults section and having a larger set of processes for the referencing proxy than the referenced one. The present patch adds checks for such situations by verifying that all processes from the referencing proxy are present on the other one in all track-sc* and stick-* rules, and in sample fetch / converters referencing another table so that sc_inc_gpc0() and similar are safe as well. This fix must be backported to all maintained versions. It may potentially disrupt configurations which already randomly crash. There hardly is any intermediary solution though, such configurations need to be fixed. --- src/action.c | 5 +++++ src/cfgparse.c | 10 ++++++++++ src/sample.c | 6 ++++++ 3 files changed, 21 insertions(+) diff --git a/src/action.c b/src/action.c index 54d27a0f41..7574fba03d 100644 --- a/src/action.c +++ b/src/action.c @@ -51,6 +51,11 @@ int check_trk_action(struct act_rule *rule, struct proxy *px, char **err) trk_idx(rule->action)); return 0; } + else if (px->bind_proc & ~target->bind_proc) { + memprintf(err, "stick-table '%s' referenced by 'track-sc%d' rule not present on all processes covered by proxy '%s'", + target->id, trk_idx(rule->action), px->id); + return 0; + } else { free(rule->arg.trk_ctr.table.n); rule->arg.trk_ctr.table.t = &target->table; diff --git a/src/cfgparse.c b/src/cfgparse.c index 3e8a7f5c3a..a51771d44f 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -2649,6 +2649,11 @@ int check_config_validity() curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id); cfgerr++; } + else if (curproxy->bind_proc & ~target->bind_proc) { + ha_alert("Proxy '%s': stick-table '%s' referenced 'stick-store' rule not present on all processes covered by proxy '%s'.\n", + curproxy->id, target->id, curproxy->id); + return 0; + } else { free((void *)mrule->table.name); mrule->table.t = &(target->table); @@ -2682,6 +2687,11 @@ int check_config_validity() curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id); cfgerr++; } + else if (curproxy->bind_proc & ~target->bind_proc) { + ha_alert("Proxy '%s': stick-table '%s' referenced 'stick-store' rule not present on all processes covered by proxy '%s'.\n", + curproxy->id, target->id, curproxy->id); + return 0; + } else { free((void *)mrule->table.name); mrule->table.t = &(target->table); diff --git a/src/sample.c b/src/sample.c index 88217501d4..963cb597d2 100644 --- a/src/sample.c +++ b/src/sample.c @@ -1264,6 +1264,12 @@ int smp_resolve_args(struct proxy *p) break; } + if (p->bind_proc & ~px->bind_proc) { + ha_alert("parsing [%s:%d] : stick-table '%s' not present on all processes covered by proxy '%s'.\n", + cur->file, cur->line, px->id, p->id); + return 0; + } + free(arg->data.str.area); arg->data.str.area = NULL; arg->unresolved = 0; -- 2.39.5