From a0f85f3b67edd8362c8058e29af6f3695c27d31a Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 17 Jan 2017 14:09:30 +0000 Subject: [PATCH] [Fix] Avoid race condition on saving cache and reload MFH: true --- src/libserver/symbols_cache.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/libserver/symbols_cache.c b/src/libserver/symbols_cache.c index 74fcc0698..dca365e49 100644 --- a/src/libserver/symbols_cache.c +++ b/src/libserver/symbols_cache.c @@ -479,7 +479,10 @@ rspamd_symbols_cache_load_items (struct symbols_cache *cache, const gchar *name) return FALSE; } + rspamd_file_lock (fd, FALSE); + if (fstat (fd, &st) == -1) { + rspamd_file_unlock (fd, FALSE); close (fd); msg_info_cache ("cannot stat file %s, error %d, %s", name, errno, strerror (errno)); @@ -487,6 +490,7 @@ rspamd_symbols_cache_load_items (struct symbols_cache *cache, const gchar *name) } if (st.st_size < (gint)sizeof (*hdr)) { + rspamd_file_unlock (fd, FALSE); close (fd); errno = EINVAL; msg_info_cache ("cannot use file %s, error %d, %s", name, @@ -497,19 +501,22 @@ rspamd_symbols_cache_load_items (struct symbols_cache *cache, const gchar *name) map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { + rspamd_file_unlock (fd, FALSE); close (fd); msg_info_cache ("cannot mmap file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } - close (fd); hdr = map; if (memcmp (hdr->magic, rspamd_symbols_cache_magic, sizeof (rspamd_symbols_cache_magic)) != 0) { msg_info_cache ("cannot use file %s, bad magic", name); munmap (map, st.st_size); + rspamd_file_unlock (fd, FALSE); + close (fd); + return FALSE; } @@ -521,11 +528,16 @@ rspamd_symbols_cache_load_items (struct symbols_cache *cache, const gchar *name) ucl_parser_get_error (parser)); munmap (map, st.st_size); ucl_parser_free (parser); + rspamd_file_unlock (fd, FALSE); + close (fd); + return FALSE; } top = ucl_parser_get_object (parser); munmap (map, st.st_size); + rspamd_file_unlock (fd, FALSE); + close (fd); ucl_parser_free (parser); if (top == NULL || ucl_object_type (top) != UCL_OBJECT) { @@ -607,10 +619,10 @@ rspamd_symbols_cache_save_items (struct symbols_cache *cache, const gchar *name) struct ucl_emitter_functions *efunc; gpointer k, v; gint fd; - FILE *f; bool ret; - fd = open (name, O_CREAT | O_TRUNC | O_WRONLY, 00644); + (void)unlink (name); + fd = open (name, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL, 00644); if (fd == -1) { msg_info_cache ("cannot open file %s, error %d, %s", name, @@ -618,6 +630,8 @@ rspamd_symbols_cache_save_items (struct symbols_cache *cache, const gchar *name) return FALSE; } + rspamd_file_lock (fd, FALSE); + memset (&hdr, 0, sizeof (hdr)); memcpy (hdr.magic, rspamd_symbols_cache_magic, sizeof (rspamd_symbols_cache_magic)); @@ -625,6 +639,7 @@ rspamd_symbols_cache_save_items (struct symbols_cache *cache, const gchar *name) if (write (fd, &hdr, sizeof (hdr)) == -1) { msg_info_cache ("cannot write to file %s, error %d, %s", name, errno, strerror (errno)); + rspamd_file_unlock (fd, FALSE); close (fd); return FALSE; @@ -648,14 +663,12 @@ rspamd_symbols_cache_save_items (struct symbols_cache *cache, const gchar *name) ucl_object_insert_key (top, elt, k, 0, false); } - f = fdopen (fd, "a"); - g_assert (f != NULL); - - efunc = ucl_object_emit_file_funcs (f); + efunc = ucl_object_emit_fd_funcs (fd); ret = ucl_object_emit_full (top, UCL_EMIT_JSON_COMPACT, efunc, NULL); ucl_object_emit_funcs_free (efunc); ucl_object_unref (top); - fclose (f); + rspamd_file_unlock (fd, FALSE); + close (fd); return ret; } -- 2.39.5