From e88a512b2f370b3fcf5b0ff1205a0a84d156e060 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 27 Feb 2023 10:56:27 +0000 Subject: [PATCH] [Fix] Add hyperscan databases sanity check Issue: #4409 --- src/libserver/hyperscan_tools.cxx | 23 ++++++++++++++++++++++- src/libutil/multipattern.c | 16 ++++++++++------ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/libserver/hyperscan_tools.cxx b/src/libserver/hyperscan_tools.cxx index 615aa57aa..034184cba 100644 --- a/src/libserver/hyperscan_tools.cxx +++ b/src/libserver/hyperscan_tools.cxx @@ -306,7 +306,28 @@ static auto hs_shared_from_unserialized(raii_mmaped_file &&map) -> tl::expected { auto ptr = map.get_map(); - return tl::expected{tl::in_place, std::move(map), (hs_database_t *)ptr}; + auto db = (hs_database_t *)ptr; + + char *info = nullptr; + // Check HS database sanity (see #4409 for details) + auto ret = hs_database_info(db, &info); + + if (ret != HS_SUCCESS) { + if (info) { + g_free (info); + } + return tl::make_unexpected( + error{fmt::format("cannot use database {}: error code: {}", map.get_file().get_name(), ret), + ret, error_category::IMPORTANT}); + } + + msg_debug_hyperscan("database: %s, info: %s", map.get_file().get_name(), info); + + if (info) { + g_free (info); + } + + return tl::expected{tl::in_place, std::move(map), db}; } static auto diff --git a/src/libutil/multipattern.c b/src/libutil/multipattern.c index 0d6e8b4f4..e39374d42 100644 --- a/src/libutil/multipattern.c +++ b/src/libutil/multipattern.c @@ -429,8 +429,9 @@ rspamd_multipattern_try_save_hs (struct rspamd_multipattern *mp, rspamd_snprintf (fp, sizeof (fp), "%s/%*xs.hsmp.tmp", hs_cache_dir, (gint)rspamd_cryptobox_HASHBYTES / 2, hash); - if ((fd = rspamd_file_xopen (fp, O_WRONLY | O_CREAT | O_EXCL, 00644, 0)) != -1) { - if (hs_serialize_database (rspamd_hyperscan_get_database(mp->hs_db), &bytes, &len) == HS_SUCCESS) { + if ((fd = rspamd_file_xopen (fp, O_WRONLY | O_CREAT | O_EXCL, 00644, 1)) != -1) { + int ret; + if ((ret = hs_serialize_database (rspamd_hyperscan_get_database(mp->hs_db), &bytes, &len)) == HS_SUCCESS) { if (write (fd, bytes, len) == -1) { msg_warn ("cannot write hyperscan cache to %s: %s", fp, strerror (errno)); @@ -455,14 +456,17 @@ rspamd_multipattern_try_save_hs (struct rspamd_multipattern *mp, } } else { - msg_warn ("cannot serialize hyperscan cache to %s: %s", - fp, strerror (errno)); + msg_warn ("cannot serialize hyperscan cache to %s: error code %d", + fp, ret); unlink (fp); } close (fd); } + else { + msg_warn ("cannot open a temp file %s to write hyperscan cache: %s", fp, strerror(errno)); + } } #endif @@ -515,9 +519,9 @@ rspamd_multipattern_compile (struct rspamd_multipattern *mp, GError **err) /* Should not happen in the real life */ mp->hs_db = rspamd_hyperscan_from_raw_db(db, NULL); } - } - rspamd_multipattern_try_save_hs (mp, hash); + rspamd_multipattern_try_save_hs (mp, hash); + } for (i = 0; i < MAX_SCRATCH; i ++) { mp->scratch[i] = NULL; -- 2.39.5