From: Vsevolod Stakhov Date: Tue, 8 Dec 2015 00:55:26 +0000 (+0000) Subject: Fix re-using of hyperscan hashes X-Git-Tag: 1.1.0~378 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=239c4e5d2e8ede4bcdc35058208371e8febaf6c1;p=thirdparty%2Frspamd.git Fix re-using of hyperscan hashes --- diff --git a/src/hs_helper.c b/src/hs_helper.c index 220224572f..9b0f5b7c88 100644 --- a/src/hs_helper.c +++ b/src/hs_helper.c @@ -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; + } } } } diff --git a/src/libserver/re_cache.c b/src/libserver/re_cache.c index af11f02c51..9614bd36fd 100644 --- a/src/libserver/re_cache.c +++ b/src/libserver/re_cache.c @@ -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 }