Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
93a804d368
!114 [sync] PR-112: Fix CVE-2023-45145,CVE-2024-31228 and CVE-2024-31449
From: @openeuler-sync-bot 
Reviewed-by: @wang--ge 
Signed-off-by: @wang--ge
2024-10-16 02:12:11 +00:00
starlet-dx
49e43f38a6 Fix CVE-2023-45145,CVE-2024-31228 and CVE-2024-31449
(cherry picked from commit d1707e8164155222cb5e4b464497ebf32fa62df0)
2024-10-16 09:09:27 +08:00
openeuler-ci-bot
719b085193
!91 Fix CVE-2022-24834
From: @wk333 
Reviewed-by: @wang--ge 
Signed-off-by: @wang--ge
2023-07-31 03:18:46 +00:00
wk333
84228635a1 Fix CVE-2022-24834 2023-07-31 10:08:10 +08:00
openeuler-ci-bot
3e2b194ae9
!89 Fix CVE-2023-28856
From: @starlet-dx 
Reviewed-by: @wang--ge 
Signed-off-by: @wang--ge
2023-05-15 06:12:29 +00:00
starlet-dx
35d3ef1619 Fix CVE-2023-28856 2023-05-15 11:33:46 +08:00
openeuler-ci-bot
4a9d4a360e
!75 FIX CVE-2022-36021
From: @wszlight 
Reviewed-by: @wang--ge 
Signed-off-by: @wang--ge
2023-03-28 03:45:26 +00:00
wszlight
dcfdee2c5e fix CVE-2022-36021 2023-03-28 01:48:43 +00:00
openeuler-ci-bot
c76afd8f00
!73 Update config.guess and config.sub for loongarch.
From: @huajingyun 
Reviewed-by: @gitee-cmd 
Signed-off-by: @gitee-cmd
2022-11-22 11:56:35 +00:00
Jingyun Hua
63c68949d4 Update config.guess and config.sub for loongarch
Signed-off-by: Jingyun Hua <huajingyun@loongson.cn>
2022-11-15 11:30:38 +00:00
7 changed files with 1034 additions and 1 deletions

689
CVE-2022-24834.patch Normal file
View File

