Browse Source

Fix re-using of hyperscan hashes

tags/1.1.0
Vsevolod Stakhov 8 years ago
parent
commit
239c4e5d2e
2 changed files with 40 additions and 11 deletions
  1. 7
    4
      src/hs_helper.c
  2. 33
    7
      src/libserver/re_cache.c

+ 7
- 4
src/hs_helper.c View 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;
}
}
}
}

+ 33
- 7
src/libserver/re_cache.c View 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
}

Loading…
Cancel
Save