From 62b8b657d9d07844b8b72d21df5b8e66ee84ac43 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 29 Jul 2016 13:54:58 +0100 Subject: [PATCH] [Fix] Ensure that hyperscan cache written is written properly --- src/hs_helper.c | 22 ++++++++++++++++++++-- src/libserver/re_cache.c | 11 ++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/hs_helper.c b/src/hs_helper.c index 127cf2785..d2bcf891b 100644 --- a/src/hs_helper.c +++ b/src/hs_helper.c @@ -127,11 +127,11 @@ rspamd_hs_helper_cleanup_dir (struct hs_helper_ctx *ctx, gboolean forced) } globbuf.gl_offs = 0; - len = strlen (ctx->hs_dir) + 1 + sizeof ("*.hs"); + len = strlen (ctx->hs_dir) + 1 + sizeof ("*.hs.new") + 2; pattern = g_malloc (len); rspamd_snprintf (pattern, len, "%s%c%s", ctx->hs_dir, G_DIR_SEPARATOR, "*.hs"); - if ((rc = glob (pattern, GLOB_DOOFFS, NULL, &globbuf)) == 0) { + if ((rc = glob (pattern, 0, NULL, &globbuf)) == 0) { for (i = 0; i < globbuf.gl_pathc; i++) { if (forced || !rspamd_re_cache_is_valid_hyperscan_file (ctx->cfg->re_cache, @@ -149,6 +149,24 @@ rspamd_hs_helper_cleanup_dir (struct hs_helper_ctx *ctx, gboolean forced) ret = FALSE; } + globfree (&globbuf); + + memset (&globbuf, 0, sizeof (globbuf)); + rspamd_snprintf (pattern, len, "%s%c%s", ctx->hs_dir, G_DIR_SEPARATOR, "*.hs.new"); + if ((rc = glob (pattern, 0, NULL, &globbuf)) == 0) { + for (i = 0; i < globbuf.gl_pathc; i++) { + if (unlink (globbuf.gl_pathv[i]) == -1) { + msg_err ("cannot unlink %s: %s", globbuf.gl_pathv[i], + strerror (errno)); + ret = FALSE; + } + } + } + else if (rc != GLOB_NOMATCH) { + msg_err ("glob %s failed: %s", pattern, strerror (errno)); + ret = FALSE; + } + globfree (&globbuf); g_free (pattern); diff --git a/src/libserver/re_cache.c b/src/libserver/re_cache.c index dc993513c..9fa2688a2 100644 --- a/src/libserver/re_cache.c +++ b/src/libserver/re_cache.c @@ -1318,7 +1318,7 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, GHashTableIter it, cit; gpointer k, v; struct rspamd_re_class *re_class; - gchar path[PATH_MAX]; + gchar path[PATH_MAX], npath[PATH_MAX]; hs_database_t *test_db; gint fd, i, n, *hs_ids = NULL, pcre_flags, re_flags; guint64 crc; @@ -1371,6 +1371,8 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, continue; } + rspamd_snprintf (path, sizeof (path), "%s%c%s.hs.new", cache_dir, + G_DIR_SEPARATOR, re_class->hash); fd = open (path, O_CREAT|O_TRUNC|O_EXCL|O_WRONLY, 00600); if (fd == -1) { @@ -1471,6 +1473,7 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, g_free (hs_ids); g_free (hs_pats); close (fd); + unlink (path); hs_free_compile_error (hs_errors); return -1; @@ -1487,6 +1490,7 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, re_class->hash); close (fd); + unlink (path); g_free (hs_ids); g_free (hs_flags); hs_free_database (test_db); @@ -1514,6 +1518,7 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, else { iov[0].iov_base = (void *) rspamd_hs_magic; } + iov[0].iov_len = RSPAMD_HS_MAGIC_LEN; iov[1].iov_base = &cache->plt; iov[1].iov_len = sizeof (cache->plt); @@ -1535,6 +1540,7 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, "cannot serialize tree of regexp to %s: %s", path, strerror (errno)); close (fd); + unlink (path); g_free (hs_ids); g_free (hs_flags); g_free (hs_serialized); @@ -1566,7 +1572,10 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, g_free (hs_flags); } + fsync (fd); close (fd); + + /* Now rename temporary file to the new .hs file */ } return total; -- 2.39.5