From a48c8d873bc2a49f66ab398ebed51dc45764ca17 Mon Sep 17 00:00:00 2001 From: antirez Date: Sat, 21 Jan 2012 23:05:32 +0100 Subject: [PATCH] Fix for hash table collision attack. We simply randomize hash table initialization value at startup time. --- src/debug.c | 2 ++ src/dict.c | 14 ++++++++++++-- src/dict.h | 2 ++ src/redis.c | 8 ++++++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/debug.c b/src/debug.c index f16bcfd1..54920032 100644 --- a/src/debug.c +++ b/src/debug.c @@ -589,6 +589,8 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) { /* Log INFO and CLIENT LIST */ redisLog(REDIS_WARNING, "--- INFO OUTPUT"); infostring = genRedisInfoString("all"); + infostring = sdscatprintf(infostring, "hash_init_value: %u\n", + dictGetHashFunctionSeed()); redisLogRaw(REDIS_WARNING, infostring); redisLog(REDIS_WARNING, "--- CLIENT LIST OUTPUT"); clients = getAllClientsInfoString(); diff --git a/src/dict.c b/src/dict.c index a573bcd6..a3291375 100644 --- a/src/dict.c +++ b/src/dict.c @@ -85,10 +85,20 @@ unsigned int dictIdentityHashFunction(unsigned int key) return key; } +static int dict_hash_function_seed = 5183; + +void dictSetHashFunctionSeed(unsigned int seed) { + dict_hash_function_seed = seed; +} + +unsigned int dictGetHashFunctionSeed(void) { + return dict_hash_function_seed; +} + /* Generic hash function (a popular one from Bernstein). * I tested a few and this was the best. */ unsigned int dictGenHashFunction(const unsigned char *buf, int len) { - unsigned int hash = 5381; + unsigned int hash = dict_hash_function_seed; while (len--) hash = ((hash << 5) + hash) + (*buf++); /* hash * 33 + c */ @@ -97,7 +107,7 @@ unsigned int dictGenHashFunction(const unsigned char *buf, int len) { /* And a case insensitive version */ unsigned int dictGenCaseHashFunction(const unsigned char *buf, int len) { - unsigned int hash = 5381; + unsigned int hash = dict_hash_function_seed; while (len--) hash = ((hash << 5) + hash) + (tolower(*buf++)); /* hash * 33 + c */ diff --git a/src/dict.h b/src/dict.h index 76451047..5f856953 100644 --- a/src/dict.h +++ b/src/dict.h @@ -162,6 +162,8 @@ void dictEnableResize(void); void dictDisableResize(void); int dictRehash(dict *d, int n); int dictRehashMilliseconds(dict *d, int ms); +void dictSetHashFunctionSeed(unsigned int initval); +unsigned int dictGetHashFunctionSeed(void); /* Hash table types */ extern dictType dictTypeHeapStringCopyKey; diff --git a/src/redis.c b/src/redis.c index 3914003d..7446e72e 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1080,8 +1080,6 @@ void initServer() { scriptingInit(); slowlogInit(); bioInit(); - srand(time(NULL)^getpid()); - } /* Populates the Redis Command Table starting from the hard coded list @@ -1959,9 +1957,15 @@ void setupSignalHandlers(void) { int main(int argc, char **argv) { long long start; + struct timeval tv; + /* We need to initialize our libraries, and the server. */ zmalloc_enable_thread_safeness(); + srand(time(NULL)^getpid()); + gettimeofday(&tv,NULL); + dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid()); initServerConfig(); + if (argc >= 2) { int j = 1; /* First option to parse in argv[] */ sds options = sdsempty(); -- 2.47.2