From bc7c207f745bf6406b38139b98cb5b8c794e13f0 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 12 Oct 2022 10:35:41 +0200 Subject: [PATCH] BUG/MAJOR: stick-tables: do not try to index a server name for applets Since commit 03cdf55e6 ("MINOR: stream: Stickiness server lookup by name.") in 2.0-dev6, server names may be used instead of their IDs, in order to perform stickiness. However the commit above may end up trying to insert an empty server name in the dictionary when the server is an applet instead, resulting in an immediate segfault. This is typically what happens when a "stick-store" rule is present in a backend featuring a "stats" directive. As there doesn't seem to be an easy way around it, it seems to imply that "stick-store" is not much used anymore. The solution here is to only try to insert non-null keys into the dictionary. The patch moves the check of the key type before the first lock so that the test on the key can be performed under the lock instead of locking twice (the patch is more readable with diff -b). Note that before 2.4, there's no variable there as it was introduced by commit 92149f9a8 ("MEDIUM: stick-tables: Add srvkey option to stick-table"), but the __objt_server(s->target)->id still needs to be tested. This needs to be backported as far as 2.0. --- src/stream.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/stream.c b/src/stream.c index a3c4a1ab70..b19519f84a 100644 --- a/src/stream.c +++ b/src/stream.c @@ -1424,24 +1424,25 @@ static int process_store_rules(struct stream *s, struct channel *rep, int an_bit } s->store[i].ts = NULL; - HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); - ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_ID); - stktable_data_cast(ptr, std_t_sint) = __objt_server(s->target)->puid; - HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); - if (t->server_key_type == STKTABLE_SRV_NAME) key = __objt_server(s->target)->id; else if (t->server_key_type == STKTABLE_SRV_ADDR) key = __objt_server(s->target)->addr_node.key; else - continue; + key = NULL; HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); - de = dict_insert(&server_key_dict, key); - if (de) { - ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_KEY); - stktable_data_cast(ptr, std_t_dict) = de; + ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_ID); + stktable_data_cast(ptr, std_t_sint) = __objt_server(s->target)->puid; + + if (key) { + de = dict_insert(&server_key_dict, key); + if (de) { + ptr = __stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_KEY); + stktable_data_cast(ptr, std_t_dict) = de; + } } + HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); stktable_touch_local(t, ts, 1); -- 2.39.5