]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
Fix re-using of hyperscan hashes
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 8 Dec 2015 00:55:26 +0000 (00:55 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 8 Dec 2015 00:55:26 +0000 (00:55 +0000)
src/hs_helper.c
src/libserver/re_cache.c

index 220224572fe2494aa63774906046555306c1d034..9b0f5b7c88736b89504843da0cbce1d3c6980681 100644 (file)
@@ -103,10 +103,13 @@ rspamd_hs_helper_cleanup_dir (struct hs_helper_ctx *ctx)
 
        if ((rc = glob (pattern, GLOB_DOOFFS, 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;
+                       if (!rspamd_re_cache_is_valid_hyperscan_file (ctx->cfg->re_cache,
+                                               globbuf.gl_pathv[i])) {
+                               if (unlink (globbuf.gl_pathv[i]) == -1) {
+                                       msg_err ("cannot unlink %s: %s", globbuf.gl_pathv[i],
+                                                       strerror (errno));
+                                       ret = FALSE;
+                               }
                        }
                }
        }
index af11f02c51451d269a17b94333e3913047ab553a..9614bd36fdeda3032617960e9649d706327457ee 100644 (file)
@@ -63,7 +63,7 @@ struct rspamd_re_class {
        gpointer type_data;
        gsize type_len;
        GHashTable *re;
-       gchar hash[rspamd_cryptobox_HASHBYTES * 2 + 1];
+       gchar hash[rspamd_cryptobox_HASHBYTES + 1];
 #ifdef WITH_HYPERSCAN
        hs_database_t *hs_db;
 
@@ -87,7 +87,7 @@ struct rspamd_re_cache {
        ref_entry_t ref;
        guint nre;
        guint max_re_data;
-       gchar hash[rspamd_cryptobox_HASHBYTES * 2 + 1];
+       gchar hash[rspamd_cryptobox_HASHBYTES + 1];
 #ifdef WITH_HYPERSCAN
        hs_platform_info_t plt;
 #endif
@@ -112,7 +112,7 @@ rspamd_re_cache_class_id (enum rspamd_re_type type,
 {
        XXH64_state_t st;
 
-       XXH64_reset (&st, rspamd_hash_seed ());
+       XXH64_reset (&st, 0xdeadbabe);
        XXH64_update (&st, &type, sizeof (type));
 
        if (datalen > 0) {
@@ -209,7 +209,7 @@ rspamd_re_cache_add (struct rspamd_re_cache *cache, rspamd_regexp_t *re,
        elt->re = rspamd_regexp_ref (re);
        g_ptr_array_add (cache->re, elt);
        rspamd_regexp_set_class (re, re_class);
-       g_hash_table_insert (re_class->re, nre, nre);
+       g_hash_table_insert (re_class->re, rspamd_regexp_get_id (nre), nre);
 }
 
 void
@@ -243,7 +243,9 @@ rspamd_re_cache_replace (struct rspamd_re_cache *cache,
                        /*
                         * On calling of this function, we actually unref old re (what)
                         */
-                       g_hash_table_insert (re_class->re, what, rspamd_regexp_ref (with));
+                       g_hash_table_insert (re_class->re,
+                                       rspamd_regexp_get_id (what),
+                                       rspamd_regexp_ref (with));
                }
 
                if (elt) {
@@ -732,6 +734,21 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache,
                re_class = v;
                rspamd_snprintf (path, sizeof (path), "%s%c%s.hs", cache_dir,
                                G_DIR_SEPARATOR, re_class->hash);
+
+               if (rspamd_re_cache_is_valid_hyperscan_file (cache, path)) {
+                       msg_info_re_cache ("skip already valid file for re class '%s'",
+                                       re_class->hash);
+
+                       fd = open (path, O_RDONLY, 00600);
+
+                       /* Read number of regexps */
+                       g_assert (fd != -1);
+                       lseek (fd, SEEK_SET, RSPAMD_HS_MAGIC_LEN);
+                       read (fd, &n, sizeof (n));
+                       total += n;
+                       continue;
+               }
+
                fd = open (path, O_CREAT|O_TRUNC|O_EXCL|O_WRONLY, 00600);
 
                if (fd == -1) {
@@ -888,7 +905,7 @@ rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
 
        len = strlen (path);
 
-       if (len < sizeof (rspamd_cryptobox_HASHBYTES * 2 + 3)) {
+       if (len < sizeof (rspamd_cryptobox_HASHBYTES + 3)) {
                return FALSE;
        }
 
@@ -896,7 +913,8 @@ rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
                return FALSE;
        }
 
-       hash_pos = path + len - 3 - rspamd_cryptobox_HASHBYTES * 2;
+       hash_pos = path + len - 3 - rspamd_cryptobox_HASHBYTES;
+       g_hash_table_iter_init (&it, cache->re_classes);
 
        while (g_hash_table_iter_next (&it, &k, &v)) {
                re_class = v;
@@ -918,6 +936,8 @@ rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
                                return FALSE;
                        }
 
+                       close (fd);
+
                        if (memcmp (magicbuf, rspamd_hs_magic, sizeof (magicbuf)) != 0) {
                                msg_err_re_cache ("cannot open hyperscan cache file %s: "
                                                "bad magic ('%*xs', '%*xs' expected)",
@@ -927,7 +947,13 @@ rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
 
                                return FALSE;
                        }
+
+                       return TRUE;
                }
        }
+
+       msg_warn_re_cache ("unknown hyperscan cache file %s", path);
+
+       return FALSE;
 #endif
 }