Fix for hash table collision attack. We simply randomize hash table initialization value at startup time.

This commit is contained in:
antirez 2012-01-21 23:05:32 +01:00
parent 447ebf3bc7
commit a48c8d873b
4 changed files with 22 additions and 4 deletions

View File

@ -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();

View File

@ -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 */

View File

@ -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;

View File

@ -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();