Browse Source

Add more sanity checks when loading hyperscan cache

tags/1.2.0
Vsevolod Stakhov 8 years ago
parent
commit
de42879925
3 changed files with 52 additions and 10 deletions
  1. 1
    1
      src/hs_helper.c
  2. 50
    8
      src/libserver/re_cache.c
  3. 1
    1
      src/libserver/re_cache.h

+ 1
- 1
src/hs_helper.c View File

@@ -135,7 +135,7 @@ rspamd_hs_helper_cleanup_dir (struct hs_helper_ctx *ctx, gboolean forced)
for (i = 0; i < globbuf.gl_pathc; i++) {
if (forced ||
!rspamd_re_cache_is_valid_hyperscan_file (ctx->cfg->re_cache,
globbuf.gl_pathv[i], TRUE)) {
globbuf.gl_pathv[i], TRUE, TRUE)) {
if (unlink (globbuf.gl_pathv[i]) == -1) {
msg_err ("cannot unlink %s: %s", globbuf.gl_pathv[i],
strerror (errno));

+ 50
- 8
src/libserver/re_cache.c View File

@@ -1071,7 +1071,7 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache,
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, TRUE)) {
if (rspamd_re_cache_is_valid_hyperscan_file (cache, path, TRUE, TRUE)) {

fd = open (path, O_RDONLY, 00600);

@@ -1302,7 +1302,7 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache,

gboolean
rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
const char *path, gboolean silent)
const char *path, gboolean silent, gboolean try_load)
{
g_assert (cache != NULL);
g_assert (path != NULL);
@@ -1310,7 +1310,7 @@ rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
#ifndef WITH_HYPERSCAN
return FALSE;
#else
gint fd;
gint fd, n, ret;
guchar magicbuf[RSPAMD_HS_MAGIC_LEN];
GHashTableIter it;
gpointer k, v;
@@ -1318,6 +1318,8 @@ rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
gsize len;
const gchar *hash_pos;
hs_platform_info_t test_plt;
hs_database_t *test_db = NULL;
guchar *map, *p, *end;

len = strlen (path);

@@ -1380,9 +1382,49 @@ rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
return FALSE;
}

/* XXX: add crc check */
close (fd);

if (try_load) {
map = rspamd_file_xmap (path, PROT_READ, &len);

if (map == NULL) {
msg_err_re_cache ("cannot mmap hyperscan cache file %s: "
"%s",
path, strerror (errno));
return FALSE;
}

p = map + RSPAMD_HS_MAGIC_LEN + sizeof (test_plt);
end = map + len;
n = *(gint *)p;
p += sizeof (gint);

if (n <= 0 || 2 * n * sizeof (gint) + /* IDs + flags */
sizeof (guint64) + /* crc */
RSPAMD_HS_MAGIC_LEN + /* header */
sizeof (cache->plt) > len) {
/* Some wrong amount of regexps */
msg_err_re_cache ("bad number of expressions in %s: %d",
path, n);
munmap (map, len);
return FALSE;
}

p += n * sizeof (gint) * 2 + sizeof (guint64);

if ((ret = hs_deserialize_database (p, end - p, &test_db))
!= HS_SUCCESS) {
msg_err_re_cache ("bad hs database in %s: %d", path, ret);
munmap (map, len);

return FALSE;
}

hs_free_database (test_db);
munmap (map, len);
}
/* XXX: add crc check */

return TRUE;
}
}
@@ -1407,7 +1449,7 @@ rspamd_re_cache_load_hyperscan (struct rspamd_re_cache *cache,
return FALSE;
#else
gchar path[PATH_MAX];
gint fd, i, n, *hs_ids = NULL, *hs_flags = NULL, total = 0;
gint fd, i, n, *hs_ids = NULL, *hs_flags = NULL, total = 0, ret;
GHashTableIter it;
gpointer k, v;
guint8 *map, *p, *end;
@@ -1422,7 +1464,7 @@ rspamd_re_cache_load_hyperscan (struct rspamd_re_cache *cache,
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, FALSE)) {
if (rspamd_re_cache_is_valid_hyperscan_file (cache, path, FALSE, FALSE)) {
msg_debug_re_cache ("load hyperscan database from '%s'",
re_class->hash);

@@ -1484,9 +1526,9 @@ rspamd_re_cache_load_hyperscan (struct rspamd_re_cache *cache,
re_class->hs_scratch = NULL;
re_class->hs_db = NULL;

if (hs_deserialize_database (p, end - p, &re_class->hs_db)
if ((ret = hs_deserialize_database (p, end - p, &re_class->hs_db))
!= HS_SUCCESS) {
msg_err_re_cache ("bad hs database in %s", path);
msg_err_re_cache ("bad hs database in %s: %d", path, ret);
munmap (map, st.st_size);
g_free (hs_ids);
g_free (hs_flags);

+ 1
- 1
src/libserver/re_cache.h View File

@@ -152,7 +152,7 @@ gint rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache,
* Returns TRUE if the specified file is valid hyperscan cache
*/
gboolean rspamd_re_cache_is_valid_hyperscan_file (struct rspamd_re_cache *cache,
const char *path, gboolean silent);
const char *path, gboolean silent, gboolean try_load);

/**
* Loads all hyperscan regexps precompiled

Loading…
Cancel
Save