|
|
d864f0 |
Backported for 5.0.3
|
|
|
d864f0 |
|
|
|
d864f0 |
|
|
|
d864f0 |
|
|
|
d864f0 |
From c043ba77cf9bbf73e964fd9b8681c0cc4bd2662e Mon Sep 17 00:00:00 2001
|
|
|
d864f0 |
From: Oran Agra <oran@redislabs.com>
|
|
|
d864f0 |
Date: Sun, 26 Sep 2021 15:42:17 +0300
|
|
|
d864f0 |
Subject: [PATCH] Fix Integer overflow issue with intsets (CVE-2021-32687)
|
|
|
d864f0 |
|
|
|
d864f0 |
The vulnerability involves changing the default set-max-intset-entries
|
|
|
d864f0 |
configuration parameter to a very large value and constructing specially
|
|
|
d864f0 |
crafted commands to manipulate sets
|
|
|
d864f0 |
|
|
|
d864f0 |
(cherry picked from commit 4cb7075edaaf0584c74eb080d838ca8f56c190e3)
|
|
|
d864f0 |
---
|
|
|
d864f0 |
src/intset.c | 4 +++-
|
|
|
d864f0 |
src/rdb.c | 4 +++-
|
|
|
d864f0 |
src/t_set.c | 5 ++++-
|
|
|
d864f0 |
3 files changed, 10 insertions(+), 3 deletions(-)
|
|
|
d864f0 |
|
|
|
d864f0 |
diff --git a/src/intset.c b/src/intset.c
|
|
|
d864f0 |
index 4445a5ca6c56..288e19adff18 100644
|
|
|
d864f0 |
--- a/src/intset.c
|
|
|
d864f0 |
+++ b/src/intset.c
|
|
|
d864f0 |
@@ -34,6 +34,7 @@
|
|
|
d864f0 |
#include "intset.h"
|
|
|
d864f0 |
#include "zmalloc.h"
|
|
|
d864f0 |
#include "endianconv.h"
|
|
|
d864f0 |
+#include "redisassert.h"
|
|
|
d864f0 |
|
|
|
d864f0 |
/* Note that these encodings are ordered, so:
|
|
|
d864f0 |
* INTSET_ENC_INT16 < INTSET_ENC_INT32 < INTSET_ENC_INT64. */
|
|
|
d864f0 |
@@ -103,7 +104,8 @@ intset *intsetNew(void) {
|
|
|
d864f0 |
|
|
|
d864f0 |
/* Resize the intset */
|
|
|
d864f0 |
static intset *intsetResize(intset *is, uint32_t len) {
|
|
|
d864f0 |
- uint32_t size = len*intrev32ifbe(is->encoding);
|
|
|
d864f0 |
+ uint64_t size = (uint64_t)len*intrev32ifbe(is->encoding);
|
|
|
d864f0 |
+ assert(size <= SIZE_MAX - sizeof(intset));
|
|
|
d864f0 |
is = zrealloc(is,sizeof(intset)+size);
|
|
|
d864f0 |
return is;
|
|
|
d864f0 |
}
|
|
|
d864f0 |
diff --git a/src/rdb.c b/src/rdb.c
|
|
|
d864f0 |
index afbbd8ca450c..3c58a1eaf7fb 100644
|
|
|
d864f0 |
--- a/src/rdb.c
|
|
|
d864f0 |
+++ b/src/rdb.c
|
|
|
d864f0 |
@@ -1411,7 +1411,9 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key) {
|
|
|
d864f0 |
if ((len = rdbLoadLen(rdb,NULL)) == RDB_LENERR) return NULL;
|
|
|
d864f0 |
|
|
|
d864f0 |
/* Use a regular set when there are too many entries. */
|
|
|
d864f0 |
- if (len > server.set_max_intset_entries) {
|
|
|
d864f0 |
+ size_t max_entries = server.set_max_intset_entries;
|
|
|
d864f0 |
+ if (max_entries >= 1<<30) max_entries = 1<<30;
|
|
|
d864f0 |
+ if (len > max_entries) {
|
|
|
d864f0 |
o = createSetObject();
|
|
|
d864f0 |
/* It's faster to expand the dict to the right size asap in order
|
|
|
d864f0 |
* to avoid rehashing */
|
|
|
d864f0 |
diff --git a/src/t_set.c b/src/t_set.c
|
|
|
d864f0 |
index f67073fe6bb1..db5a8cb757bb 100644
|
|
|
d864f0 |
--- a/src/t_set.c
|
|
|
d864f0 |
+++ b/src/t_set.c
|
|
|
d864f0 |
@@ -66,7 +66,10 @@ int setTypeAdd(robj *subject, sds value) {
|
|
|
d864f0 |
if (success) {
|
|
|
d864f0 |
/* Convert to regular set when the intset contains
|
|
|
d864f0 |
* too many entries. */
|
|
|
d864f0 |
- if (intsetLen(subject->ptr) > server.set_max_intset_entries)
|
|
|
d864f0 |
+ size_t max_entries = server.set_max_intset_entries;
|
|
|
d864f0 |
+ /* limit to 1G entries due to intset internals. */
|
|
|
d864f0 |
+ if (max_entries >= 1<<30) max_entries = 1<<30;
|
|
|
d864f0 |
+ if (intsetLen(subject->ptr) > max_entries)
|
|
|
d864f0 |
setTypeConvert(subject,OBJ_ENCODING_HT);
|
|
|
d864f0 |
return 1;
|
|
|
d864f0 |
}
|