@ -0,0 +1,689 @@
From 4fe8a0af3f479a4a5b17885334cb67a3887ae96e Mon Sep 17 00:00:00 2001
From: Oran Agra <oran@redislabs.com>
Date: Sun, 2 Jul 2023 14:56:10 +0300
Subject: [PATCH] Lua cjson and cmsgpack integer overflow issues
(CVE-2022-24834)
* Fix integer overflows due to using wrong integer size.
* Add assertions / panic when overflow still happens.
* Deletion of dead code to avoid need to maintain it
* Some changes are not because of bugs, but rather paranoia.
* Improve cmsgpack and cjson test coverage.
Co-authored-by: Yossi Gottlieb <yossigo@gmail.com>
Origin: https://github.com/redis/redis/commit/4fe8a0af3f479a4a5b17885334cb67a3887ae96e
---
deps/Makefile | 7 ++
deps/lua/src/lua_cjson.c | 9 ++-
deps/lua/src/lua_cmsgpack.c | 31 +++++----
deps/lua/src/strbuf.c | 109 ++++++++------------------------
deps/lua/src/strbuf.h | 46 ++++++--------
tests/unit/scripting.tcl | 123 ++++++++++++++++++++++++++++++++++++
6 files changed, 200 insertions(+), 125 deletions(-)
diff --git a/deps/Makefile b/deps/Makefile
index 700867f3b61c..dea4cd656c6f 100644
--- a/deps/Makefile
+++ b/deps/Makefile
@@ -2,6 +2,8 @@
uname_S:= $(shell sh -c 'uname -s 2>/dev/null || echo not')
+LUA_COVERAGE?=no
+
CCCOLOR="\033[34m"
LINKCOLOR="\033[34;1m"
SRCCOLOR="\033[33m"
@@ -64,6 +66,11 @@ endif
LUA_CFLAGS+= -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL -DREDIS_STATIC='' $(CFLAGS)
LUA_LDFLAGS+= $(LDFLAGS)
+ifeq ($(LUA_COVERAGE),yes)
+ LUA_CFLAGS += -fprofile-arcs -ftest-coverage
+ LUA_LDFLAGS += -fprofile-arcs -ftest-coverage
+endif
+
# lua's Makefile defines AR="ar rcu", which is unusual, and makes it more
# challenging to cross-compile lua (and redis). These defines make it easier
# to fit redis into cross-compilation environments, which typically set AR.
diff --git a/deps/lua/src/lua_cjson.c b/deps/lua/src/lua_cjson.c
index c26c0d7b8ea4..991f5d31ddb3 100644
--- a/deps/lua/src/lua_cjson.c
+++ b/deps/lua/src/lua_cjson.c
@@ -39,6 +39,7 @@
#include <assert.h>
#include <string.h>
#include <math.h>
+#include <stdint.h>
#include <limits.h>
#include "lua.h"
#include "lauxlib.h"
@@ -141,13 +142,13 @@ typedef struct {
typedef struct {
json_token_type_t type;
- int index;
+ size_t index;
union {
const char *string;
double number;
int boolean;
} value;
- int string_len;
+ size_t string_len;
} json_token_t;
static const char *char2escape[256] = {
@@ -473,6 +474,8 @@ static void json_append_string(lua_State *l, strbuf_t *json, int lindex)
* This buffer is reused constantly for small strings
* If there are any excess pages, they won't be hit anyway.
* This gains ~5% speedup. */
+ if (len > SIZE_MAX / 6 - 3)
+ abort(); /* Overflow check */
strbuf_ensure_empty_length(json, len * 6 + 2);
strbuf_append_char_unsafe(json, '\"');
@@ -706,7 +709,7 @@ static int json_encode(lua_State *l)
strbuf_t local_encode_buf;
strbuf_t *encode_buf;
char *json;
- int len;
+ size_t len;
luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
diff --git a/deps/lua/src/lua_cmsgpack.c b/deps/lua/src/lua_cmsgpack.c
index 892154793991..49879455a4a9 100644
--- a/deps/lua/src/lua_cmsgpack.c
+++ b/deps/lua/src/lua_cmsgpack.c
@@ -117,7 +117,9 @@ mp_buf *mp_buf_new(lua_State *L) {
void mp_buf_append(lua_State *L, mp_buf *buf, const unsigned char *s, size_t len) {
if (buf->free < len) {
- size_t newsize = (buf->len+len)*2;
+ size_t newsize = buf->len+len;
+ if (newsize < buf->len || newsize >= SIZE_MAX/2) abort();
+ newsize *= 2;
buf->b = (unsigned char*)mp_realloc(L, buf->b, buf->len + buf->free, newsize);
buf->free = newsize - buf->len;
@@ -173,7 +175,7 @@ void mp_cur_init(mp_cur *cursor, const unsigned char *s, size_t len) {
void mp_encode_bytes(lua_State *L, mp_buf *buf, const unsigned char *s, size_t len) {
unsigned char hdr[5];
- int hdrlen;
+ size_t hdrlen;
if (len < 32) {
hdr[0] = 0xa0 | (len&0xff); /* fix raw */
@@ -220,7 +222,7 @@ void mp_encode_double(lua_State *L, mp_buf *buf, double d) {
void mp_encode_int(lua_State *L, mp_buf *buf, int64_t n) {
unsigned char b[9];
- int enclen;
+ size_t enclen;
if (n >= 0) {
if (n <= 127) {
@@ -290,9 +292,9 @@ void mp_encode_int(lua_State *L, mp_buf *buf, int64_t n) {
mp_buf_append(L,buf,b,enclen);
}
-void mp_encode_array(lua_State *L, mp_buf *buf, int64_t n) {
+void mp_encode_array(lua_State *L, mp_buf *buf, uint64_t n) {
unsigned char b[5];
- int enclen;
+ size_t enclen;
if (n <= 15) {
b[0] = 0x90 | (n & 0xf); /* fix array */
@@ -313,7 +315,7 @@ void mp_encode_array(lua_State *L, mp_buf *buf, int64_t n) {
mp_buf_append(L,buf,b,enclen);
}
-void mp_encode_map(lua_State *L, mp_buf *buf, int64_t n) {
+void mp_encode_map(lua_State *L, mp_buf *buf, uint64_t n) {
unsigned char b[5];
int enclen;
@@ -790,7 +792,7 @@ void mp_decode_to_lua_type(lua_State *L, mp_cur *c) {
}
}
-int mp_unpack_full(lua_State *L, int limit, int offset) {
+int mp_unpack_full(lua_State *L, lua_Integer limit, lua_Integer offset) {
size_t len;
const char *s;
mp_cur c;
@@ -802,10 +804,10 @@ int mp_unpack_full(lua_State *L, int limit, int offset) {
if (offset < 0 || limit < 0) /* requesting negative off or lim is invalid */
return luaL_error(L,
"Invalid request to unpack with offset of %d and limit of %d.",
- offset, len);
+ (int) offset, (int) len);
else if (offset > len)
return luaL_error(L,
- "Start offset %d greater than input length %d.", offset, len);
+ "Start offset %d greater than input length %d.", (int) offset, (int) len);
if (decode_all) limit = INT_MAX;
@@ -827,12 +829,13 @@ int mp_unpack_full(lua_State *L, int limit, int offset) {
/* c->left is the remaining size of the input buffer.
* subtract the entire buffer size from the unprocessed size
* to get our next start offset */
- int offset = len - c.left;
+ size_t new_offset = len - c.left;
+ if (new_offset > LONG_MAX) abort();
luaL_checkstack(L, 1, "in function mp_unpack_full");
/* Return offset -1 when we have have processed the entire buffer. */
- lua_pushinteger(L, c.left == 0 ? -1 : offset);
+ lua_pushinteger(L, c.left == 0 ? -1 : (lua_Integer) new_offset);
/* Results are returned with the arg elements still
* in place. Lua takes care of only returning
* elements above the args for us.
@@ -851,15 +854,15 @@ int mp_unpack(lua_State *L) {
}
int mp_unpack_one(lua_State *L) {
- int offset = luaL_optinteger(L, 2, 0);
+ lua_Integer offset = luaL_optinteger(L, 2, 0);
/* Variable pop because offset may not exist */
lua_pop(L, lua_gettop(L)-1);
return mp_unpack_full(L, 1, offset);
}
int mp_unpack_limit(lua_State *L) {
- int limit = luaL_checkinteger(L, 2);
- int offset = luaL_optinteger(L, 3, 0);
+ lua_Integer limit = luaL_checkinteger(L, 2);
+ lua_Integer offset = luaL_optinteger(L, 3, 0);
/* Variable pop because offset may not exist */
lua_pop(L, lua_gettop(L)-1);
diff --git a/deps/lua/src/strbuf.c b/deps/lua/src/strbuf.c
index f0f7f4b9a366..775e8baf1be9 100644
--- a/deps/lua/src/strbuf.c
+++ b/deps/lua/src/strbuf.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
+#include <stdint.h>
#include "strbuf.h"
@@ -38,22 +39,22 @@ static void die(const char *fmt, ...)
va_end(arg);
fprintf(stderr, "\n");
- exit(-1);
+ abort();
}
-void strbuf_init(strbuf_t *s, int len)
+void strbuf_init(strbuf_t *s, size_t len)
{
- int size;
+ size_t size;
- if (len <= 0)
+ if (!len)
size = STRBUF_DEFAULT_SIZE;
else
- size = len + 1; /* \0 terminator */
-
+ size = len + 1;
+ if (size < len)
+ die("Overflow, len: %zu", len);
s->buf = NULL;
s->size = size;
s->length = 0;
- s->increment = STRBUF_DEFAULT_INCREMENT;
s->dynamic = 0;
s->reallocs = 0;
s->debug = 0;
@@ -65,7 +66,7 @@ void strbuf_init(strbuf_t *s, int len)
strbuf_ensure_null(s);
}
-strbuf_t *strbuf_new(int len)
+strbuf_t *strbuf_new(size_t len)
{
strbuf_t *s;
@@ -81,20 +82,10 @@ strbuf_t *strbuf_new(int len)
return s;
}
-void strbuf_set_increment(strbuf_t *s, int increment)
-{
- /* Increment > 0: Linear buffer growth rate
- * Increment < -1: Exponential buffer growth rate */
- if (increment == 0 || increment == -1)
- die("BUG: Invalid string increment");
-
- s->increment = increment;
-}
-
static inline void debug_stats(strbuf_t *s)
{
if (s->debug) {
- fprintf(stderr, "strbuf(%lx) reallocs: %d, length: %d, size: %d\n",
+ fprintf(stderr, "strbuf(%lx) reallocs: %d, length: %zd, size: %zd\n",
(long)s, s->reallocs, s->length, s->size);
}
}
@@ -113,7 +104,7 @@ void strbuf_free(strbuf_t *s)
free(s);
}
-char *strbuf_free_to_string(strbuf_t *s, int *len)
+char *strbuf_free_to_string(strbuf_t *s, size_t *len)
{
char *buf;
@@ -131,57 +122,62 @@ char *strbuf_free_to_string(strbuf_t *s, int *len)
return buf;
}
-static int calculate_new_size(strbuf_t *s, int len)
+static size_t calculate_new_size(strbuf_t *s, size_t len)
{
- int reqsize, newsize;
+ size_t reqsize, newsize;
if (len <= 0)
die("BUG: Invalid strbuf length requested");
/* Ensure there is room for optional NULL termination */
reqsize = len + 1;
+ if (reqsize < len)
+ die("Overflow, len: %zu", len);
/* If the user has requested to shrink the buffer, do it exactly */
if (s->size > reqsize)
return reqsize;
newsize = s->size;
- if (s->increment < 0) {
+ if (reqsize >= SIZE_MAX / 2) {
+ newsize = reqsize;
+ } else {
/* Exponential sizing */
while (newsize < reqsize)
- newsize *= -s->increment;
- } else {
- /* Linear sizing */
- newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;
+ newsize *= 2;
}
+ if (newsize < reqsize)
+ die("BUG: strbuf length would overflow, len: %zu", len);
+
return newsize;
}
/* Ensure strbuf can handle a string length bytes long (ignoring NULL
* optional termination). */
-void strbuf_resize(strbuf_t *s, int len)
+void strbuf_resize(strbuf_t *s, size_t len)
{
- int newsize;
+ size_t newsize;
newsize = calculate_new_size(s, len);
if (s->debug > 1) {
- fprintf(stderr, "strbuf(%lx) resize: %d => %d\n",
+ fprintf(stderr, "strbuf(%lx) resize: %zd => %zd\n",
(long)s, s->size, newsize);
}
s->size = newsize;
s->buf = realloc(s->buf, s->size);
if (!s->buf)
- die("Out of memory");
+ die("Out of memory, len: %zu", len);
s->reallocs++;
}
void strbuf_append_string(strbuf_t *s, const char *str)
{
- int space, i;
+ int i;
+ size_t space;
space = strbuf_empty_length(s);
@@ -197,55 +193,6 @@ void strbuf_append_string(strbuf_t *s, const char *str)
}
}
-/* strbuf_append_fmt() should only be used when an upper bound
- * is known for the output string. */
-void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)
-{
- va_list arg;
- int fmt_len;
-
- strbuf_ensure_empty_length(s, len);
-
- va_start(arg, fmt);
- fmt_len = vsnprintf(s->buf + s->length, len, fmt, arg);
- va_end(arg);
-
- if (fmt_len < 0)
- die("BUG: Unable to convert number"); /* This should never happen.. */
-
- s->length += fmt_len;
-}
-
-/* strbuf_append_fmt_retry() can be used when the there is no known
- * upper bound for the output string. */
-void strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)
-{
- va_list arg;
- int fmt_len, try;
- int empty_len;
-
- /* If the first attempt to append fails, resize the buffer appropriately
- * and try again */
- for (try = 0; ; try++) {
- va_start(arg, fmt);
- /* Append the new formatted string */
- /* fmt_len is the length of the string required, excluding the
- * trailing NULL */
- empty_len = strbuf_empty_length(s);
- /* Add 1 since there is also space to store the terminating NULL. */
- fmt_len = vsnprintf(s->buf + s->length, empty_len + 1, fmt, arg);
- va_end(arg);
-
- if (fmt_len <= empty_len)
- break; /* SUCCESS */
- if (try > 0)
- die("BUG: length of formatted string changed");
-
- strbuf_resize(s, s->length + fmt_len);
- }
-
- s->length += fmt_len;
-}
/* vi:ai et sw=4 ts=4:
*/
diff --git a/deps/lua/src/strbuf.h b/deps/lua/src/strbuf.h
index d861108c14cd..c10f83f0db89 100644
--- a/deps/lua/src/strbuf.h
+++ b/deps/lua/src/strbuf.h
@@ -27,15 +27,13 @@
/* Size: Total bytes allocated to *buf
* Length: String length, excluding optional NULL terminator.
- * Increment: Allocation increments when resizing the string buffer.
* Dynamic: True if created via strbuf_new()
*/
typedef struct {
char *buf;
- int size;
- int length;
- int increment;
+ size_t size;
+ size_t length;
int dynamic;
int reallocs;
int debug;
@@ -44,32 +42,26 @@ typedef struct {
#ifndef STRBUF_DEFAULT_SIZE
#define STRBUF_DEFAULT_SIZE 1023
#endif
-#ifndef STRBUF_DEFAULT_INCREMENT
-#define STRBUF_DEFAULT_INCREMENT -2
-#endif
/* Initialise */
-extern strbuf_t *strbuf_new(int len);
-extern void strbuf_init(strbuf_t *s, int len);
-extern void strbuf_set_increment(strbuf_t *s, int increment);
+extern strbuf_t *strbuf_new(size_t len);
+extern void strbuf_init(strbuf_t *s, size_t len);
/* Release */
extern void strbuf_free(strbuf_t *s);
-extern char *strbuf_free_to_string(strbuf_t *s, int *len);
+extern char *strbuf_free_to_string(strbuf_t *s, size_t *len);
/* Management */
-extern void strbuf_resize(strbuf_t *s, int len);
-static int strbuf_empty_length(strbuf_t *s);
-static int strbuf_length(strbuf_t *s);
-static char *strbuf_string(strbuf_t *s, int *len);
-static void strbuf_ensure_empty_length(strbuf_t *s, int len);
+extern void strbuf_resize(strbuf_t *s, size_t len);
+static size_t strbuf_empty_length(strbuf_t *s);
+static size_t strbuf_length(strbuf_t *s);
+static char *strbuf_string(strbuf_t *s, size_t *len);
+static void strbuf_ensure_empty_length(strbuf_t *s, size_t len);
static char *strbuf_empty_ptr(strbuf_t *s);
-static void strbuf_extend_length(strbuf_t *s, int len);
+static void strbuf_extend_length(strbuf_t *s, size_t len);
/* Update */
-extern void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...);
-extern void strbuf_append_fmt_retry(strbuf_t *s, const char *format, ...);
-static void strbuf_append_mem(strbuf_t *s, const char *c, int len);
+static void strbuf_append_mem(strbuf_t *s, const char *c, size_t len);
extern void strbuf_append_string(strbuf_t *s, const char *str);
static void strbuf_append_char(strbuf_t *s, const char c);
static void strbuf_ensure_null(strbuf_t *s);
@@ -87,12 +79,12 @@ static inline int strbuf_allocated(strbuf_t *s)
/* Return bytes remaining in the string buffer
* Ensure there is space for a NULL terminator. */
-static inline int strbuf_empty_length(strbuf_t *s)
+static inline size_t strbuf_empty_length(strbuf_t *s)
{
return s->size - s->length - 1;
}
-static inline void strbuf_ensure_empty_length(strbuf_t *s, int len)
+static inline void strbuf_ensure_empty_length(strbuf_t *s, size_t len)
{
if (len > strbuf_empty_length(s))
strbuf_resize(s, s->length + len);
@@ -103,12 +95,12 @@ static inline char *strbuf_empty_ptr(strbuf_t *s)
return s->buf + s->length;
}
-static inline void strbuf_extend_length(strbuf_t *s, int len)
+static inline void strbuf_extend_length(strbuf_t *s, size_t len)
{
s->length += len;
}
-static inline int strbuf_length(strbuf_t *s)
+static inline size_t strbuf_length(strbuf_t *s)
{
return s->length;
}
@@ -124,14 +116,14 @@ static inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)
s->buf[s->length++] = c;
}
-static inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)
+static inline void strbuf_append_mem(strbuf_t *s, const char *c, size_t len)
{
strbuf_ensure_empty_length(s, len);
memcpy(s->buf + s->length, c, len);
s->length += len;
}
-static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)
+static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, size_t len)
{
memcpy(s->buf + s->length, c, len);
s->length += len;
@@ -142,7 +134,7 @@ static inline void strbuf_ensure_null(strbuf_t *s)
s->buf[s->length] = 0;
}
-static inline char *strbuf_string(strbuf_t *s, int *len)
+static inline char *strbuf_string(strbuf_t *s, size_t *len)
{
if (len)
*len = s->length;
diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl
index 8314f0268f41..552ed757a711 100644
--- a/tests/unit/scripting.tcl
+++ b/tests/unit/scripting.tcl
@@ -215,6 +215,66 @@ start_server {tags {"scripting"}} {
} 0
} {a b}
+ test {EVAL - JSON smoke test} {
+ r eval {
+ local some_map = {
+ s1="Some string",
+ n1=100,
+ a1={"Some","String","Array"},
+ nil1=nil,
+ b1=true,
+ b2=false}
+ local encoded = cjson.encode(some_map)
+ local decoded = cjson.decode(encoded)
+ assert(table.concat(some_map) == table.concat(decoded))
+
+ cjson.encode_keep_buffer(false)
+ encoded = cjson.encode(some_map)
+ decoded = cjson.decode(encoded)
+ assert(table.concat(some_map) == table.concat(decoded))
+
+ -- Table with numeric keys
+ local table1 = {one="one", [1]="one"}
+ encoded = cjson.encode(table1)
+ decoded = cjson.decode(encoded)
+ assert(decoded["one"] == table1["one"])
+ assert(decoded["1"] == table1[1])
+
+ -- Array
+ local array1 = {[1]="one", [2]="two"}
+ encoded = cjson.encode(array1)
+ decoded = cjson.decode(encoded)
+ assert(table.concat(array1) == table.concat(decoded))
+
+ -- Invalid keys
+ local invalid_map = {}
+ invalid_map[false] = "false"
+ local ok, encoded = pcall(cjson.encode, invalid_map)
+ assert(ok == false)
+
+ -- Max depth
+ cjson.encode_max_depth(1)
+ ok, encoded = pcall(cjson.encode, some_map)
+ assert(ok == false)
+
+ cjson.decode_max_depth(1)
+ ok, decoded = pcall(cjson.decode, '{"obj": {"array": [1,2,3,4]}}')
+ assert(ok == false)
+
+ -- Invalid numbers
+ ok, encoded = pcall(cjson.encode, {num1=0/0})
+ assert(ok == false)
+ cjson.encode_invalid_numbers(true)
+ ok, encoded = pcall(cjson.encode, {num1=0/0})
+ assert(ok == true)
+
+ -- Restore defaults
+ cjson.decode_max_depth(1000)
+ cjson.encode_max_depth(1000)
+ cjson.encode_invalid_numbers(false)
+ } 0
+ }
+
test {EVAL - cmsgpack can pack double?} {
r eval {local encoded = cmsgpack.pack(0.1)
local h = ""
@@ -235,6 +295,68 @@ start_server {tags {"scripting"}} {
} 0
} {d3ffffff0000000000}
+ test {EVAL - cmsgpack pack/unpack smoke test} {
+ r eval {
+ local str_lt_32 = string.rep("x", 30)
+ local str_lt_255 = string.rep("x", 250)
+ local str_lt_65535 = string.rep("x", 65530)
+ local str_long = string.rep("x", 100000)
+ local array_lt_15 = {1, 2, 3, 4, 5}
+ local array_lt_65535 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}
+ local array_big = {}
+ for i=1, 100000 do
+ array_big[i] = i
+ end
+ local map_lt_15 = {a=1, b=2}
+ local map_big = {}
+ for i=1, 100000 do
+ map_big[tostring(i)] = i
+ end
+ local some_map = {
+ s1=str_lt_32,
+ s2=str_lt_255,
+ s3=str_lt_65535,
+ s4=str_long,
+ d1=0.1,
+ i1=1,
+ i2=250,
+ i3=65530,
+ i4=100000,
+ i5=2^40,
+ i6=-1,
+ i7=-120,
+ i8=-32000,
+ i9=-100000,
+ i10=-3147483648,
+ a1=array_lt_15,
+ a2=array_lt_65535,
+ a3=array_big,
+ m1=map_lt_15,
+ m2=map_big,
+ b1=false,
+ b2=true,
+ n=nil
+ }
+ local encoded = cmsgpack.pack(some_map)
+ local decoded = cmsgpack.unpack(encoded)
+ assert(table.concat(some_map) == table.concat(decoded))
+ local offset, decoded_one = cmsgpack.unpack_one(encoded, 0)
+ assert(table.concat(some_map) == table.concat(decoded_one))
+ assert(offset == -1)
+
+ local encoded_multiple = cmsgpack.pack(str_lt_32, str_lt_255, str_lt_65535, str_long)
+ local offset, obj = cmsgpack.unpack_limit(encoded_multiple, 1, 0)
+ assert(obj == str_lt_32)
+ offset, obj = cmsgpack.unpack_limit(encoded_multiple, 1, offset)
+ assert(obj == str_lt_255)
+ offset, obj = cmsgpack.unpack_limit(encoded_multiple, 1, offset)
+ assert(obj == str_lt_65535)
+ offset, obj = cmsgpack.unpack_limit(encoded_multiple, 1, offset)
+ assert(obj == str_long)
+ assert(offset == -1)
+ } 0
+ }
+
test {EVAL - cmsgpack can pack and unpack circular references?} {
r eval {local a = {x=nil,y=5}
local b = {x=a}
@@ -396,6 +518,7 @@ start_server {tags {"scripting"}} {
}
test {EVAL does not leak in the Lua stack} {
+ r script flush ;# reset Lua VM
r set x 0
# Use a non blocking client to speedup the loop.
set rd [redis_deferring_client]

92
CVE-2022-36021.patch Normal file
View File

@ -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"
+ } {}
}

49
CVE-2023-28856.patch Normal file
View File

@ -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]
+ }
}

66
CVE-2023-45145.patch Normal file
View File

@ -0,0 +1,66 @@
From 7f486ea6eebf0afce74f2e59763b9b82b78629dc Mon Sep 17 00:00:00 2001
From: Yossi Gottlieb <yossigo@gmail.com>
Date: Wed, 11 Oct 2023 22:45:34 +0300
Subject: [PATCH] Fix issue of listen before chmod on Unix sockets
(CVE-2023-45145)
Before this commit, Unix socket setup performed chmod(2) on the socket
file after calling listen(2). Depending on what umask is used, this
could leave the file with the wrong permissions for a short period of
time. As a result, another process could exploit this race condition and
establish a connection that would otherwise not be possible.
We now make sure the socket permissions are set up prior to calling
listen(2).
(cherry picked from commit a11b3bc34a054818f2ac70e50adfc542ca1cba42)
---
src/anet.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/anet.c b/src/anet.c
index dc88eb7..d0db80f 100644
--- a/src/anet.c
+++ b/src/anet.c
@@ -437,13 +437,16 @@ int anetWrite(int fd, char *buf, int count)
return totlen;
}
-static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len, int backlog) {
+static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len, int backlog, mode_t perm) {
if (bind(s,sa,len) == -1) {
anetSetError(err, "bind: %s", strerror(errno));
close(s);
return ANET_ERR;
}
+ if (sa->sa_family == AF_LOCAL && perm)
+ chmod(((struct sockaddr_un *) sa)->sun_path, perm);
+
if (listen(s, backlog) == -1) {
anetSetError(err, "listen: %s", strerror(errno));
close(s);
@@ -484,7 +487,7 @@ static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backl
if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error;
if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;
- if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) s = ANET_ERR;
+ if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog,0) == ANET_ERR) s = ANET_ERR;
goto end;
}
if (p == NULL) {
@@ -521,10 +524,8 @@ int anetUnixServer(char *err, char *path, mode_t perm, int backlog)
memset(&sa,0,sizeof(sa));
sa.sun_family = AF_LOCAL;
strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
- if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa),backlog) == ANET_ERR)
+ if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa),backlog,perm) == ANET_ERR)
return ANET_ERR;
- if (perm)
- chmod(sa.sun_path, perm);
return s;
}
--
2.33.0

