commit 2c316e8: [Fix] Fix maps object update race condition
Vsevolod Stakhov
vsevolod at highsecure.ru
Wed Feb 27 14:28:08 UTC 2019
Author: Vsevolod Stakhov
Date: 2019-02-26 16:51:07 +0000
URL: https://github.com/rspamd/rspamd/commit/2c316e86a137b0622863c18b2b6e9f09c693fbc3
[Fix] Fix maps object update race condition
Issue: #2467
---
src/libserver/cfg_utils.c | 22 +++++++++++++---------
src/libserver/dynamic_cfg.c | 27 ++++++++++++++++-----------
src/libutil/map.c | 12 ++----------
src/libutil/map.h | 2 +-
src/libutil/map_helpers.c | 45 +++++++++++++++++++++++++++++----------------
src/libutil/map_helpers.h | 6 +++---
src/lua/lua_map.c | 14 +++++++++-----
src/plugins/surbl.c | 16 ++++++++++++----
8 files changed, 85 insertions(+), 59 deletions(-)
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c
index 5c6fc6672..af31db849 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.c
@@ -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
diff --git a/src/libserver/dynamic_cfg.c b/src/libserver/dynamic_cfg.c
index 1e970a17b..984a26697 100644
--- a/src/libserver/dynamic_cfg.c
+++ b/src/libserver/dynamic_cfg.c
@@ -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
diff --git a/src/libutil/map.c b/src/libutil/map.c
index bab145e5e..d4687e433 100644
--- a/src/libutil/map.c
+++ b/src/libutil/map.c
@@ -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);
diff --git a/src/libutil/map.h b/src/libutil/map.h
index 80aa03825..acf6eea4e 100644
--- a/src/libutil/map.h
+++ b/src/libutil/map.h
@@ -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,
diff --git a/src/libutil/map_helpers.c b/src/libutil/map_helpers.c
index ece3017ab..ec4d95183 100644
--- a/src/libutil/map_helpers.c
+++ b/src/libutil/map_helpers.c
@@ -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)
diff --git a/src/libutil/map_helpers.h b/src/libutil/map_helpers.h
index f7c86436f..4645024e3 100644
--- a/src/libutil/map_helpers.h
+++ b/src/libutil/map_helpers.h
@@ -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);
/**
diff --git a/src/lua/lua_map.c b/src/lua/lua_map.c
index 98b025ea2..3ba7d0ed1 100644
--- a/src/lua/lua_map.c
+++ b/src/lua/lua_map.c
@@ -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
diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c
index 842071afb..26af1210c 100644
--- a/src/plugins/surbl.c
+++ b/src/plugins/surbl.c
@@ -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;
More information about the Commits
mailing list