fix CVE-2021-32672
(cherry picked from commit 57dc370e6c0c2caf63dae9281e3b8e8179c0c0d7)
This commit is contained in:
parent
ef45aaf84f
commit
744dc928fa
132
CVE-2021-32672.patch
Normal file
132
CVE-2021-32672.patch
Normal file
@ -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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
Name: redis
|
||||
Version: 4.0.11
|
||||
Release: 17
|
||||
Release: 18
|
||||
Summary: A persistent key-value database
|
||||
License: BSD and MIT
|
||||
URL: https://redis.io
|
||||
@ -22,6 +22,7 @@ Patch0008: huawei-deps-jemalloc-support-riscv.patch
|
||||
Patch0009: CVE-2021-21309.patch
|
||||
Patch0010: CVE-2021-3470.patch
|
||||
Patch0011: CVE-2021-29478.patch
|
||||
Patch0012: CVE-2021-32672.patch
|
||||
|
||||
BuildRequires: systemd gcc
|
||||
Requires: /bin/awk
|
||||
@ -50,6 +51,7 @@ Redis is an advanced key-value store. It is often referred to as a dattructure s
|
||||
%patch0009 -p1
|
||||
%patch0010 -p1
|
||||
%patch0011 -p1
|
||||
%patch0012 -p1
|
||||
|
||||
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
|
||||
@ -107,6 +109,9 @@ exit 0
|
||||
%{_unitdir}/%{name}-sentinel.service
|
||||
|
||||
%changelog
|
||||
* 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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user