]> source.dussan.org Git - rspamd.git/commitdiff
[Fix] Ensure that hyperscan cache written is written properly
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 29 Jul 2016 12:54:58 +0000 (13:54 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 29 Jul 2016 12:54:58 +0000 (13:54 +0100)
src/hs_helper.c
src/libserver/re_cache.c

index 127cf278546ef2e84b5b92c66efbe3cf64f036e6..d2bcf891b2ee6ed7e00a124e1ed0d38d44a0b88d 100644 (file)
@@ -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);
 
index dc993513c25068fbeb8d92456f7427378c45962c..9fa2688a2662fe89180089ac29ca675165ce5140 100644 (file)
@@ -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;