63
CVE-2024-31228.patch Normal file
View File

@ -0,0 +1,63 @@
From c8649f8e852d1dc388b5446e003bb0eefa33d61f Mon Sep 17 00:00:00 2001
From: Oran Agra <oran@redislabs.com>
Date: Wed, 2 Oct 2024 20:11:01 +0300
Subject: [PATCH] Prevent pattern matching abuse (CVE-2024-31228)
---
src/util.c | 9 ++++++---
tests/unit/keyspace.tcl | 6 ++++++
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/util.c b/src/util.c
index 861ef67..0f5e8e1 100644
--- a/src/util.c
+++ b/src/util.c
@@ -45,8 +45,11 @@
/* Glob-style pattern matching. */
static int stringmatchlen_impl(const char *pattern, int patternLen,
- const char *string, int stringLen, int nocase, int *skipLongerMatches)
+ const char *string, int stringLen, int nocase, int *skipLongerMatches, int nesting)
{
+ /* Protection against abusive patterns. */
+ if (nesting > 1000) return 0;
+
while(patternLen && stringLen) {
switch(pattern[0]) {
case '*':
@@ -58,7 +61,7 @@ static int stringmatchlen_impl(const char *pattern, int patternLen,
return 1; /* match */
while(stringLen) {
if (stringmatchlen_impl(pattern+1, patternLen-1,
- string, stringLen, nocase, skipLongerMatches))
+ string, stringLen, nocase, skipLongerMatches, nesting+1))
return 1; /* match */
if (*skipLongerMatches)
return 0; /* no match */
@@ -181,7 +184,7 @@ static int stringmatchlen_impl(const char *pattern, int patternLen,
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);
+ return stringmatchlen_impl(pattern,patternLen,string,stringLen,nocase,&skipLongerMatches,0);
}
int stringmatch(const char *pattern, const char *string, int nocase) {
diff --git a/tests/unit/keyspace.tcl b/tests/unit/keyspace.tcl
index 1617ac5..2217b29 100644
--- a/tests/unit/keyspace.tcl
+++ b/tests/unit/keyspace.tcl
@@ -278,4 +278,10 @@ start_server {tags {"keyspace"}} {
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"
} {}
+
+ test {Regression for pattern matching very long nested loops} {
+ r flushdb
+ r SET [string repeat "a" 50000] 1
+ r KEYS [string repeat "*?" 50000]
+ } {}
}
--
2.33.0

43
CVE-2024-31449.patch Normal file
View File

@ -0,0 +1,43 @@
From fe8de4313f85e0f8af2eff1f78b52cfe56fb4c71 Mon Sep 17 00:00:00 2001
From: Oran Agra <oran@redislabs.com>
Date: Wed, 2 Oct 2024 19:54:06 +0300
Subject: [PATCH] Fix lua bit.tohex (CVE-2024-31449)
INT_MIN value must be explicitly checked, and cannot be negated.
---
deps/lua/src/lua_bit.c | 1 +
tests/unit/scripting.tcl | 6 ++++++
2 files changed, 7 insertions(+)
diff --git a/deps/lua/src/lua_bit.c b/deps/lua/src/lua_bit.c
index 690df7d..a459ca9 100644
--- a/deps/lua/src/lua_bit.c
+++ b/deps/lua/src/lua_bit.c
@@ -131,6 +131,7 @@ static int bit_tohex(lua_State *L)
const char *hexdigits = "0123456789abcdef";
char buf[8];
int i;
+ if (n == INT32_MIN) n = INT32_MIN+1;
if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }
if (n > 8) n = 8;
for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; }
diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl
index d747fa6..a7e1e9e 100644
--- a/tests/unit/scripting.tcl
+++ b/tests/unit/scripting.tcl
@@ -459,6 +459,12 @@ start_server {tags {"scripting"}} {
set e
} {*ERR*attempted to create global*}
+ test {lua bit.tohex bug} {
+ set res [run_script {return bit.tohex(65535, -2147483648)} 0]
+ r ping
+ set res
+ } {0000FFFF}
+
test {Test an example script DECR_IF_GT} {
set decr_if_gt {
local current
--
2.33.0

View File

@ -1,6 +1,6 @@
Name: redis
Version: 4.0.14
Release: 2
Release: 7
Summary: A persistent key-value database
License: BSD-3-Clause and MIT
URL: https://redis.io
@ -19,6 +19,12 @@ 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
Patch0013: CVE-2022-24834.patch
Patch0014: CVE-2023-45145.patch
Patch0015: CVE-2024-31228.patch
Patch0016: CVE-2024-31449.patch
BuildRequires: systemd gcc
Requires: /bin/awk
@ -46,6 +52,16 @@ Redis is an advanced key-value store. It is often referred to as a dattructure s
%patch0008 -p1
%patch0009 -p1
%patch0010 -p1
%patch0011 -p1
%patch0012 -p1
%patch0013 -p1
%patch0014 -p1
%patch0015 -p1
%patch0016 -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
@ -103,6 +119,21 @@ exit 0
%{_unitdir}/%{name}-sentinel.service
%changelog
* Wed Oct 09 2024 yaoxin <yao_xin001@hoperun.com> - 4.0.14-7
- Fix CVE-2023-45145,CVE-2024-31228 and CVE-2024-31449
* Mon Jul 31 2023 wangkai <13474090681@163.com> - 4.0.14-6
- Fix CVE-2022-24834
* 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