From: Vsevolod Stakhov Date: Fri, 27 Feb 2026 10:42:20 +0000 (+0000) Subject: [Fix] Include HS magic in cache key hashes to force recompilation on version bump X-Git-Tag: 4.0.0~63 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2eabaed147047a2e74d2a487aa7fc3582bbd5f4;p=thirdparty%2Frspamd.git [Fix] Include HS magic in cache key hashes to force recompilation on version bump --- diff --git a/src/libserver/hyperscan_tools.cxx b/src/libserver/hyperscan_tools.cxx index 6e58516dbc..2dcc62e44f 100644 --- a/src/libserver/hyperscan_tools.cxx +++ b/src/libserver/hyperscan_tools.cxx @@ -940,6 +940,15 @@ gboolean rspamd_hyperscan_create_shared_unser(const char *serialized_data, static const unsigned char rspamd_hs_magic[] = {'r', 's', 'h', 's', 'r', 'e', '1', '2'}; #define RSPAMD_HS_MAGIC_LEN (sizeof(rspamd_hs_magic)) +const unsigned char * +rspamd_hyperscan_get_magic(gsize *len) +{ + if (len) { + *len = RSPAMD_HS_MAGIC_LEN; + } + return rspamd_hs_magic; +} + gboolean rspamd_hyperscan_serialize_with_header(hs_database_t *db, const unsigned int *ids, const unsigned int *flags, diff --git a/src/libserver/hyperscan_tools.h b/src/libserver/hyperscan_tools.h index 255e334e04..e2fd5c52a5 100644 --- a/src/libserver/hyperscan_tools.h +++ b/src/libserver/hyperscan_tools.h @@ -161,6 +161,15 @@ gboolean rspamd_hyperscan_validate_header(const char *data, gsize len, GError **err); +/** + * Get the hyperscan serialization magic bytes. + * Used to include magic in hash computations so that version bumps + * invalidate cached databases. + * @param[out] len length of magic bytes + * @return pointer to magic bytes (static storage) + */ +const unsigned char *rspamd_hyperscan_get_magic(gsize *len); + G_END_DECLS #endif diff --git a/src/libserver/maps/map_helpers.c b/src/libserver/maps/map_helpers.c index 627743f71e..5f6c276930 100644 --- a/src/libserver/maps/map_helpers.c +++ b/src/libserver/maps/map_helpers.c @@ -1411,6 +1411,12 @@ void rspamd_regexp_list_fin(struct map_cb_data *data, void **target) else { if (data->cur_data) { re_map = data->cur_data; +#ifdef WITH_HYPERSCAN + /* Include serialization magic so version bumps invalidate cache */ + gsize magic_len; + const unsigned char *magic = rspamd_hyperscan_get_magic(&magic_len); + rspamd_cryptobox_hash_update(&re_map->hst, magic, magic_len); +#endif rspamd_cryptobox_hash_final(&re_map->hst, re_map->re_digest); memcpy(&data->map->digest, re_map->re_digest, sizeof(data->map->digest)); rspamd_re_map_finalize(re_map); diff --git a/src/libserver/re_cache.c b/src/libserver/re_cache.c index bb9c3db858..9b8b87dd92 100644 --- a/src/libserver/re_cache.c +++ b/src/libserver/re_cache.c @@ -679,6 +679,10 @@ void rspamd_re_cache_init(struct rspamd_re_cache *cache, struct rspamd_config *c rspamd_cryptobox_hash_update(re_class->st, (gpointer) &re_class->num_local_re, sizeof(re_class->num_local_re)); + /* Include serialization magic so version bumps invalidate cache */ + rspamd_cryptobox_hash_update(re_class->st, + rspamd_hs_magic, + RSPAMD_HS_MAGIC_LEN); rspamd_cryptobox_hash_final(re_class->st, hash_out); rspamd_snprintf(re_class->hash, sizeof(re_class->hash), "%*xs", (int) rspamd_cryptobox_HASHBYTES, hash_out); diff --git a/src/libutil/multipattern.c b/src/libutil/multipattern.c index 16449cab88..f84a495f00 100644 --- a/src/libutil/multipattern.c +++ b/src/libutil/multipattern.c @@ -1223,6 +1223,11 @@ void rspamd_multipattern_get_hash(struct rspamd_multipattern *mp, g_assert(hs_populate_platform(&plt) == HS_SUCCESS); rspamd_cryptobox_hash_update(&hash_state, (void *) &plt, sizeof(plt)); + /* Include serialization magic so version bumps invalidate cache */ + gsize magic_len; + const unsigned char *magic = rspamd_hyperscan_get_magic(&magic_len); + rspamd_cryptobox_hash_update(&hash_state, magic, magic_len); + rspamd_cryptobox_hash_final(&hash_state, hash_out); return; }