CVE-2021-32626
This commit is contained in:
parent
feb36f797a
commit
da3e083ac8
140
CVE-2021-32626.patch
Normal file
140
CVE-2021-32626.patch
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
From 666ed7facf4524bf6d19b11b20faa2cf93fdf591 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "meir@redislabs.com" <meir@redislabs.com>
|
||||||
|
Date: Sun, 13 Jun 2021 14:27:18 +0300
|
||||||
|
Subject: [PATCH] Fix invalid memory write on lua stack overflow
|
||||||
|
{CVE-2021-32626}
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
When LUA call our C code, by default, the LUA stack has room for 20
|
||||||
|
elements. In most cases, this is more than enough but sometimes it's not
|
||||||
|
and the caller must verify the LUA stack size before he pushes elements.
|
||||||
|
|
||||||
|
On 3 places in the code, there was no verification of the LUA stack size.
|
||||||
|
On specific inputs this missing verification could have lead to invalid
|
||||||
|
memory write:
|
||||||
|
1. On 'luaReplyToRedisReply', one might return a nested reply that will
|
||||||
|
explode the LUA stack.
|
||||||
|
2. On 'redisProtocolToLuaType', the Redis reply might be deep enough
|
||||||
|
to explode the LUA stack (notice that currently there is no such
|
||||||
|
command in Redis that returns such a nested reply, but modules might
|
||||||
|
do it)
|
||||||
|
3. On 'ldbRedis', one might give a command with enough arguments to
|
||||||
|
explode the LUA stack (all the arguments will be pushed to the LUA
|
||||||
|
stack)
|
||||||
|
|
||||||
|
This commit is solving all those 3 issues by calling 'lua_checkstack' and
|
||||||
|
verify that there is enough room in the LUA stack to push elements. In
|
||||||
|
case 'lua_checkstack' returns an error (there is not enough room in the
|
||||||
|
LUA stack and it's not possible to increase the stack), we will do the
|
||||||
|
following:
|
||||||
|
1. On 'luaReplyToRedisReply', we will return an error to the user.
|
||||||
|
2. On 'redisProtocolToLuaType' we will exit with panic (we assume this
|
||||||
|
scenario is rare because it can only happen with a module).
|
||||||
|
3. On 'ldbRedis', we return an error.
|
||||||
|
---
|
||||||
|
src/scripting.c | 41 +++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 41 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/scripting.c b/src/scripting.c
|
||||||
|
index dea5f516561e..afa6adb0c47e 100644
|
||||||
|
--- a/src/scripting.c
|
||||||
|
+++ b/src/scripting.c
|
||||||
|
@@ -128,6 +128,16 @@ void sha1hex(char *digest, char *script, size_t len) {
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *redisProtocolToLuaType(lua_State *lua, char* reply) {
|
||||||
|
+
|
||||||
|
+ if (!lua_checkstack(lua, 5)) {
|
||||||
|
+ /*
|
||||||
|
+ * Increase the Lua stack if needed, to make sure there is enough room
|
||||||
|
+ * to push 5 elements to the stack. On failure, exit with panic.
|
||||||
|
+ * Notice that we need, in the worst case, 5 elements because redisProtocolToLuaType_Aggregate
|
||||||
|
+ * might push 5 elements to the Lua stack.*/
|
||||||
|
+ serverPanic("lua stack limit reach when parsing redis.call reply");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
char *p = reply;
|
||||||
|
|
||||||
|
switch(*p) {
|
||||||
|
@@ -220,6 +230,11 @@ char *redisProtocolToLuaType_Aggregate(lua_State *lua, char *reply, int atype) {
|
||||||
|
if (atype == '%') {
|
||||||
|
p = redisProtocolToLuaType(lua,p);
|
||||||
|
} else {
|
||||||
|
+ if (!lua_checkstack(lua, 1)) {
|
||||||
|
+ /* Notice that here we need to check the stack again because the recursive
|
||||||
|
+ * call to redisProtocolToLuaType might have use the room allocated in the stack */
|
||||||
|
+ serverPanic("lua stack limit reach when parsing redis.call reply");
|
||||||
|
+ }
|
||||||
|
lua_pushboolean(lua,1);
|
||||||
|
}
|
||||||
|
lua_settable(lua,-3);
|
||||||
|
@@ -339,6 +354,17 @@ void luaSortArray(lua_State *lua) {
|
||||||
|
/* Reply to client 'c' converting the top element in the Lua stack to a
|
||||||
|
* Redis reply. As a side effect the element is consumed from the stack. */
|
||||||
|
void luaReplyToRedisReply(client *c, lua_State *lua) {
|
||||||
|
+
|
||||||
|
+ if (!lua_checkstack(lua, 4)) {
|
||||||
|
+ /* Increase the Lua stack if needed to make sure there is enough room
|
||||||
|
+ * to push 4 elements to the stack. On failure, return error.
|
||||||
|
+ * Notice that we need, in the worst case, 4 elements because returning a map might
|
||||||
|
+ * require push 4 elements to the Lua stack.*/
|
||||||
|
+ addReplyErrorFormat(c, "reached lua stack limit");
|
||||||
|
+ lua_pop(lua,1); // pop the element from the stack
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
int t = lua_type(lua,-1);
|
||||||
|
|
||||||
|
switch(t) {
|
||||||
|
@@ -362,6 +388,7 @@ void luaReplyToRedisReply(client *c, lua_State *lua) {
|
||||||
|
* field. */
|
||||||
|
|
||||||
|
/* Handle error reply. */
|
||||||
|
+ // we took care of the stack size on function start
|
||||||
|
lua_pushstring(lua,"err");
|
||||||
|
lua_gettable(lua,-2);
|
||||||
|
t = lua_type(lua,-1);
|
||||||
|
@@ -407,6 +434,7 @@ void luaReplyToRedisReply(client *c, lua_State *lua) {
|
||||||
|
if (t == LUA_TTABLE) {
|
||||||
|
int maplen = 0;
|
||||||
|
void *replylen = addReplyDeferredLen(c);
|
||||||
|
+ /* we took care of the stack size on function start */
|
||||||
|
lua_pushnil(lua); /* Use nil to start iteration. */
|
||||||
|
while (lua_next(lua,-2)) {
|
||||||
|
/* Stack now: table, key, value */
|
||||||
|
@@ -429,6 +457,7 @@ void luaReplyToRedisReply(client *c, lua_State *lua) {
|
||||||
|
if (t == LUA_TTABLE) {
|
||||||
|
int setlen = 0;
|
||||||
|
void *replylen = addReplyDeferredLen(c);
|
||||||
|
+ /* we took care of the stack size on function start */
|
||||||
|
lua_pushnil(lua); /* Use nil to start iteration. */
|
||||||
|
while (lua_next(lua,-2)) {
|
||||||
|
/* Stack now: table, key, true */
|
||||||
|
@@ -448,6 +477,7 @@ void luaReplyToRedisReply(client *c, lua_State *lua) {
|
||||||
|
void *replylen = addReplyDeferredLen(c);
|
||||||
|
int j = 1, mbulklen = 0;
|
||||||
|
while(1) {
|
||||||
|
+ /* we took care of the stack size on function start */
|
||||||
|
lua_pushnumber(lua,j++);
|
||||||
|
lua_gettable(lua,-2);
|
||||||
|
t = lua_type(lua,-1);
|
||||||
|
@@ -2506,6 +2536,17 @@ void ldbEval(lua_State *lua, sds *argv, int argc) {
|
||||||
|
void ldbRedis(lua_State *lua, sds *argv, int argc) {
|
||||||
|
int j, saved_rc = server.lua_replicate_commands;
|
||||||
|
|
||||||
|
+ if (!lua_checkstack(lua, argc + 1)) {
|
||||||
|
+ /* Increase the Lua stack if needed to make sure there is enough room
|
||||||
|
+ * to push 'argc + 1' elements to the stack. On failure, return error.
|
||||||
|
+ * Notice that we need, in worst case, 'argc + 1' elements because we push all the arguments
|
||||||
|
+ * given by the user (without the first argument) and we also push the 'redis' global table and
|
||||||
|
+ * 'redis.call' function so:
|
||||||
|
+ * (1 (redis table)) + (1 (redis.call function)) + (argc - 1 (all arguments without the first)) = argc + 1*/
|
||||||
|
+ ldbLogRedisReply("max lua stack reached");
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
lua_getglobal(lua,"redis");
|
||||||
|
lua_pushstring(lua,"call");
|
||||||
|
lua_gettable(lua,-2); /* Stack: redis, redis.call */
|
||||||
@ -6,7 +6,7 @@
|
|||||||
%global Pname redis
|
%global Pname redis
|
||||||
Name: redis6
|
Name: redis6
|
||||||
Version: 6.0.11
|
Version: 6.0.11
|
||||||
Release: 3
|
Release: 4
|
||||||
Summary: A persistent key-value database
|
Summary: A persistent key-value database
|
||||||
License: BSD and MIT
|
License: BSD and MIT
|
||||||
URL: https://redis.io
|
URL: https://redis.io
|
||||||
@ -21,6 +21,7 @@ Source10: https://github.com/%{Pname}/%{Pname}-doc/archive/%{doc_comm
|
|||||||
|
|
||||||
Patch0001: Modify-aarch64-architecture-jemalloc-page-size-from-from-4k-to-64k.patch
|
Patch0001: Modify-aarch64-architecture-jemalloc-page-size-from-from-4k-to-64k.patch
|
||||||
|
|
||||||
|
Patch0002: CVE-2021-32626.patch
|
||||||
BuildRequires: make gcc
|
BuildRequires: make gcc
|
||||||
%if %{with tests}
|
%if %{with tests}
|
||||||
BuildRequires: procps-ng tcl
|
BuildRequires: procps-ng tcl
|
||||||
@ -79,6 +80,7 @@ tar -xvf %{SOURCE10}
|
|||||||
%setup -n %{Pname}-%{version}
|
%setup -n %{Pname}-%{version}
|
||||||
%ifarch aarch64
|
%ifarch aarch64
|
||||||
%patch0001 -p1
|
%patch0001 -p1
|
||||||
|
%patch0002 -p1
|
||||||
%endif
|
%endif
|
||||||
mv ../%{Pname}-doc-%{doc_commit} doc
|
mv ../%{Pname}-doc-%{doc_commit} doc
|
||||||
mv deps/lua/COPYRIGHT COPYRIGHT-lua
|
mv deps/lua/COPYRIGHT COPYRIGHT-lua
|
||||||
@ -208,6 +210,9 @@ fi
|
|||||||
%{_docdir}/%{Pname}
|
%{_docdir}/%{Pname}
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Nov 04 2021 liwu <liwu13@huawei.com> - 6.0.11-4
|
||||||
|
- Fix CVE-2021-32626
|
||||||
|
|
||||||
* Thu Sep 02 2021 lingsheng <lingsheng@huawei.com> - 6.0.11-3
|
* Thu Sep 02 2021 lingsheng <lingsheng@huawei.com> - 6.0.11-3
|
||||||
- Fix missing patch in source package
|
- Fix missing patch in source package
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user