From: Dragan Dosen Date: Mon, 22 Feb 2021 16:20:01 +0000 (+0100) Subject: BUG/MEDIUM: vars: make functions vars_get_by_{name,desc} thread-safe X-Git-Tag: v2.1.12~31 X-Git-Url: http://git.haproxy.org/?a=commitdiff_plain;h=dd8b4da9e1bd908111a2829d5aadec338d345865;p=haproxy-2.1.git BUG/MEDIUM: vars: make functions vars_get_by_{name,desc} thread-safe This patch adds a lock to functions vars_get_by_name() and vars_get_by_desc() to protect accesses to the list of variables. After the variable is fetched, a sample data is duplicated by using smp_dup() because the variable may be modified by another thread. This should be backported to all versions supporting vars along with "BUG/MINOR: sample: secure convs that accept base64 string and var name as args" which this patch depends on. (cherry picked from commit 14518f2305027dfd537c1be0f88350337b5fba23) Signed-off-by: Christopher Faulet (cherry picked from commit bdea395d630bdb92e5d882e235439a1560e12296) Signed-off-by: Christopher Faulet (cherry picked from commit 6524481ea5ab6ca5888450d535d011046d7d2f80) Signed-off-by: Christopher Faulet --- diff --git a/src/vars.c b/src/vars.c index b2a2b7e..d76cadb 100644 --- a/src/vars.c +++ b/src/vars.c @@ -571,9 +571,13 @@ void vars_unset_by_name(const char *name, size_t len, struct sample *smp) sample_clear_stream(name, scope, smp); } -/* this function fills a sample with the - * variable content. Returns 1 if the sample - * is filled, otherwise it returns 0. +/* This function fills a sample with the variable content. + * + * Keep in mind that a sample content is duplicated by using smp_dup() + * and it therefore uses a pre-allocated trash chunk as returned by + * get_trash_chunk(). + * + * Returns 1 if the sample is filled, otherwise it returns 0. */ int vars_get_by_name(const char *name, size_t len, struct sample *smp) { @@ -592,19 +596,29 @@ int vars_get_by_name(const char *name, size_t len, struct sample *smp) return 0; /* Get the variable entry. */ + HA_RWLOCK_RDLOCK(VARS_LOCK, &vars->rwlock); var = var_get(vars, name); - if (!var) + if (!var) { + HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock); return 0; + } /* Copy sample. */ smp->data = var->data; - smp->flags = SMP_F_CONST; + smp_dup(smp); + + HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock); return 1; } -/* this function fills a sample with the - * content of the variable described by . Returns 1 - * if the sample is filled, otherwise it returns 0. +/* This function fills a sample with the content of the variable described + * by . + * + * Keep in mind that a sample content is duplicated by using smp_dup() + * and it therefore uses a pre-allocated trash chunk as returned by + * get_trash_chunk(). + * + * Returns 1 if the sample is filled, otherwise it returns 0. */ int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp) { @@ -619,13 +633,18 @@ int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp) return 0; /* Get the variable entry. */ + HA_RWLOCK_RDLOCK(VARS_LOCK, &vars->rwlock); var = var_get(vars, var_desc->name); - if (!var) + if (!var) { + HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock); return 0; + } /* Copy sample. */ smp->data = var->data; - smp->flags = SMP_F_CONST; + smp_dup(smp); + + HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock); return 1; }