From 616c716397034872a54bff935249eb02e53b94db Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Tue, 30 Dec 2025 11:39:46 +0100 Subject: [PATCH] MT#63826 db_redis: add string key length protection Introduce a list of improvements for size overflow protection: - change func signatures to work with `size_t` only - check the raw pointer and its length - introduce optional max allowed keys size This measure will protect inserts from extremely large key size (e.g. negative length that then gets into integer overflow) and from triggering the stack canary. Change-Id: I7e07e28b0ae398675f9980f42fe2b0f8ed61d51f (cherry picked from commit c1876f6bae469c92bd3007b851c8242742eac25d) --- debian/patches/series | 1 + .../db_redis_protect_length_overflow.patch | 121 ++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 debian/patches/sipwise/db_redis_protect_length_overflow.patch diff --git a/debian/patches/series b/debian/patches/series index d86ada50f..6ce00a453 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -45,6 +45,7 @@ sipwise/presence_offline_cleanup.patch ### active development sipwise/permissions-don-t-allow-reloads-in-the-middle-of-ong.patch sipwise/dlg_get_var_error_more_verbose_on_dlg +sipwise/db_redis_protect_length_overflow.patch ### Don't just put stuff in any order ### use gbp pq import/export tooling to help maintain patches ### diff --git a/debian/patches/sipwise/db_redis_protect_length_overflow.patch b/debian/patches/sipwise/db_redis_protect_length_overflow.patch new file mode 100644 index 000000000..f9161d6ff --- /dev/null +++ b/debian/patches/sipwise/db_redis_protect_length_overflow.patch @@ -0,0 +1,121 @@ +--- a/src/modules/db_redis/db_redis_mod.c ++++ b/src/modules/db_redis/db_redis_mod.c +@@ -42,6 +42,7 @@ MODULE_VERSION + str redis_keys = str_init(""); + str redis_schema_path = str_init(SHARE_DIR "db_redis/kamailio"); + int db_redis_verbosity = 1; ++unsigned int db_redis_max_key_len = 0; + + static int db_redis_bind_api(db_func_t *dbb); + static int mod_init(void); +@@ -60,6 +61,7 @@ static param_export_t params[] = { + {"keys", PARAM_STRING | PARAM_USE_FUNC, (void *)keys_param}, + {"schema_path", PARAM_STR, &redis_schema_path}, + {"verbosity", PARAM_INT, &db_redis_verbosity}, ++ {"max_key_length", PARAM_INT, &db_redis_max_key_len}, + #ifdef WITH_SSL + {"opt_tls", PARAM_INT, &db_redis_opt_tls}, + {"ca_path", PARAM_STRING, &db_redis_ca_path}, +--- a/src/modules/db_redis/redis_dbase.c ++++ b/src/modules/db_redis/redis_dbase.c +@@ -876,7 +876,7 @@ static int db_redis_scan_query_keys_patt + LM_ERR("Failed to add scan command to scan query\n"); + goto err; + } +- if(db_redis_key_add_string(&query_v, index_key->s, index_key->len) ++ if(db_redis_key_add_str(&query_v, index_key) + != 0) { + LM_ERR("Failed to add scan command to scan query\n"); + goto err; +@@ -891,8 +891,7 @@ static int db_redis_scan_query_keys_patt + LM_ERR("Failed to add match command to scan query\n"); + goto err; + } +- if(db_redis_key_add_string( +- &query_v, match_pattern->s, match_pattern->len) ++ if (db_redis_key_add_str(&query_v, match_pattern) + != 0) { + LM_ERR("Failed to add match pattern to scan query\n"); + goto err; +@@ -907,7 +906,7 @@ static int db_redis_scan_query_keys_patt + LM_ERR("Failed to print integer for scan query\n"); + goto err; + } +- if(db_redis_key_add_string(&query_v, match_count_str, l) != 0) { ++ if(db_redis_key_add_string(&query_v, match_count_str, (size_t)l) != 0) { + LM_ERR("Failed to add count value to scan query\n"); + goto err; + } +--- a/src/modules/db_redis/redis_table.c ++++ b/src/modules/db_redis/redis_table.c +@@ -24,14 +24,24 @@ + #include + #include + +-#include "db_redis_mod.h" +-#include "redis_connection.h" + #include "redis_table.h" + +-int db_redis_key_add_string(redis_key_t **list, const char *entry, int len) ++extern unsigned int db_redis_max_key_len; ++ ++int db_redis_key_add_string(redis_key_t **list, const char *entry, size_t len) + { + redis_key_t *k; + ++ if (!entry || !len) { ++ LM_ERR("Empty entry or zero length\n"); ++ return -1; ++ } ++ ++ if (db_redis_max_key_len > 0 && len > db_redis_max_key_len) { ++ LM_ERR("Too big length for key being added: allowed '%u' / given '%zu'\n", ++ db_redis_max_key_len, len); ++ return -1; ++ } + + k = (redis_key_t *)pkg_malloc(sizeof(redis_key_t)); + if(!k) { +@@ -69,13 +79,26 @@ err: + + int db_redis_key_add_str(redis_key_t **list, const str *entry) + { +- return db_redis_key_add_string(list, entry->s, entry->len); ++ if (entry->len < 0) ++ return -1; ++ return db_redis_key_add_string(list, entry->s, (size_t)entry->len); + } + +-int db_redis_key_prepend_string(redis_key_t **list, const char *entry, int len) ++int db_redis_key_prepend_string(redis_key_t **list, const char *entry, size_t len) + { + redis_key_t *k; + ++ if (!entry || !len) { ++ LM_ERR("Empty entry or zero length\n"); ++ return -1; ++ } ++ ++ if (db_redis_max_key_len > 0 && len > db_redis_max_key_len) { ++ LM_ERR("Too big length for key being prepended: allowed '%u' / given '%zu'\n", ++ db_redis_max_key_len, len); ++ return -1; ++ } ++ + k = (redis_key_t *)pkg_malloc(sizeof(redis_key_t)); + if(!k) { + LM_ERR("Failed to allocate memory for key list entry\n"); +--- a/src/modules/db_redis/redis_table.h ++++ b/src/modules/db_redis/redis_table.h +@@ -61,9 +61,9 @@ void db_redis_free_tables(km_redis_con_t + int db_redis_parse_schema(km_redis_con_t *con); + int db_redis_parse_keys(km_redis_con_t *con); + +-int db_redis_key_add_string(redis_key_t **list, const char *entry, int len); ++int db_redis_key_add_string(redis_key_t **list, const char *entry, size_t len); + int db_redis_key_add_str(redis_key_t **list, const str *entry); +-int db_redis_key_prepend_string(redis_key_t **list, const char *entry, int len); ++int db_redis_key_prepend_string(redis_key_t **list, const char *entry, size_t len); + int db_redis_key_list2arr(redis_key_t *list, char ***arr); + redis_key_t *db_redis_key_shift(redis_key_t **list); + void db_redis_key_free(redis_key_t **list);