]> source.dussan.org Git - rspamd.git/commitdiff
[Fix] Fix maps object update race condition
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 26 Feb 2019 16:51:07 +0000 (16:51 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 26 Feb 2019 16:55:58 +0000 (16:55 +0000)
Issue: #2467

src/libserver/cfg_utils.c
src/libserver/dynamic_cfg.c
src/libutil/map.c
src/libutil/map.h
src/libutil/map_helpers.c
src/libutil/map_helpers.h
src/lua/lua_map.c
src/plugins/surbl.c

index 5c6fc6672ce81b6c7aed0412f8776b81ed66c9ac..af31db8494fa18595d44e5f3069f351b4f2db7a6 100644 (file)
@@ -58,7 +58,7 @@ static gchar * rspamd_ucl_read_cb (gchar * chunk,
        gint len,
        struct map_cb_data *data,
        gboolean final);
-static void rspamd_ucl_fin_cb (struct map_cb_data *data);
+static void rspamd_ucl_fin_cb (struct map_cb_data *data, void **target);
 static void rspamd_ucl_dtor_cb (struct map_cb_data *data);
 
 guint rspamd_config_log_id = (guint)-1;
@@ -1358,7 +1358,7 @@ rspamd_ucl_read_cb (gchar * chunk,
 }
 
 static void
-rspamd_ucl_fin_cb (struct map_cb_data *data)
+rspamd_ucl_fin_cb (struct map_cb_data *data, void **target)
 {
        struct rspamd_ucl_map_cbdata *cbdata = data->cur_data, *prev =
                data->prev_data;
@@ -1368,13 +1368,6 @@ rspamd_ucl_fin_cb (struct map_cb_data *data)
        const ucl_object_t *cur;
        struct rspamd_config *cfg = data->map->cfg;
 
-       if (prev != NULL) {
-               if (prev->buf != NULL) {
-                       g_string_free (prev->buf, TRUE);
-               }
-               g_free (prev);
-       }
-
        if (cbdata == NULL) {
                msg_err_config ("map fin error: new data is NULL");
                return;
@@ -1400,6 +1393,17 @@ rspamd_ucl_fin_cb (struct map_cb_data *data)
                }
                ucl_object_unref (obj);
        }
+
+       if (target) {
+               *target = data->cur_data;
+       }
+
+       if (prev != NULL) {
+               if (prev->buf != NULL) {
+                       g_string_free (prev->buf, TRUE);
+               }
+               g_free (prev);
+       }
 }
 
 static void
index 1e970a17b1e0d90d409e131691adce28c8bf40b7..984a26697b866721347f92942843d0be9eabaa58 100644 (file)
@@ -175,22 +175,12 @@ json_config_read_cb (gchar * chunk,
 }
 
 static void
