commit e88a512: [Fix] Add hyperscan databases sanity check

Vsevolod Stakhov vsevolod at rspamd.com
Mon Feb 27 11:00:04 UTC 2023


Author: Vsevolod Stakhov
Date: 2023-02-27 10:56:27 +0000
URL: https://github.com/rspamd/rspamd/commit/e88a512b2f370b3fcf5b0ff1205a0a84d156e060 (HEAD -> master)

[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<hs_shared_database, error>
 {
 	auto ptr = map.get_map();
-	return tl::expected<hs_shared_database, error>{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<hs_shared_database, error>{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;


More information about the Commits mailing list