diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Aesthetic-changes-to-PR.patch | 185 | ||||
-rw-r--r-- | CVE-2019-10193.patch | 30 | ||||
-rw-r--r-- | CVE-2020-14147.patch | 50 | ||||
-rw-r--r-- | CVE-2021-21309.patch | 150 | ||||
-rw-r--r-- | CVE-2021-29478.patch | 35 | ||||
-rw-r--r-- | CVE-2021-32672.patch | 132 | ||||
-rw-r--r-- | CVE-2021-3470.patch | 39 | ||||
-rw-r--r-- | CVE-2022-36021.patch | 92 | ||||
-rw-r--r-- | CVE-2023-28856.patch | 49 | ||||
-rw-r--r-- | huawei-deps-jemalloc-support-riscv.patch | 62 | ||||
-rw-r--r-- | improved-HyperLogLog-cardinality-estimation.patch | 328 | ||||
-rw-r--r-- | modify-aarch64-architecture-jemalloc-page-size-from-4k-to-64k.patch | 13 | ||||
-rw-r--r-- | redis-sentinel.service | 14 | ||||
-rw-r--r-- | redis.logrotate | 9 | ||||
-rw-r--r-- | redis.service | 15 | ||||
-rw-r--r-- | redis.spec | 181 | ||||
-rw-r--r-- | sources | 1 |
18 files changed, 1386 insertions, 0 deletions
@@ -0,0 +1 @@ +/redis-4.0.14.tar.gz diff --git a/Aesthetic-changes-to-PR.patch b/Aesthetic-changes-to-PR.patch new file mode 100644 index 0000000..77e848e --- /dev/null +++ b/Aesthetic-changes-to-PR.patch @@ -0,0 +1,185 @@ +From 7413dc16572ffd672835c1391b08409472771093 Mon Sep 17 00:00:00 2001 +From: antirez <antirez@gmail.com> +Date: Fri, 16 Mar 2018 16:57:53 +0100 +Subject: [PATCH] Aesthetic changes to PR #4749. + +--- + src/hyperloglog.c | 80 +++++++++++++++++++++++------------------------ + 1 file changed, 40 insertions(+), 40 deletions(-) + +diff --git a/src/hyperloglog.c b/src/hyperloglog.c +index 77109c8..68d591c 100644 +--- a/src/hyperloglog.c ++++ b/src/hyperloglog.c +@@ -403,7 +403,7 @@ uint64_t MurmurHash64A (const void * key, int len, unsigned int seed) { + + #if (BYTE_ORDER == LITTLE_ENDIAN) + #ifdef USE_ALIGNED_ACCESS +- memcpy(&k,data,sizeof(uint64_t)); ++ memcpy(&k,data,sizeof(uint64_t)); + #else + k = *((uint64_t*)data); + #endif +@@ -512,7 +512,7 @@ int hllDenseAdd(uint8_t *registers, unsigned char *ele, size_t elesize) { + } + + /* Compute the register histogram in the dense representation. */ +-void hllDenseRegHisto(uint8_t *registers, int* regHisto) { ++void hllDenseRegHisto(uint8_t *registers, int* reghisto) { + int j; + + /* Redis default is to use 16384 registers 6 bits each. The code works +@@ -541,22 +541,22 @@ void hllDenseRegHisto(uint8_t *registers, int* regHisto) { + r14 = (r[10] >> 4 | r[11] << 4) & 63; + r15 = (r[11] >> 2) & 63; + +- regHisto[r0] += 1; +- regHisto[r1] += 1; +- regHisto[r2] += 1; +- regHisto[r3] += 1; +- regHisto[r4] += 1; +- regHisto[r5] += 1; +- regHisto[r6] += 1; +- regHisto[r7] += 1; +- regHisto[r8] += 1; +- regHisto[r9] += 1; +- regHisto[r10] += 1; +- regHisto[r11] += 1; +- regHisto[r12] += 1; +- regHisto[r13] += 1; +- regHisto[r14] += 1; +- regHisto[r15] += 1; ++ reghisto[r0]++; ++ reghisto[r1]++; ++ reghisto[r2]++; ++ reghisto[r3]++; ++ reghisto[r4]++; ++ reghisto[r5]++; ++ reghisto[r6]++; ++ reghisto[r7]++; ++ reghisto[r8]++; ++ reghisto[r9]++; ++ reghisto[r10]++; ++ reghisto[r11]++; ++ reghisto[r12]++; ++ reghisto[r13]++; ++ reghisto[r14]++; ++ reghisto[r15]++; + + r += 12; + } +@@ -564,7 +564,7 @@ void hllDenseRegHisto(uint8_t *registers, int* regHisto) { + for(j = 0; j < HLL_REGISTERS; j++) { + unsigned long reg; + HLL_DENSE_GET_REGISTER(reg,registers,j); +- regHisto[reg] += 1; ++ reghisto[reg]++; + } + } + } +@@ -904,7 +904,7 @@ int hllSparseAdd(robj *o, unsigned char *ele, size_t elesize) { + } + + /* Compute the register histogram in the sparse representation. */ +-void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* regHisto) { ++void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* reghisto) { + int idx = 0, runlen, regval; + uint8_t *end = sparse+sparselen, *p = sparse; + +@@ -912,18 +912,18 @@ void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* regHis + if (HLL_SPARSE_IS_ZERO(p)) { + runlen = HLL_SPARSE_ZERO_LEN(p); + idx += runlen; +- regHisto[0] += runlen; ++ reghisto[0] += runlen; + p++; + } else if (HLL_SPARSE_IS_XZERO(p)) { + runlen = HLL_SPARSE_XZERO_LEN(p); + idx += runlen; +- regHisto[0] += runlen; ++ reghisto[0] += runlen; + p += 2; + } else { + runlen = HLL_SPARSE_VAL_LEN(p); + regval = HLL_SPARSE_VAL_VALUE(p); + idx += runlen; +- regHisto[regval] += runlen; ++ reghisto[regval] += runlen; + p++; + } + } +@@ -938,24 +938,24 @@ void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* regHis + + /* Implements the register histogram calculation for uint8_t data type + * which is only used internally as speedup for PFCOUNT with multiple keys. */ +-void hllRawRegHisto(uint8_t *registers, int* regHisto) { ++void hllRawRegHisto(uint8_t *registers, int* reghisto) { + uint64_t *word = (uint64_t*) registers; + uint8_t *bytes; + int j; + + for (j = 0; j < HLL_REGISTERS/8; j++) { + if (*word == 0) { +- regHisto[0] += 8; ++ reghisto[0] += 8; + } else { + bytes = (uint8_t*) word; +- regHisto[bytes[0]] += 1; +- regHisto[bytes[1]] += 1; +- regHisto[bytes[2]] += 1; +- regHisto[bytes[3]] += 1; +- regHisto[bytes[4]] += 1; +- regHisto[bytes[5]] += 1; +- regHisto[bytes[6]] += 1; +- regHisto[bytes[7]] += 1; ++ reghisto[bytes[0]]++; ++ reghisto[bytes[1]]++; ++ reghisto[bytes[2]]++; ++ reghisto[bytes[3]]++; ++ reghisto[bytes[4]]++; ++ reghisto[bytes[5]]++; ++ reghisto[bytes[6]]++; ++ reghisto[bytes[7]]++; + } + word++; + } +@@ -1011,16 +1011,16 @@ uint64_t hllCount(struct hllhdr *hdr, int *invalid) { + double E; + int j; + double alphaInf = 0.5 / log(2.); +- int regHisto[HLL_Q+2] = {0}; ++ int reghisto[HLL_Q+2] = {0}; + + /* Compute register histogram */ + if (hdr->encoding == HLL_DENSE) { +- hllDenseRegHisto(hdr->registers,regHisto); ++ hllDenseRegHisto(hdr->registers,reghisto); + } else if (hdr->encoding == HLL_SPARSE) { + hllSparseRegHisto(hdr->registers, +- sdslen((sds)hdr)-HLL_HDR_SIZE,invalid,regHisto); ++ sdslen((sds)hdr)-HLL_HDR_SIZE,invalid,reghisto); + } else if (hdr->encoding == HLL_RAW) { +- hllRawRegHisto(hdr->registers,regHisto); ++ hllRawRegHisto(hdr->registers,reghisto); + } else { + serverPanic("Unknown HyperLogLog encoding in hllCount()"); + } +@@ -1028,12 +1028,12 @@ uint64_t hllCount(struct hllhdr *hdr, int *invalid) { + /* Estimate cardinality form register histogram. See: + * "New cardinality estimation algorithms for HyperLogLog sketches" + * Otmar Ertl, arXiv:1702.01284 */ +- double z = m * hllTau((m-regHisto[HLL_Q+1])/(double)m); ++ double z = m * hllTau((m-reghisto[HLL_Q+1])/(double)m); + for (j = HLL_Q; j >= 1; --j) { +- z += regHisto[j]; ++ z += reghisto[j]; + z *= 0.5; + } +- z += m * hllSigma(regHisto[0]/(double)m); ++ z += m * hllSigma(reghisto[0]/(double)m); + E = llroundl(alphaInf*m*m/z); + + return (uint64_t) E; +-- +2.23.0 + diff --git a/CVE-2019-10193.patch b/CVE-2019-10193.patch new file mode 100644 index 0000000..80edfd3 --- /dev/null +++ b/CVE-2019-10193.patch @@ -0,0 +1,30 @@ +From 4c7eda965af7f231148219267c9b039d06cab519 Mon Sep 17 00:00:00 2001 +From: antirez <antirez@gmail.com> +Date: Fri, 15 Mar 2019 17:10:16 +0100 +Subject: [PATCH] HyperLogLog: enlarge reghisto variable for safety. + +--- + src/hyperloglog.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/hyperloglog.c b/src/hyperloglog.c +index 68d591c..24cf81a 100644 +--- a/src/hyperloglog.c ++++ b/src/hyperloglog.c +@@ -1011,7 +1011,12 @@ uint64_t hllCount(struct hllhdr *hdr, int *invalid) { + double E; + int j; + double alphaInf = 0.5 / log(2.); +- int reghisto[HLL_Q+2] = {0}; ++ /* Note that reghisto could be just HLL_Q+1, becuase this is the ++ * maximum frequency of the "000...1" sequence the hash function is ++ * able to return. However it is slow to check for sanity of the ++ * input: instead we history array at a safe size: overflows will ++ * just write data to wrong, but correctly allocated, places. */ ++ int reghisto[64] = {0}; + + /* Compute register histogram */ + if (hdr->encoding == HLL_DENSE) { +-- +2.23.0 + diff --git a/CVE-2020-14147.patch b/CVE-2020-14147.patch new file mode 100644 index 0000000..7225224 --- /dev/null +++ b/CVE-2020-14147.patch @@ -0,0 +1,50 @@ +From ef764dde1cca2f25d00686673d1bc89448819571 Mon Sep 17 00:00:00 2001 +From: Seunghoon Woo <toad58@nate.com> +Date: Mon, 10 Feb 2020 16:32:46 +0900 +Subject: [PATCH] [FIX] revisit CVE-2015-8080 vulnerability + +--- + deps/lua/src/lua_struct.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/deps/lua/src/lua_struct.c b/deps/lua/src/lua_struct.c +index 4d5f027b85c..c58c8e72b08 100644 +--- a/deps/lua/src/lua_struct.c ++++ b/deps/lua/src/lua_struct.c +@@ -89,12 +89,14 @@ typedef struct Header { + } Header; + + +-static int getnum (const char **fmt, int df) { ++static int getnum (lua_State *L, const char **fmt, int df) { + if (!isdigit(**fmt)) /* no number? */ + return df; /* return default value */ + else { + int a = 0; + do { ++ if (a > (INT_MAX / 10) || a * 10 > (INT_MAX - (**fmt - '0'))) ++ luaL_error(L, "integral size overflow"); + a = a*10 + *((*fmt)++) - '0'; + } while (isdigit(**fmt)); + return a; +@@ -115,9 +117,9 @@ static size_t optsize (lua_State *L, char opt, const char **fmt) { + case 'f': return sizeof(float); + case 'd': return sizeof(double); + case 'x': return 1; +- case 'c': return getnum(fmt, 1); ++ case 'c': return getnum(L, fmt, 1); + case 'i': case 'I': { +- int sz = getnum(fmt, sizeof(int)); ++ int sz = getnum(L, fmt, sizeof(int)); + if (sz > MAXINTSIZE) + luaL_error(L, "integral size %d is larger than limit of %d", + sz, MAXINTSIZE); +@@ -150,7 +152,7 @@ static void controloptions (lua_State *L, int opt, const char **fmt, + case '>': h->endian = BIG; return; + case '<': h->endian = LITTLE; return; + case '!': { +- int a = getnum(fmt, MAXALIGN); ++ int a = getnum(L, fmt, MAXALIGN); + if (!isp2(a)) + luaL_error(L, "alignment %d is not a power of 2", a); + h->align = a; diff --git a/CVE-2021-21309.patch b/CVE-2021-21309.patch new file mode 100644 index 0000000..6e91579 --- /dev/null +++ b/CVE-2021-21309.patch @@ -0,0 +1,150 @@ +From 48f04a82a0ac542341fb644a4cfbebadd5c59a33 Mon Sep 17 00:00:00 2001 +From: Yossi Gottlieb <yossigo@gmail.com> +Date: Mon, 22 Feb 2021 15:41:32 +0200 +Subject: [PATCH] Fix integer overflow (CVE-2021-21309). (#8522) + +On 32-bit systems, setting the proto-max-bulk-len config parameter to a high value may result with integer overflow and a subsequent heap overflow when parsing an input bulk (CVE-2021-21309). + +This fix has two parts: + +Set a reasonable limit to the config parameter. +Add additional checks to prevent the problem in other potential but unknown code paths. + +(cherry picked from commit d32f2e9999ce003bad0bd2c3bca29f64dcce4433) + +Fix MSVR reported issue. +--- + src/config.c | 16 ++++++++-------- + src/sds.c | 3 +++ + src/zmalloc.c | 10 ++++++++++ + 3 files changed, 21 insertions(+), 8 deletions(-) + +diff --git a/src/config.c b/src/config.c +index 5f22442ecc5..0814768b9d9 100644 +--- a/src/config.c ++++ b/src/config.c +@@ -817,10 +817,10 @@ void loadServerConfig(char *filename, ch + if (max != LLONG_MAX && ll > max) goto badfmt; \ + _var = ll; + +-#define config_set_memory_field(_name,_var) \ ++#define config_set_memory_field(_name,_var,min,max) \ + } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \ + ll = memtoll(o->ptr,&err); \ +- if (err || ll < 0) goto badfmt; \ ++ if (err || ll < (long long) (min) || ll > (long long) (max)) goto badfmt; \ + _var = ll; + + #define config_set_enum_field(_name,_var,_enumvar) \ +@@ -1063,7 +1063,7 @@ void configSetCommand(client *c) { + } config_set_numerical_field( + "active-defrag-threshold-upper",server.active_defrag_threshold_upper,0,1000) { + } config_set_memory_field( +- "active-defrag-ignore-bytes",server.active_defrag_ignore_bytes) { ++ "active-defrag-ignore-bytes",server.active_defrag_ignore_bytes,0,LONG_MAX) { + } config_set_numerical_field( + "active-defrag-cycle-min",server.active_defrag_cycle_min,1,99) { + } config_set_numerical_field( +@@ -1139,7 +1139,7 @@ void configSetCommand(client *c) { + + /* Memory fields. + * config_set_memory_field(name,var) */ +- } config_set_memory_field("maxmemory",server.maxmemory) { ++ } config_set_memory_field("maxmemory",server.maxmemory,0,LONG_MAX) { + if (server.maxmemory) { + if (server.maxmemory < zmalloc_used_memory()) { + serverLog(LL_WARNING,"WARNING: the new maxmemory value set via CONFIG SET is smaller than the current memory usage. This will result in keys eviction and/or inability to accept new write commands depending on the maxmemory-policy."); +@@ -1147,12 +1147,12 @@ void configSetCommand(client *c) { + freeMemoryIfNeeded(); + } + } config_set_memory_field( +- "proto-max-bulk-len",server.proto_max_bulk_len) { ++ "proto-max-bulk-len",server.proto_max_bulk_len,1024*1024,LONG_MAX/2) { + } config_set_memory_field( +- "client-query-buffer-limit",server.client_max_querybuf_len) { +- } config_set_memory_field("repl-backlog-size",ll) { ++ "client-query-buffer-limit",server.client_max_querybuf_len,0,LONG_MAX) { ++ } config_set_memory_field("repl-backlog-size",ll,0,LONG_MAX) { + resizeReplicationBacklog(ll); +- } config_set_memory_field("auto-aof-rewrite-min-size",ll) { ++ } config_set_memory_field("auto-aof-rewrite-min-size",ll,0,LONG_MAX) { + server.aof_rewrite_min_size = ll; + + /* Enumeration fields. +diff --git a/src/sds.c b/src/sds.c +index cd60946bdd3..12c9da356d9 100644 +--- a/src/sds.c ++++ b/src/sds.c +@@ -91,6 +91,7 @@ sds sdsnewlen(const void *init, size_t initlen) { + int hdrlen = sdsHdrSize(type); + unsigned char *fp; /* flags pointer. */ + ++ assert(hdrlen+initlen+1 > initlen); /* Catch size_t overflow */ + sh = s_malloc(hdrlen+initlen+1); + if (!init) + memset(sh, 0, hdrlen+initlen+1); +@@ -207,6 +208,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) { + len = sdslen(s); + sh = (char*)s-sdsHdrSize(oldtype); + newlen = (len+addlen); ++ assert(newlen > len); /* Catch size_t overflow */ + if (newlen < SDS_MAX_PREALLOC) + newlen *= 2; + else +@@ -220,6 +222,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) { + if (type == SDS_TYPE_5) type = SDS_TYPE_8; + + hdrlen = sdsHdrSize(type); ++ assert(hdrlen+newlen+1 > len); /* Catch size_t overflow */ + if (oldtype==type) { + newsh = s_realloc(sh, hdrlen+newlen+1); + if (newsh == NULL) return NULL; +diff --git a/src/zmalloc.c b/src/zmalloc.c +index 972db79d7ab..29e68180f0d 100644 +--- a/src/zmalloc.c ++++ b/src/zmalloc.c +@@ -55,6 +55,12 @@ void zlibc_free(void *ptr) { + #endif + #endif + ++#if PREFIX_SIZE > 0 ++#define ASSERT_NO_SIZE_OVERFLOW(sz) assert((sz) + PREFIX_SIZE > (sz)) ++#else ++#define ASSERT_NO_SIZE_OVERFLOW(sz) ++#endif ++ + /* Explicitly override malloc/free etc when using tcmalloc. */ + #if defined(USE_TCMALLOC) + #define malloc(size) tc_malloc(size) +@@ -95,6 +101,7 @@ static void zmalloc_default_oom(size_t size) { + static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom; + + void *zmalloc(size_t size) { ++ ASSERT_NO_SIZE_OVERFLOW(size); + void *ptr = malloc(size+PREFIX_SIZE); + + if (!ptr) zmalloc_oom_handler(size); +@@ -113,6 +120,7 @@ void *zmalloc(size_t size) { + * Currently implemented only for jemalloc. Used for online defragmentation. */ + #ifdef HAVE_DEFRAG + void *zmalloc_no_tcache(size_t size) { ++ ASSERT_NO_SIZE_OVERFLOW(size); + void *ptr = mallocx(size+PREFIX_SIZE, MALLOCX_TCACHE_NONE); + if (!ptr) zmalloc_oom_handler(size); + update_zmalloc_stat_alloc(zmalloc_size(ptr)); +@@ -127,6 +135,7 @@ void zfree_no_tcache(void *ptr) { + #endif + + void *zcalloc(size_t size) { ++ ASSERT_NO_SIZE_OVERFLOW(size); + void *ptr = calloc(1, size+PREFIX_SIZE); + + if (!ptr) zmalloc_oom_handler(size); +@@ -141,6 +150,7 @@ void *zcalloc(size_t size) { + } + + void *zrealloc(void *ptr, size_t size) { ++ ASSERT_NO_SIZE_OVERFLOW(size); + #ifndef HAVE_MALLOC_SIZE + void *realptr; + #endif diff --git a/CVE-2021-29478.patch b/CVE-2021-29478.patch new file mode 100644 index 0000000..c7002c2 --- /dev/null +++ b/CVE-2021-29478.patch @@ -0,0 +1,35 @@ +From ef78ba0a7793a0b6be026ec77ef3c7e919efa08a Mon Sep 17 00:00:00 2001 +From: Oran Agra <oran@redislabs.com> +Date: Mon, 3 May 2021 08:27:22 +0300 +Subject: [PATCH] Fix integer overflow in intset (CVE-2021-29478) + +An integer overflow bug in Redis 6.2 could be exploited to corrupt the heap and +potentially result with remote code execution. + +The vulnerability involves changing the default set-max-intset-entries +configuration value, creating a large set key that consists of integer values +and using the COPY command to duplicate it. + +The integer overflow bug exists in all versions of Redis starting with 2.6, +where it could result with a corrupted RDB or DUMP payload, but not exploited +through COPY (which did not exist before 6.2). +--- + src/intset.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/intset.c b/src/intset.c +index 198c90a..8d35536 100644 +--- a/src/intset.c ++++ b/src/intset.c +@@ -278,7 +278,7 @@ uint32_t intsetLen(const intset *is) { + + /* Return intset blob size in bytes. */ + size_t intsetBlobLen(intset *is) { +- return sizeof(intset)+intrev32ifbe(is->length)*intrev32ifbe(is->encoding); ++ return sizeof(intset)+(size_t)intrev32ifbe(is->length)*intrev32ifbe(is->encoding); + } + + #ifdef REDIS_TEST +-- +2.23.0 + diff --git a/CVE-2021-32672.patch b/CVE-2021-32672.patch new file mode 100644 index 0000000..9c4780a --- /dev/null +++ b/CVE-2021-32672.patch @@ -0,0 +1,132 @@ +From 6ac3c0b7abd35f37201ed2d6298ecef4ea1ae1dd Mon Sep 17 00:00:00 2001 +From: "meir@redislabs.com" <meir@redislabs.com> +Date: Sun, 13 Jun 2021 14:29:20 +0300 +Subject: [PATCH] Fix protocol parsing on 'ldbReplParseCommand' + (CVE-2021-32672) + +The protocol parsing on 'ldbReplParseCommand' (LUA debugging)Assumed protocol correctness. This means that if the following +is given: +*1 +$100 +test +The parser will try to read additional 94 unallocated bytes after +the client buffer. +This commit fixes this issue by validating that there are actually enough +bytes to read. It also limits the amount of data that can be sent by +the debugger client to 1M so the client will not be able to explode +the memory. +--- + src/scripting.c | 29 +++++++++++++++++++++++++---- + tests/unit/scripting.tcl | 14 ++++++++++++++ + 2 files changed, 39 insertions(+), 4 deletions(-) + +diff --git a/src/scripting.c b/src/scripting.c +index a781e68..ecb6811 100644 +--- a/src/scripting.c ++++ b/src/scripting.c +@@ -1784,7 +1784,8 @@ int ldbDelBreakpoint(int line) { + /* Expect a valid multi-bulk command in the debugging client query buffer. + * On success the command is parsed and returned as an array of SDS strings, + * otherwise NULL is returned and there is to read more buffer. */ +-sds *ldbReplParseCommand(int *argcp) { ++sds *ldbReplParseCommand(int *argcp, char** err) { ++ static char* protocol_error = "protocol error"; + sds *argv = NULL; + int argc = 0; + if (sdslen(ldb.cbuf) == 0) return NULL; +@@ -1801,7 +1802,7 @@ sds *ldbReplParseCommand(int *argcp) { + /* Seek and parse *<count>\r\n. */ + p = strchr(p,'*'); if (!p) goto protoerr; + char *plen = p+1; /* Multi bulk len pointer. */ +- p = strstr(p,"\r\n"); if (!p) goto protoerr; ++ p = strstr(p,"\r\n"); if (!p) goto keep_reading; + *p = '\0'; p += 2; + *argcp = atoi(plen); + if (*argcp <= 0 || *argcp > 1024) goto protoerr; +@@ -1810,12 +1811,16 @@ sds *ldbReplParseCommand(int *argcp) { + argv = zmalloc(sizeof(sds)*(*argcp)); + argc = 0; + while(argc < *argcp) { ++ // reached the end but there should be more data to read ++ if (*p == '\0') goto keep_reading; ++ + if (*p != '$') goto protoerr; + plen = p+1; /* Bulk string len pointer. */ +- p = strstr(p,"\r\n"); if (!p) goto protoerr; ++ p = strstr(p,"\r\n"); if (!p) goto keep_reading; + *p = '\0'; p += 2; + int slen = atoi(plen); /* Length of this arg. */ + if (slen <= 0 || slen > 1024) goto protoerr; ++ if ((size_t)(p + slen + 2 - copy) > sdslen(copy) ) goto keep_reading; + argv[argc++] = sdsnewlen(p,slen); + p += slen; /* Skip the already parsed argument. */ + if (p[0] != '\r' || p[1] != '\n') goto protoerr; +@@ -1825,6 +1830,8 @@ sds *ldbReplParseCommand(int *argcp) { + return argv; + + protoerr: ++ *err = protocol_error; ++keep_reading: + sdsfreesplitres(argv,argc); + sdsfree(copy); + return NULL; +@@ -2246,12 +2253,17 @@ void ldbMaxlen(sds *argv, int argc) { + int ldbRepl(lua_State *lua) { + sds *argv; + int argc; ++ char* err = NULL; + + /* We continue processing commands until a command that should return + * to the Lua interpreter is found. */ + while(1) { +- while((argv = ldbReplParseCommand(&argc)) == NULL) { ++ while((argv = ldbReplParseCommand(&argc, &err)) == NULL) { + char buf[1024]; ++ if (err) { ++ lua_pushstring(lua, err); ++ lua_error(lua); ++ } + int nread = read(ldb.fd,buf,sizeof(buf)); + if (nread <= 0) { + /* Make sure the script runs without user input since the +@@ -2261,6 +2273,15 @@ int ldbRepl(lua_State *lua) { + return C_ERR; + } + ldb.cbuf = sdscatlen(ldb.cbuf,buf,nread); ++ /* after 1M we will exit with an error ++ * so that the client will not blow the memory ++ */ ++ if (sdslen(ldb.cbuf) > 1<<20) { ++ sdsfree(ldb.cbuf); ++ ldb.cbuf = sdsempty(); ++ lua_pushstring(lua, "max client buffer reached"); ++ lua_error(lua); ++ } + } + + /* Flush the old buffer. */ +diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl +index be82e15..48c9f1f 100644 +--- a/tests/unit/scripting.tcl ++++ b/tests/unit/scripting.tcl +@@ -733,3 +733,17 @@ start_server {tags {"scripting repl"}} { + } + } + ++start_server {tags {"scripting needs:debug external:skip"}} { ++ test {Test scripting debug protocol parsing} { ++ r script debug sync ++ r eval {return 'hello'} 0 ++ catch {r 'hello\0world'} e ++ assert_match {*Unknown Redis Lua debugger command*} $e ++ catch {r 'hello\0'} e ++ assert_match {*Unknown Redis Lua debugger command*} $e ++ catch {r '\0hello'} e ++ assert_match {*Unknown Redis Lua debugger command*} $e ++ catch {r '\0hello\0'} e ++ assert_match {*Unknown Redis Lua debugger command*} $e ++ } ++} +-- +2.27.0 + diff --git a/CVE-2021-3470.patch b/CVE-2021-3470.patch new file mode 100644 index 0000000..d49e271 --- /dev/null +++ b/CVE-2021-3470.patch @@ -0,0 +1,39 @@ +From a714d2561b78985ec85f3056aac83c603cbaaa5f Mon Sep 17 00:00:00 2001 +From: wang_yue111 <648774160@qq.com> +Date: Wed, 7 Apr 2021 10:00:53 +0800 +Subject: [PATCH] Fix wrong zmalloc_size() assumption. (#7963) + +When using a system with no malloc_usable_size(), zmalloc_size() assumed +that the heap allocator always returns blocks that are long-padded. + +This may not always be the case, and will result with zmalloc_size() +returning a size that is bigger than allocated. At least in one case +this leads to out of bound write, process crash and a potential security +vulnerability. + +Effectively this does not affect the vast majority of users, who use +jemalloc or glibc. + +This problem along with a (different) fix was reported by Drew DeVault. + +--- + src/zmalloc.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/zmalloc.c b/src/zmalloc.c +index cc47f71..67b1b65 100644 +--- a/src/zmalloc.c ++++ b/src/zmalloc.c +@@ -186,9 +186,6 @@ void *zrealloc(void *ptr, size_t size) { + size_t zmalloc_size(void *ptr) { + void *realptr = (char*)ptr-PREFIX_SIZE; + size_t size = *((size_t*)realptr); +- /* Assume at least that all the allocations are padded at sizeof(long) by +- * the underlying allocator. */ +- if (size&(sizeof(long)-1)) size += sizeof(long)-(size&(sizeof(long)-1)); + return size+PREFIX_SIZE; + } + #endif +-- +2.23.0 + diff --git a/CVE-2022-36021.patch b/CVE-2022-36021.patch new file mode 100644 index 0000000..0eb5b30 --- /dev/null +++ b/CVE-2022-36021.patch @@ -0,0 +1,92 @@ +From dcbfcb916ca1a269b3feef86ee86835294758f84 Mon Sep 17 00:00:00 2001 +From: Oran Agra <oran@redislabs.com> +Date: Tue, 28 Feb 2023 15:15:26 +0200 +Subject: [PATCH] String pattern matching had exponential time complexity on + pathological patterns (CVE-2022-36021) (#11858) + +Authenticated users can use string matching commands with a +specially crafted pattern to trigger a denial-of-service attack on Redis, +causing it to hang and consume 100% CPU time. + +Co-authored-by: Tom Levy <tomlevy93@gmail.com> +--- + src/util.c | 27 +++++++++++++++++++++++---- + tests/unit/keyspace.tcl | 6 ++++++ + 2 files changed, 29 insertions(+), 4 deletions(-) + +diff --git a/src/util.c b/src/util.c +index d33f4522a507..26d92b92290e 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -44,8 +44,8 @@ + #include "sha1.h" + + /* Glob-style pattern matching. */ +-int stringmatchlen(const char *pattern, int patternLen, +- const char *string, int stringLen, int nocase) ++static int stringmatchlen_impl(const char *pattern, int patternLen, ++ const char *string, int stringLen, int nocase, int *skipLongerMatches) + { + while(patternLen && stringLen) { + switch(pattern[0]) { +@@ -57,12 +57,24 @@ + if (patternLen == 1) + return 1; /* match */ + while(stringLen) { +- if (stringmatchlen(pattern+1, patternLen-1, +- string, stringLen, nocase)) ++ if (stringmatchlen_impl(pattern+1, patternLen-1, ++ string, stringLen, nocase, skipLongerMatches)) + return 1; /* match */ ++ if (*skipLongerMatches) ++ return 0; /* no match */ + string++; + stringLen--; + } ++ /* There was no match for the rest of the pattern starting ++ * from anywhere in the rest of the string. If there were ++ * any '*' earlier in the pattern, we can terminate the ++ * search early without trying to match them to longer ++ * substrings. This is because a longer match for the ++ * earlier part of the pattern would require the rest of the ++ * pattern to match starting later in the string, and we ++ * have just determined that there is no match for the rest ++ * of the pattern starting from anywhere in the current ++ * string. */ + return 0; /* no match */ + break; + case '?': +@@ -166,10 +178,17 @@ + return 0; + } + ++int stringmatchlen(const char *pattern, int patternLen, ++ const char *string, int stringLen, int nocase) { ++ int skipLongerMatches = 0; ++ return stringmatchlen_impl(pattern,patternLen,string,stringLen,nocase,&skipLongerMatches); ++} ++ + int stringmatch(const char *pattern, const char *string, int nocase) { + return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase); + } + ++ + /* Convert a string representing an amount of memory into the number of + * bytes, so for instance memtoll("1Gb") will return 1073741824 that is + * (1024*1024*1024). + +diff --git a/tests/unit/keyspace.tcl b/tests/unit/keyspace.tcl +index b173e0efcacc..43690d06b321 100644 +--- a/tests/unit/keyspace.tcl ++++ b/tests/unit/keyspace.tcl +@@ -493,4 +493,10 @@ foreach {type large} [array get largevalue] { + r keys * + r keys * + } {dlskeriewrioeuwqoirueioqwrueoqwrueqw} ++ ++ test {Regression for pattern matching long nested loops} { ++ r flushdb ++ r SET aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1 ++ r KEYS "a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*b" ++ } {} + } diff --git a/CVE-2023-28856.patch b/CVE-2023-28856.patch new file mode 100644 index 0000000..43ceb81 --- /dev/null +++ b/CVE-2023-28856.patch @@ -0,0 +1,49 @@ +From c924ac3fdf8fe544891dc66c88018e259ee4be87 Mon Sep 17 00:00:00 2001 +From: chendianqiang <c.d_q@163.com> +Date: Sun, 28 Aug 2022 16:33:41 +0800 +Subject: [PATCH] fix hincrbyfloat not to create a key if the new value is + invalid (#11149) + +Check the validity of the value before performing the create operation, +prevents new data from being generated even if the request fails to execute. + +Co-authored-by: Oran Agra <oran@redislabs.com> +Co-authored-by: chendianqiang <chendianqiang@meituan.com> +Co-authored-by: Binbin <binloveplay1314@qq.com> +(cherry picked from commit bc7fe41e5857a0854d524e2a63a028e9394d2a5c) +(cherry picked from commit 606a385935363ea46c0df4f40f8a949d85f7a20a) +(cherry picked from commit 7df23a5f51488ce002411c9d24b38520ad67b764) +--- + src/t_hash.c | 4 ++++ + tests/unit/type/hash.tcl | 5 +++++ + 2 files changed, 9 insertions(+) + +diff --git a/src/t_hash.c b/src/t_hash.c +index 3cdfdd169abf..13e65502f145 100644 +--- a/src/t_hash.c ++++ b/src/t_hash.c +@@ -605,6 +605,10 @@ void hincrbyfloatCommand(client *c) { + unsigned int vlen; + + if (getLongDoubleFromObjectOrReply(c,c->argv[3],&incr,NULL) != C_OK) return; ++ if (isnan(incr) || isinf(incr)) { ++ addReplyError(c,"value is NaN or Infinity"); ++ return; ++ } + if ((o = hashTypeLookupWriteOrCreate(c,c->argv[1])) == NULL) return; + if (hashTypeGetValue(o,c->argv[2]->ptr,&vstr,&vlen,&ll) == C_OK) { + if (vstr) { +diff --git a/tests/unit/type/hash.tcl b/tests/unit/type/hash.tcl +index 9f8a21b1ce11..931662989d82 100644 +--- a/tests/unit/type/hash.tcl ++++ b/tests/unit/type/hash.tcl +@@ -540,4 +540,9 @@ start_server {tags {"hash"}} { + assert {[r hincrbyfloat myhash float -0.1] eq {1.9}} + } + } ++ ++ test {HINCRBYFLOAT does not allow NaN or Infinity} { ++ assert_error "*value is NaN or Infinity*" {r hincrbyfloat hfoo field +inf} ++ assert_equal 0 [r exists hfoo] ++ } + } diff --git a/huawei-deps-jemalloc-support-riscv.patch b/huawei-deps-jemalloc-support-riscv.patch new file mode 100644 index 0000000..2a486b9 --- /dev/null +++ b/huawei-deps-jemalloc-support-riscv.patch @@ -0,0 +1,62 @@ +From 1b9b76419cf0b6c2ff73bb0d02c8c04896bdde20 Mon Sep 17 00:00:00 2001 +From: yangyanchao <yangyanchao6@huawei.com> +Date: Wed, 11 Nov 2020 17:49:37 +0800 +Subject: [PATCH] jemalloc_support_riscv + +--- + deps/jemalloc/config.guess | 3 +++ + deps/jemalloc/config.sub | 2 ++ + deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in | 3 +++ + 3 files changed, 8 insertions(+) + +diff --git a/deps/jemalloc/config.guess b/deps/jemalloc/config.guess +index 1f5c50c..e5a8c92 100755 +--- a/deps/jemalloc/config.guess ++++ b/deps/jemalloc/config.guess +@@ -1001,6 +1001,9 @@ EOF + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; ++ riscv32:Linux:*:* | riscv64:Linux:*:*) ++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC} ++ exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; +diff --git a/deps/jemalloc/config.sub b/deps/jemalloc/config.sub +index 0ccff77..76df7ee 100755 +--- a/deps/jemalloc/config.sub ++++ b/deps/jemalloc/config.sub +@@ -302,6 +302,7 @@ case $basic_machine in + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ ++ | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ +@@ -423,6 +424,7 @@ case $basic_machine in + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ ++ | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ +diff --git a/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in b/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in +index 8536a3e..cfbe169 100644 +--- a/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in ++++ b/deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in +@@ -256,6 +256,9 @@ typedef unsigned szind_t; + # ifdef __powerpc__ + # define LG_QUANTUM 4 + # endif ++# if defined(__riscv) || defined(__riscv__) ++# define LQ_QUANTUM 4 ++# endif + # ifdef __s390__ + # define LG_QUANTUM 4 + # endif +-- +1.8.3.1 + diff --git a/improved-HyperLogLog-cardinality-estimation.patch b/improved-HyperLogLog-cardinality-estimation.patch new file mode 100644 index 0000000..0a2256b --- /dev/null +++ b/improved-HyperLogLog-cardinality-estimation.patch @@ -0,0 +1,328 @@ +From 1e9a7748716e1cd234893dd858d07ffa77920e41 Mon Sep 17 00:00:00 2001 +From: Otmar Ertl <otmar.ertl@gmail.com> +Date: Sat, 10 Mar 2018 20:13:21 +0100 +Subject: [PATCH] improved HyperLogLog cardinality estimation + +based on method described in https://arxiv.org/abs/1702.01284 +that does not rely on any magic constants +--- + src/hyperloglog.c | 230 +++++++++++++++++++++++----------------------- + 1 file changed, 117 insertions(+), 113 deletions(-) + +diff --git a/src/hyperloglog.c b/src/hyperloglog.c +index 8ab9d2a30c0..7f5f62445c9 100644 +--- a/src/hyperloglog.c ++++ b/src/hyperloglog.c +@@ -192,6 +192,7 @@ struct hllhdr { + #define HLL_VALID_CACHE(hdr) (((hdr)->card[7] & (1<<7)) == 0) + + #define HLL_P 14 /* The greater is P, the smaller the error. */ ++#define HLL_Q (63-HLL_P) + #define HLL_REGISTERS (1<<HLL_P) /* With P=14, 16384 registers. */ + #define HLL_P_MASK (HLL_REGISTERS-1) /* Mask to index register. */ + #define HLL_BITS 6 /* Enough to count up to 63 leading zeroes. */ +@@ -510,13 +511,9 @@ int hllDenseAdd(uint8_t *registers, unsigned char *ele, size_t elesize) { + return hllDenseSet(registers,index,count); + } + +-/* Compute SUM(2^-reg) in the dense representation. +- * PE is an array with a pre-computer table of values 2^-reg indexed by reg. +- * As a side effect the integer pointed by 'ezp' is set to the number +- * of zero registers. */ +-double hllDenseSum(uint8_t *registers, double *PE, int *ezp) { +- double E = 0; +- int j, ez = 0; ++/* Compute the register histogram in the dense representation. */ ++void hllDenseRegHisto(uint8_t *registers, int* regHisto) { ++ int j; + + /* Redis default is to use 16384 registers 6 bits each. The code works + * with other values by modifying the defines, but for our target value +@@ -527,47 +524,49 @@ double hllDenseSum(uint8_t *registers, double *PE, int *ezp) { + r10, r11, r12, r13, r14, r15; + for (j = 0; j < 1024; j++) { + /* Handle 16 registers per iteration. */ +- r0 = r[0] & 63; if (r0 == 0) ez++; +- r1 = (r[0] >> 6 | r[1] << 2) & 63; if (r1 == 0) ez++; +- r2 = (r[1] >> 4 | r[2] << 4) & 63; if (r2 == 0) ez++; +- r3 = (r[2] >> 2) & 63; if (r3 == 0) ez++; +- r4 = r[3] & 63; if (r4 == 0) ez++; +- r5 = (r[3] >> 6 | r[4] << 2) & 63; if (r5 == 0) ez++; +- r6 = (r[4] >> 4 | r[5] << 4) & 63; if (r6 == 0) ez++; +- r7 = (r[5] >> 2) & 63; if (r7 == 0) ez++; +- r8 = r[6] & 63; if (r8 == 0) ez++; +- r9 = (r[6] >> 6 | r[7] << 2) & 63; if (r9 == 0) ez++; +- r10 = (r[7] >> 4 | r[8] << 4) & 63; if (r10 == 0) ez++; +- r11 = (r[8] >> 2) & 63; if (r11 == 0) ez++; +- r12 = r[9] & 63; if (r12 == 0) ez++; +- r13 = (r[9] >> 6 | r[10] << 2) & 63; if (r13 == 0) ez++; +- r14 = (r[10] >> 4 | r[11] << 4) & 63; if (r14 == 0) ez++; +- r15 = (r[11] >> 2) & 63; if (r15 == 0) ez++; +- +- /* Additional parens will allow the compiler to optimize the +- * code more with a loss of precision that is not very relevant +- * here (floating point math is not commutative!). */ +- E += (PE[r0] + PE[r1]) + (PE[r2] + PE[r3]) + (PE[r4] + PE[r5]) + +- (PE[r6] + PE[r7]) + (PE[r8] + PE[r9]) + (PE[r10] + PE[r11]) + +- (PE[r12] + PE[r13]) + (PE[r14] + PE[r15]); ++ r0 = r[0] & 63; ++ r1 = (r[0] >> 6 | r[1] << 2) & 63; ++ r2 = (r[1] >> 4 | r[2] << 4) & 63; ++ r3 = (r[2] >> 2) & 63; ++ r4 = r[3] & 63; ++ r5 = (r[3] >> 6 | r[4] << 2) & 63; ++ r6 = (r[4] >> 4 | r[5] << 4) & 63; ++ r7 = (r[5] >> 2) & 63; ++ r8 = r[6] & 63; ++ r9 = (r[6] >> 6 | r[7] << 2) & 63; ++ r10 = (r[7] >> 4 | r[8] << 4) & 63; ++ r11 = (r[8] >> 2) & 63; ++ r12 = r[9] & 63; ++ r13 = (r[9] >> 6 | r[10] << 2) & 63; ++ r14 = (r[10] >> 4 | r[11] << 4) & 63; ++ r15 = (r[11] >> 2) & 63; ++ ++ regHisto[r0] += 1; ++ regHisto[r1] += 1; ++ regHisto[r2] += 1; ++ regHisto[r3] += 1; ++ regHisto[r4] += 1; ++ regHisto[r5] += 1; ++ regHisto[r6] += 1; ++ regHisto[r7] += 1; ++ regHisto[r8] += 1; ++ regHisto[r9] += 1; ++ regHisto[r10] += 1; ++ regHisto[r11] += 1; ++ regHisto[r12] += 1; ++ regHisto[r13] += 1; ++ regHisto[r14] += 1; ++ regHisto[r15] += 1; ++ + r += 12; + } + } else { +- for (j = 0; j < HLL_REGISTERS; j++) { ++ for(j = 0; j < HLL_REGISTERS; j++) { + unsigned long reg; +- + HLL_DENSE_GET_REGISTER(reg,registers,j); +- if (reg == 0) { +- ez++; +- /* Increment E at the end of the loop. */ +- } else { +- E += PE[reg]; /* Precomputed 2^(-reg[j]). */ +- } ++ regHisto[reg] += 1; + } +- E += ez; /* Add 2^0 'ez' times. */ + } +- *ezp = ez; +- return E; + } + + /* ================== Sparse representation implementation ================= */ +@@ -903,76 +902,96 @@ int hllSparseAdd(robj *o, unsigned char *ele, size_t elesize) { + return hllSparseSet(o,index,count); + } + +-/* Compute SUM(2^-reg) in the sparse representation. +- * PE is an array with a pre-computer table of values 2^-reg indexed by reg. +- * As a side effect the integer pointed by 'ezp' is set to the number +- * of zero registers. */ +-double hllSparseSum(uint8_t *sparse, int sparselen, double *PE, int *ezp, int *invalid) { +- double E = 0; +- int ez = 0, idx = 0, runlen, regval; ++/* Compute the register histogram in the sparse representation. */ ++void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int* regHisto) { ++ int idx = 0, runlen, regval; + uint8_t *end = sparse+sparselen, *p = sparse; + + while(p < end) { + if (HLL_SPARSE_IS_ZERO(p)) { + runlen = HLL_SPARSE_ZERO_LEN(p); + idx += runlen; +- ez += runlen; +- /* Increment E at the end of the loop. */ ++ regHisto[0] += runlen; + p++; + } else if (HLL_SPARSE_IS_XZERO(p)) { + runlen = HLL_SPARSE_XZERO_LEN(p); + idx += runlen; +- ez += runlen; +- /* Increment E at the end of the loop. */ ++ regHisto[0] += runlen; + p += 2; + } else { + runlen = HLL_SPARSE_VAL_LEN(p); + regval = HLL_SPARSE_VAL_VALUE(p); + idx += runlen; +- E += PE[regval]*runlen; ++ regHisto[regval] += runlen; + p++; + } + } + if (idx != HLL_REGISTERS && invalid) *invalid = 1; +- E += ez; /* Add 2^0 'ez' times. */ +- *ezp = ez; +- return E; + } + + /* ========================= HyperLogLog Count ============================== + * This is the core of the algorithm where the approximated count is computed. +- * The function uses the lower level hllDenseSum() and hllSparseSum() functions +- * as helpers to compute the SUM(2^-reg) part of the computation, which is +- * representation-specific, while all the rest is common. */ +- +-/* Implements the SUM operation for uint8_t data type which is only used +- * internally as speedup for PFCOUNT with multiple keys. */ +-double hllRawSum(uint8_t *registers, double *PE, int *ezp) { +- double E = 0; +- int j, ez = 0; ++ * The function uses the lower level hllDenseRegHisto() and hllSparseRegHisto() ++ * functions as helpers to compute histogram of register values part of the ++ * computation, which is representation-specific, while all the rest is common. */ ++ ++/* Implements the register histogram calculation for uint8_t data type ++ * which is only used internally as speedup for PFCOUNT with multiple keys. */ ++void hllRawRegHisto(uint8_t *registers, int* regHisto) { + uint64_t *word = (uint64_t*) registers; + uint8_t *bytes; ++ int j; + + for (j = 0; j < HLL_REGISTERS/8; j++) { + if (*word == 0) { +- ez += 8; ++ regHisto[0] += 8; + } else { + bytes = (uint8_t*) word; +- if (bytes[0]) E += PE[bytes[0]]; else ez++; +- if (bytes[1]) E += PE[bytes[1]]; else ez++; +- if (bytes[2]) E += PE[bytes[2]]; else ez++; +- if (bytes[3]) E += PE[bytes[3]]; else ez++; +- if (bytes[4]) E += PE[bytes[4]]; else ez++; +- if (bytes[5]) E += PE[bytes[5]]; else ez++; +- if (bytes[6]) E += PE[bytes[6]]; else ez++; +- if (bytes[7]) E += PE[bytes[7]]; else ez++; ++ regHisto[bytes[0]] += 1; ++ regHisto[bytes[1]] += 1; ++ regHisto[bytes[2]] += 1; ++ regHisto[bytes[3]] += 1; ++ regHisto[bytes[4]] += 1; ++ regHisto[bytes[5]] += 1; ++ regHisto[bytes[6]] += 1; ++ regHisto[bytes[7]] += 1; + } + word++; + } +- E += ez; /* 2^(-reg[j]) is 1 when m is 0, add it 'ez' times for every +- zero register in the HLL. */ +- *ezp = ez; +- return E; ++} ++ ++/* Helper function sigma as defined in ++ * "New cardinality estimation algorithms for HyperLogLog sketches" ++ * Otmar Ertl, arXiv:1702.01284 */ ++double hllSigma(double x) { ++ if (x == 1.) return INFINITY; ++ double zPrime; ++ double y = 1; ++ double z = x; ++ do { ++ x *= x; ++ zPrime = z; ++ z += x * y; ++ y += y; ++ } while(zPrime != z); ++ return z; ++} ++ ++/* Helper function tau as defined in ++ * "New cardinality estimation algorithms for HyperLogLog sketches" ++ * Otmar Ertl, arXiv:1702.01284 */ ++double hllTau(double x) { ++ if (x == 0. || x == 1.) return 0.; ++ double zPrime; ++ double y = 1.0; ++ double z = 1 - x; ++ do { ++ x = sqrt(x); ++ zPrime = z; ++ y *= 0.5; ++ z -= pow(1 - x, 2)*y; ++ } while(zPrime != z); ++ return z / 3; + } + + /* Return the approximated cardinality of the set based on the harmonic +@@ -988,49 +1007,34 @@ double hllRawSum(uint8_t *registers, double *PE, int *ezp) { + * keys (no need to work with 6-bit integers encoding). */ + uint64_t hllCount(struct hllhdr *hdr, int *invalid) { + double m = HLL_REGISTERS; +- double E, alpha = 0.7213/(1+1.079/m); +- int j, ez; /* Number of registers equal to 0. */ +- +- /* We precompute 2^(-reg[j]) in a small table in order to +- * speedup the computation of SUM(2^-register[0..i]). */ +- static int initialized = 0; +- static double PE[64]; +- if (!initialized) { +- PE[0] = 1; /* 2^(-reg[j]) is 1 when m is 0. */ +- for (j = 1; j < 64; j++) { +- /* 2^(-reg[j]) is the same as 1/2^reg[j]. */ +- PE[j] = 1.0/(1ULL << j); +- } +- initialized = 1; +- } ++ double E; ++ int j; ++ double alphaInf = 0.5 / log(2.); ++ int regHisto[HLL_Q+2] = {0}; + +- /* Compute SUM(2^-register[0..i]). */ ++ /* Compute register histogram */ + if (hdr->encoding == HLL_DENSE) { +- E = hllDenseSum(hdr->registers,PE,&ez); ++ hllDenseRegHisto(hdr->registers,regHisto); + } else if (hdr->encoding == HLL_SPARSE) { +- E = hllSparseSum(hdr->registers, +- sdslen((sds)hdr)-HLL_HDR_SIZE,PE,&ez,invalid); ++ hllSparseRegHisto(hdr->registers, ++ sdslen((sds)hdr)-HLL_HDR_SIZE,invalid,regHisto); + } else if (hdr->encoding == HLL_RAW) { +- E = hllRawSum(hdr->registers,PE,&ez); ++ hllRawRegHisto(hdr->registers,regHisto); + } else { + serverPanic("Unknown HyperLogLog encoding in hllCount()"); + } + +- /* Apply loglog-beta to the raw estimate. See: +- * "LogLog-Beta and More: A New Algorithm for Cardinality Estimation +- * Based on LogLog Counting" Jason Qin, Denys Kim, Yumei Tung +- * arXiv:1612.02284 */ +- double zl = log(ez + 1); +- double beta = -0.370393911*ez + +- 0.070471823*zl + +- 0.17393686*pow(zl,2) + +- 0.16339839*pow(zl,3) + +- -0.09237745*pow(zl,4) + +- 0.03738027*pow(zl,5) + +- -0.005384159*pow(zl,6) + +- 0.00042419*pow(zl,7); +- +- E = llroundl(alpha*m*(m-ez)*(1/(E+beta))); ++ /* Estimate cardinality form register histogram. See: ++ * "New cardinality estimation algorithms for HyperLogLog sketches" ++ * Otmar Ertl, arXiv:1702.01284 */ ++ double z = m * hllTau((m-regHisto[HLL_Q+1])/(double)m); ++ for (j = HLL_Q; j >= 1; --j) { ++ z += regHisto[j]; ++ z *= 0.5; ++ } ++ z += m * hllSigma(regHisto[0]/(double)m); ++ E = llroundl(alphaInf*m*m/z); ++ + return (uint64_t) E; + } + diff --git a/modify-aarch64-architecture-jemalloc-page-size-from-4k-to-64k.patch b/modify-aarch64-architecture-jemalloc-page-size-from-4k-to-64k.patch new file mode 100644 index 0000000..bedaaca --- /dev/null +++ b/modify-aarch64-architecture-jemalloc-page-size-from-4k-to-64k.patch @@ -0,0 +1,13 @@ +diff --git a/deps/Makefile b/deps/Makefile +index e148a33..f1855f3 100644 +--- a/deps/Makefile ++++ b/deps/Makefile +@@ -77,7 +77,7 @@ JEMALLOC_LDFLAGS= $(LDFLAGS) + + jemalloc: .make-prerequisites + @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) +- cd jemalloc && ./configure --with-lg-quantum=3 --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)" ++ cd jemalloc && ./configure --with-lg-quantum=3 --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)" --with-lg-page=16 + cd jemalloc && $(MAKE) CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)" lib/libjemalloc.a + + .PHONY: jemalloc diff --git a/redis-sentinel.service b/redis-sentinel.service new file mode 100644 index 0000000..5e8ae1c --- /dev/null +++ b/redis-sentinel.service @@ -0,0 +1,14 @@ +[Unit] +Description=Redis Sentinel +After=network.target + +[Service] +ExecStart=/usr/bin/redis-sentinel /etc/redis-sentinel.conf --supervised systemd +Type=notify +User=redis +Group=redis +RuntimeDirectory=redis +RuntimeDirectoryMode=0755 + +[Install] +WantedBy=multi-user.target diff --git a/redis.logrotate b/redis.logrotate new file mode 100644 index 0000000..3a3d185 --- /dev/null +++ b/redis.logrotate @@ -0,0 +1,9 @@ +/var/log/redis/*.log { + weekly + rotate 10 + copytruncate + delaycompress + compress + notifempty + missingok +} diff --git a/redis.service b/redis.service new file mode 100644 index 0000000..e4eff49 --- /dev/null +++ b/redis.service @@ -0,0 +1,15 @@ +[Unit] +Description=Redis persistent key-value database +After=network.target + +[Service] +ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd +Type=notify +User=redis +Group=redis +RuntimeDirectory=redis +RuntimeDirectoryMode=0755 + +[Install] +WantedBy=multi-user.target + diff --git a/redis.spec b/redis.spec new file mode 100644 index 0000000..fef75c5 --- /dev/null +++ b/redis.spec @@ -0,0 +1,181 @@ +Name: redis +Version: 4.0.14 +Release: 5 +Summary: A persistent key-value database +License: BSD-3-Clause and MIT +URL: https://redis.io +Source0: http://download.redis.io/releases/%{name}-%{version}.tar.gz +Source1: %{name}.logrotate +Source2: %{name}-sentinel.service +Source3: %{name}.service + +Patch0001: CVE-2020-14147.patch +Patch0002: improved-HyperLogLog-cardinality-estimation.patch +Patch0003: Aesthetic-changes-to-PR.patch +Patch0004: CVE-2019-10193.patch +Patch0005: modify-aarch64-architecture-jemalloc-page-size-from-4k-to-64k.patch +Patch0006: huawei-deps-jemalloc-support-riscv.patch +Patch0007: CVE-2021-21309.patch +Patch0008: CVE-2021-3470.patch +Patch0009: CVE-2021-29478.patch +Patch0010: CVE-2021-32672.patch +Patch0011: CVE-2022-36021.patch +Patch0012: CVE-2023-28856.patch + +BuildRequires: systemd gcc +Requires: /bin/awk +Requires: logrotate +Requires(pre): shadow-utils +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd + +%description +Redis is an advanced key-value store. It is often referred to as a dattructure server since keys can contain strings, hashes +,lists, sets anorted sets. + +%prep +%setup +%patch0001 -p1 +%patch0002 -p1 +%patch0003 -p1 +%patch0004 -p1 +%ifarch aarch64 +%patch0005 -p1 +%endif +%patch0006 -p1 +%patch0007 -p1 +%patch0008 -p1 +%patch0009 -p1 +%patch0010 -p1 +%patch0011 -p1 +%patch0012 -p1 +%ifarch loongarch64 +%_update_config_guess +%_update_config_sub +%endif + +sed -i -e 's|^logfile .*$|logfile /var/log/redis/redis.log|g' redis.conf +sed -i -e '$ alogfile /var/log/redis/sentinel.log' sentinel.conf +sed -i -e 's|^dir .*$|dir /var/lib/redis|g' redis.conf + +%build +make + +%install +%make_install PREFIX=%{buildroot}%{_prefix} +install -d %{buildroot}%{_sharedstatedir}/%{name} +install -d %{buildroot}%{_localstatedir}/log/%{name} +install -d %{buildroot}%{_localstatedir}/run/%{name} +install -d %{buildroot}%{_libdir}/%{name}/modules +install -pDm644 %{SOURCE1} %{buildroot}%{_sysconfdir}/logrotate.d/%{name} +mkdir -p %{buildroot}%{_unitdir} +install -pm644 %{SOURCE2} %{buildroot}%{_unitdir} +install -pm644 %{SOURCE3} %{buildroot}%{_unitdir} +install -pDm640 %{name}.conf %{buildroot}%{_sysconfdir}/%{name}.conf +install -pDm640 sentinel.conf %{buildroot}%{_sysconfdir}/%{name}-sentinel.conf + +%pre +getent group %{name} &> /dev/null || \ +groupadd -r %{name} &> /dev/null +getent passwd %{name} &> /dev/null || \ +useradd -r -g %{name} -d %{_sharedstatedir}/%{name} -s /sbin/nologin \ +-c 'Redis Database Server' %{name} &> /dev/null +exit 0 + +%post +%systemd_post %{name}.service +%systemd_post %{name}-sentinel.service + +%preun +%systemd_preun %{name}.service +%systemd_preun %{name}-sentinel.service + +%postun +%systemd_postun_with_restart %{name}.service +%systemd_postun_with_restart %{name}-sentinel.service + + +%files +%license COPYING +%doc BUGS README.md 00-RELEASENOTES MANIFESTO CONTRIBUTING +%config(noreplace) %{_sysconfdir}/logrotate.d/%{name} +%attr(0640, redis, root) %config(noreplace) %{_sysconfdir}/%{name}.conf +%attr(0640, redis, root) %config(noreplace) %{_sysconfdir}/%{name}-sentinel.conf +%dir %attr(0750, redis, redis) %{_libdir}/%{name} +%dir %attr(0750, redis, redis) %{_libdir}/%{name}/modules +%dir %attr(0750, redis, redis) %{_sharedstatedir}/%{name} +%dir %attr(0750, redis, redis) %{_localstatedir}/log/%{name} +%{_bindir}/%{name}-* +%{_unitdir}/%{name}.service +%{_unitdir}/%{name}-sentinel.service + +%changelog +* Mon May 15 2023 yaoxin <yao_xin001@hoperun.com> - 4.0.14-5 +- Fix CVE-2023-28856 + +* Mon Mar 27 2023 wushaozheng<wushaozheng@ncti-gba.cn> - 4.0.14-4 +- Fix CVE-2022-36021 + +* Tue Nov 15 2022 huajingyun<huajingyun@loongson.cn> - 4.0.14-3 +- Update config.guess and config.sub for loongarch + +* Tue May 10 2022 chenchen <chen_aka_jan@163.com> - 4.0.14-2 +- License compliance rectification + +* Wed Dec 29 2021 zhangjiapeng <zhangjiapeng9@huawei.com> - 4.0.14-1 +- Update to 4.0.14 + +* Sat Oct 09 2021 yaoxin <yaoxin30@huawei.com> - 4.0.11-18 +- Fix CVE-2021-32672 + +* Tue Jun 08 2021 wangyue <wangyue92@huawei.com> - 4.0.11-17 +- Fix CVE-2021-29478 + +* Mon May 31 2021 huanghaitao <huanghaitao8@huawei.com> - 4.0.11-16 +- Completing build dependencies to fix gcc compiler missing error + +* Wed Apr 07 2021 wangyue <wangyue92@huawei.com> - 4.0.11-15 +- Fix CVE-2021-3470 + +* Wed Mar 24 2021 sunguoshuai <sunguoshuai@huawei.com> - 4.0.11-14 +- change patch file in order src.rpm is same in aarch64 and x86_64 + +* Thu Mar 11 2021 wangxiao <wangxiao65@huawei.com> - 4.0.11-13 +- Fix CVE-2021-21309 + +* Wed Nov 11 2020 yangyanchao <yangyanchao6@huawei.com> - 4.0.11-12 +- enable dependency package jemalloc of redis to support riscv + +* Wed Sep 30 2020 Jiapeng Zhang <zhangjiapeng9@huawei.com> - 4.0.11-11 +- Modify aarch64 architecture jemalloc page size from 4k to 64k + +* Mon Sep 21 2020 wangyue <wangyue92@huawei.com> - 4.0.11-10 +- fix CVE-2019-10193 + +* Mon Jul 20 2020 wangxiao <wangxiao654@huawei.com> - 4.0.11-9 +- fix CVE-2020-14147 + +* Fri Jun 19 2020 Captain Wei <captain.a.wei@gmail.com> - 4.0.11-8 +- Add some dependency package in building and running phase + +* Fri Jun 12 2020 panchenbo <panchenbo@uniontech.com> - 4.0.11-7 +- Type:bugfix +- ID: NA +- SUG: restart +- DESC: Resolve service startup failure whthout no %pre + +* Mon Jun 01 2020 huanghaitao <huanghaitao8@huawei.com> - 4.0.11-6 +- Resolve service startup failure + +* Tue Mar 17 2020 wangye <wangye54@huawei.com> - 4.0.11-5 +- CVE name fix + +* Tue Mar 17 2020 wangye <wangye54@huawei.com> - 4.0.11-4 +- CVE fix + +* Wed Jan 15 2020 zhujunhao <zhujunhao5@huawei.com> - 4.0.11-3 +- Modify redis service + +* Wed Jan 08 2020 lijin Yang <yanglijin@openeuler.org> - 4.0.11-2 +- Package init @@ -0,0 +1 @@ +96ae20ffd68b9daee24b702b754d89f3 redis-4.0.14.tar.gz |