mirror of https://github.com/sipwise/kamailio.git
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 c1876f6bae)
mr14.0
parent
21ef42a00b
commit
616c716397
@ -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 <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
|
||||
-#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);
|
||||
Loading…
Reference in new issue