-json_config_fin_cb (struct map_cb_data *data)
+json_config_fin_cb (struct map_cb_data *data, void **target)
 {
        struct config_json_buf *jb;
        ucl_object_t *top;
        struct ucl_parser *parser;
 
-       if (data->cur_data && data->prev_data) {
-               jb = data->prev_data;
-               /* Clean prev data */
-               if (jb->buf) {
-                       g_string_free (jb->buf, TRUE);
-               }
-
-               g_free (jb);
-       }
-
        /* Now parse json */
        if (data->cur_data) {
                jb = data->cur_data;
@@ -201,6 +191,7 @@ json_config_fin_cb (struct map_cb_data *data)
 
        if (jb->buf == NULL) {
                msg_err ("no data read");
+
                return;
        }
 
@@ -225,6 +216,20 @@ json_config_fin_cb (struct map_cb_data *data)
        ucl_object_unref (jb->cfg->current_dynamic_conf);
        apply_dynamic_conf (top, jb->cfg);
        jb->cfg->current_dynamic_conf = top;
+
+       if (target) {
+               *target = data->cur_data;
+       }
+
+       if (data->prev_data) {
+               jb = data->prev_data;
+               /* Clean prev data */
+               if (jb->buf) {
+                       g_string_free (jb->buf, TRUE);
+               }
+
+               g_free (jb);
+       }
 }
 
 static void
index bab145e5e1e98cc31e7ee6e12b02ac2c137c620f..d4687e433dc7c02f72b52a92201770bf3d47f3dd 100644 (file)
@@ -1153,11 +1153,7 @@ rspamd_map_periodic_dtor (struct map_periodic_cbdata *periodic)
 
        if (periodic->need_modify) {
                /* We are done */
-               periodic->map->fin_callback (&periodic->cbdata);
-
-               if (periodic->cbdata.cur_data) {
-                       *periodic->map->user_data = periodic->cbdata.cur_data;
-               }
+               periodic->map->fin_callback (&periodic->cbdata, periodic->map->user_data);
        }
        else {
                /* Not modified */
@@ -2038,11 +2034,7 @@ rspamd_map_preload (struct rspamd_config *cfg)
                        }
 
                        if (succeed) {
-                               map->fin_callback (&fake_cbd.cbdata);
-
-                               if (fake_cbd.cbdata.cur_data) {
-                                       *map->user_data = fake_cbd.cbdata.cur_data;
-                               }
+                               map->fin_callback (&fake_cbd.cbdata, map->user_data);
                        }
                        else {
                                msg_info_map ("preload of %s failed", map->name);
index 80aa03825c50cad7054d9b26bc27bcc1a9aa5d33..acf6eea4ec615691d055d89e111b01919afe6c5d 100644 (file)
@@ -21,7 +21,7 @@ struct map_cb_data;
  */
 typedef gchar * (*map_cb_t)(gchar *chunk, gint len,
        struct map_cb_data *data, gboolean final);
-typedef void (*map_fin_cb_t)(struct map_cb_data *data);
+typedef void (*map_fin_cb_t)(struct map_cb_data *data, void **target);
 typedef void (*map_dtor_t)(struct map_cb_data *data);
 
 typedef gboolean (*rspamd_map_traverse_cb)(gconstpointer key,
index ece3017abead67a34c4b06625ba105412a2f20e4..ec4d9518348a1c2a01b0df4c416f5122944fefe6 100644 (file)
@@ -815,16 +815,11 @@ rspamd_kv_list_read (
 }
 
 void
-rspamd_kv_list_fin (struct map_cb_data *data)
+rspamd_kv_list_fin (struct map_cb_data *data, void **target)
 {
        struct rspamd_map *map = data->map;
        struct rspamd_hash_map_helper *htb;
 
-       if (data->prev_data) {
-               htb = (struct rspamd_hash_map_helper *)data->prev_data;
-               rspamd_map_helper_destroy_hash (htb);
-       }
-
        if (data->cur_data) {
                htb = (struct rspamd_hash_map_helper *)data->cur_data;
                msg_info_map ("read hash of %d elements", kh_size (htb->htb));
@@ -832,6 +827,15 @@ rspamd_kv_list_fin (struct map_cb_data *data)
                data->map->nelts = kh_size (htb->htb);
                data->map->digest = rspamd_cryptobox_fast_hash_final (&htb->hst);
        }
+
+       if (target) {
+               *target = data->cur_data;
+       }
+
+       if (data->prev_data) {
+               htb = (struct rspamd_hash_map_helper *)data->prev_data;
+               rspamd_map_helper_destroy_hash (htb);
+       }
 }
 
 void
@@ -870,16 +874,11 @@ rspamd_radix_read (
 }
 
 void
-rspamd_radix_fin (struct map_cb_data *data)
+rspamd_radix_fin (struct map_cb_data *data, void **target)
 {
        struct rspamd_map *map = data->map;
        struct rspamd_radix_map_helper *r;
 
-       if (data->prev_data) {
-               r = (struct rspamd_radix_map_helper *)data->prev_data;
-               rspamd_map_helper_destroy_radix (r);
-       }
-
        if (data->cur_data) {
                r = (struct rspamd_radix_map_helper *)data->cur_data;
                msg_info_map ("read radix trie of %z elements: %s",
@@ -888,6 +887,15 @@ rspamd_radix_fin (struct map_cb_data *data)
                data->map->nelts = kh_size (r->htb);
                data->map->digest = rspamd_cryptobox_fast_hash_final (&r->hst);
        }
+
+       if (target) {
+               *target = data->cur_data;
+       }
+
+       if (data->prev_data) {
+               r = (struct rspamd_radix_map_helper *)data->prev_data;
+               rspamd_map_helper_destroy_radix (r);
+       }
 }
 
 void
@@ -1088,14 +1096,11 @@ rspamd_glob_list_read_multiple (
 
 
 void
-rspamd_regexp_list_fin (struct map_cb_data *data)
+rspamd_regexp_list_fin (struct map_cb_data *data, void **target)
 {
        struct rspamd_regexp_map_helper *re_map;
        struct rspamd_map *map = data->map;
 
-       if (data->prev_data) {
-               rspamd_map_helper_destroy_regexp (data->prev_data);
-       }
        if (data->cur_data) {
                re_map = data->cur_data;
                rspamd_re_map_finalize (re_map);
@@ -1105,6 +1110,14 @@ rspamd_regexp_list_fin (struct map_cb_data *data)
                data->map->nelts = kh_size (re_map->htb);
                data->map->digest = rspamd_cryptobox_fast_hash_final (&re_map->hst);
        }
+
+       if (target) {
+               *target = data->cur_data;
+       }
+
+       if (data->prev_data) {
+               rspamd_map_helper_destroy_regexp (data->prev_data);
+       }
 }
 void
 rspamd_regexp_list_dtor (struct map_cb_data *data)
index f7c86436f0a02dec6506396ff8453c190cf05851..4645024e377884138d69e4b0a73a70e056856772 100644 (file)
@@ -52,7 +52,7 @@ gchar * rspamd_radix_read (
                gint len,
                struct map_cb_data *data,
                gboolean final);
-void rspamd_radix_fin (struct map_cb_data *data);
+void rspamd_radix_fin (struct map_cb_data *data, void **target);
 void rspamd_radix_dtor (struct map_cb_data *data);
 
 /**
@@ -63,7 +63,7 @@ gchar * rspamd_kv_list_read (
                gint len,
                struct map_cb_data *data,
                gboolean final);
-void rspamd_kv_list_fin (struct map_cb_data *data);
+void rspamd_kv_list_fin (struct map_cb_data *data, void **target);
 void rspamd_kv_list_dtor (struct map_cb_data *data);
 
 /**
@@ -91,7 +91,7 @@ gchar * rspamd_glob_list_read_multiple (
                gint len,
                struct map_cb_data *data,
                gboolean final);
-void rspamd_regexp_list_fin (struct map_cb_data *data);
+void rspamd_regexp_list_fin (struct map_cb_data *data, void **target);
 void rspamd_regexp_list_dtor (struct map_cb_data *data);
 
 /**
index 98b025ea2faa59616da796bc25b10b83605dda3f..3ba7d0ed1a090e0dc8d09b3f7169eb78e9945559 100644 (file)
@@ -416,7 +416,7 @@ lua_map_read (gchar *chunk, gint len,
 }
 
 static void
-lua_map_fin (struct map_cb_data *data)
+lua_map_fin (struct map_cb_data *data, void **target)
 {
        struct lua_map_callback_data *cbdata;
        struct rspamd_lua_map **pmap;
@@ -432,10 +432,6 @@ lua_map_fin (struct map_cb_data *data)
                return;
        }
 
-       if (data->prev_data) {
-               data->prev_data = NULL;
-       }
-
        if (cbdata->ref == -1) {
                msg_err_map ("map has no callback set");
        }
@@ -454,6 +450,14 @@ lua_map_fin (struct map_cb_data *data)
        }
 
        cbdata->data = rspamd_fstring_assign (cbdata->data, "", 0);
+
+       if (target) {
+               *target = data->cur_data;
+       }
+
+       if (data->prev_data) {
+               data->prev_data = NULL;
+       }
 }
 
 static void
index 842071afbbed7babf84b1a97c882270cc4bd47b6..26af1210c8f1397a303c613263cef419f7d7e697 100644 (file)
@@ -270,11 +270,15 @@ read_exceptions_list (gchar * chunk,
 }
 
 static void
-fin_exceptions_list (struct map_cb_data *data)
+fin_exceptions_list (struct map_cb_data *data, void **target)
 {
        GHashTable **t;
        gint i;
 
+       if (target) {
+               *target = data->cur_data;
+       }
+
        if (data->prev_data) {
                t = data->prev_data;
                for (i = 0; i < MAX_LEVELS; i++) {
@@ -385,11 +389,15 @@ read_redirectors_list (gchar * chunk,
                           final);
 }
 
-void
-fin_redirectors_list (struct map_cb_data *data)
+static void
+fin_redirectors_list (struct map_cb_data *data, void **target)
 {
        GHashTable *tld_hash;
 
+       if (target) {
+               *target = data->cur_data;
+       }
+
        if (data->prev_data) {
                tld_hash = data->prev_data;
 
@@ -397,7 +405,7 @@ fin_redirectors_list (struct map_cb_data *data)
        }
 }
 
-void
+static void
 dtor_redirectors_list (struct map_cb_data *data)
 {
        GHashTable *tld_hash;