]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: vars: make functions vars_get_by_{name,desc} thread-safe
authorDragan Dosen <ddosen@haproxy.com>
Mon, 22 Feb 2021 16:20:01 +0000 (17:20 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 23 Feb 2021 16:22:46 +0000 (17:22 +0100)
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.

src/vars.c

index e3289996bde5decf82fadfcc37143b09c3fc14f7..251ffe12160e5a607ed359216441e4479b8f5247 100644 (file)
@@ -585,9 +585,13 @@ int vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *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)
 {
@@ -606,19 +610,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 <var_desc>. Returns 1
- * if the sample is filled, otherwise it returns 0.
+/* This function fills a sample with the content of the variable described
+ * by <var_desc>.
+ *
+ * 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)
 {
@@ -633,13 +647,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;
 }