redict/deps
antirez 52a00201fc Security: fix Lua cmsgpack library stack overflow.
During an auditing effort, the Apple Vulnerability Research team discovered
a critical Redis security issue affecting the Lua scripting part of Redis.

-- Description of the problem

Several years ago I merged a pull request including many small changes at
the Lua MsgPack library (that originally I authored myself). The Pull
Request entered Redis in commit 90b6337c1, in 2014.
Unfortunately one of the changes included a variadic Lua function that
lacked the check for the available Lua C stack. As a result, calling the
"pack" MsgPack library function with a large number of arguments, results
into pushing into the Lua C stack a number of new values proportional to
the number of arguments the function was called with. The pushed values,
moreover, are controlled by untrusted user input.

This in turn causes stack smashing which we believe to be exploitable,
while not very deterministic, but it is likely that an exploit could be
created targeting specific versions of Redis executables. However at its
minimum the issue results in a DoS, crashing the Redis server.

-- Versions affected

Versions greater or equal to Redis 2.8.18 are affected.

-- Reproducing

Reproduce with this (based on the original reproduction script by
Apple security team):

https://gist.github.com/antirez/82445fcbea6d9b19f97014cc6cc79f8a

-- Verification of the fix

The fix was tested in the following way:

1) I checked that the problem is no longer observable running the trigger.
2) The Lua code was analyzed to understand the stack semantics, and that
actually enough stack is allocated in all the cases of mp_pack() calls.
3) The mp_pack() function was modified in order to show exactly what items
in the stack were being set, to make sure that there is no silent overflow
even after the fix.

-- Credits

Thank you to the Apple team and to the other persons that helped me
checking the patch and coordinating this communication.
2018-06-13 12:40:33 +02:00
..
hiredis Backport hiredis issue 525 fix to compile on FreeBSD. 2018-05-25 16:33:23 +02:00
jemalloc Generate configure for Jemalloc. 2018-05-24 18:21:13 +02:00
linenoise Update linenoise to fix insecure redis-cli history file creation. 2016-07-29 11:28:16 +02:00
lua Security: fix Lua cmsgpack library stack overflow. 2018-06-13 12:40:33 +02:00
Makefile Add --with-version in Jemalloc config script. 2018-05-24 17:50:12 +02:00
README.md Specify that Jemalloc configure requires version. 2018-05-24 17:49:36 +02:00
update-jemalloc.sh Jemalloc update script added. 2014-06-20 14:53:57 +02:00

This directory contains all Redis dependencies, except for the libc that should be provided by the operating system.

  • Jemalloc is our memory allocator, used as replacement for libc malloc on Linux by default. It has good performances and excellent fragmentation behavior. This component is upgraded from time to time.
  • geohash-int is inside the dependencies directory but is actually part of the Redis project, since it is our private fork (heavily modified) of a library initially developed for Ardb, which is in turn a fork of Redis.
  • hiredis is the official C client library for Redis. It is used by redis-cli, redis-benchmark and Redis Sentinel. It is part of the Redis official ecosystem but is developed externally from the Redis repository, so we just upgrade it as needed.
  • linenoise is a readline replacement. It is developed by the same authors of Redis but is managed as a separated project and updated as needed.
  • lua is Lua 5.1 with minor changes for security and additional libraries.

How to upgrade the above dependencies

Jemalloc

Jemalloc is modified with changes that allow us to implement the Redis active defragmentation logic. However this feature of Redis is not mandatory and Redis is able to understand if the Jemalloc version it is compiled against supports such Redis-specific modifications. So in theory, if you are not interested in the active defragmentation, you can replace Jemalloc just following tose steps:

  1. Remove the jemalloc directory.
  2. Substitute it with the new jemalloc source tree.
  3. Edit the Makefile localted in the same directoy as the README you are reading, and change the --with-version in the Jemalloc configure script options with the version you are using. This is required because otherwise Jemalloc configuration script is broken and will not work nested in another git repository.

However note that we change Jemalloc settings via the configure script of Jemalloc using the --with-lg-quantum option, setting it to the value of 3 instead of 4. This provides us with more size classes that better suit the Redis data structures, in order to gain memory efficiency.

If you want to upgrade Jemalloc while also providing support for active defragmentation, in addition to the above steps you need to perform the following additional steps:

  1. In Jemalloc three, file include/jemalloc/jemalloc_macros.h.in, make sure to add #define JEMALLOC_FRAG_HINT.
  2. Implement the function je_get_defrag_hint() inside src/jemalloc.c. You can see how it is implemented in the current Jemalloc source tree shipped with Redis, and rewrite it according to the new Jemalloc internals, if they changed, otherwise you could just copy the old implementation if you are upgrading just to a similar version of Jemalloc.

Geohash

This is never upgraded since it's part of the Redis project. If there are changes to merge from Ardb there is the need to manually check differences, but at this point the source code is pretty different.

Hiredis

Hiredis uses the SDS string library, that must be the same version used inside Redis itself. Hiredis is also very critical for Sentinel. Historically Redis often used forked versions of hiredis in a way or the other. In order to upgrade it is adviced to take a lot of care:

  1. Check with diff if hiredis API changed and what impact it could have in Redis.
  2. Make sure thet the SDS library inside Hiredis and inside Redis are compatible.
  3. After the upgrade, run the Redis Sentinel test.
  4. Check manually that redis-cli and redis-benchmark behave as expecteed, since we have no tests for CLI utilities currently.

Linenoise

Linenoise is rarely upgraded as needed. The upgrade process is trivial since Redis uses a non modified version of linenoise, so to upgrade just do the following:

  1. Remove the linenoise directory.
  2. Substitute it with the new linenoise source tree.

Lua

We use Lua 5.1 and no upgrade is planned currently, since we don't want to break Lua scripts for new Lua features: in the context of Redis Lua scripts the capabilities of 5.1 are usually more than enough, the release is rock solid, and we definitely don't want to break old scripts.

So upgrading of Lua is up to the Redis project maintainers and should be a manual procedure performed by taking a diff between the different versions.

Currently we have at least the following differences between official Lua 5.1 and our version:

  1. Makefile is modified to allow a different compiler than GCC.
  2. We have the implementation source code, and directly link to the following external libraries: lua_cjson.o, lua_struct.o, lua_cmsgpack.o and lua_bit.o.
  3. There is a security fix in ldo.c, line 498: The check for LUA_SIGNATURE[0] is removed in order toa void direct bytecode exectuion.