From 4fbab5740bfef66918d6c2950dd2b3b4e07815a2 Mon Sep 17 00:00:00 2001 From: Madelyn Olson Date: Wed, 2 Oct 2024 14:09:21 -0700 Subject: [PATCH] Apply security fixes for CVEs (#1114) Apply the security fixes for the release. (CVE-2024-31449) Lua library commands may lead to stack overflow and potential RCE. (CVE-2024-31227) Potential Denial-of-service due to malformed ACL selectors. (CVE-2024-31228) Potential Denial-of-service due to unbounded pattern matching. --------- Signed-off-by: Madelyn Olson --- 00-RELEASENOTES | 7 +++++++ deps/lua/src/lua_bit.c | 1 + src/acl.c | 2 +- src/util.c | 11 ++++++++--- tests/unit/acl-v2.tcl | 5 +++++ tests/unit/keyspace.tcl | 6 ++++++ tests/unit/scripting.tcl | 6 ++++++ 7 files changed, 34 insertions(+), 4 deletions(-) diff --git a/00-RELEASENOTES b/00-RELEASENOTES index e71d67f50..decbd8ffe 100644 --- a/00-RELEASENOTES +++ b/00-RELEASENOTES @@ -26,6 +26,13 @@ Bug fixes * Fix a build issue on systems where `` is unavailable. (#1053) * Fix an issue with the default `sentinel.conf` being invalid. (#1040) +Security fixes +============== + +* (CVE-2024-31449) Lua library commands may lead to stack overflow and potential RCE. +* (CVE-2024-31227) Potential Denial-of-service due to malformed ACL selectors. +* (CVE-2024-31228) Potential Denial-of-service due to unbounded pattern matching. + ================================================================================ Valkey 8.0.0 GA - Released Sun 15 Sep 2024 ================================================================================ diff --git a/deps/lua/src/lua_bit.c b/deps/lua/src/lua_bit.c index 9f83b8594..7e43faea4 100644 --- a/deps/lua/src/lua_bit.c +++ b/deps/lua/src/lua_bit.c @@ -132,6 +132,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/src/acl.c b/src/acl.c index 87d91014c..d073c0812 100644 --- a/src/acl.c +++ b/src/acl.c @@ -1079,7 +1079,7 @@ int ACLSetSelector(aclSelector *selector, const char *op, size_t oplen) { flags |= ACL_READ_PERMISSION; } else if (toupper(op[offset]) == 'W' && !(flags & ACL_WRITE_PERMISSION)) { flags |= ACL_WRITE_PERMISSION; - } else if (op[offset] == '~') { + } else if (op[offset] == '~' && flags) { offset++; break; } else { diff --git a/src/util.c b/src/util.c index 66f62c900..b1235c282 100644 --- a/src/util.c +++ b/src/util.c @@ -59,7 +59,11 @@ static int stringmatchlen_impl(const char *pattern, const char *string, int stringLen, int nocase, - int *skipLongerMatches) { + int *skipLongerMatches, + int nesting) { + /* Protection against abusive patterns. */ + if (nesting > 1000) return 0; + while (patternLen && stringLen) { switch (pattern[0]) { case '*': @@ -69,7 +73,8 @@ static int stringmatchlen_impl(const char *pattern, } if (patternLen == 1) return 1; /* match */ while (stringLen) { - if (stringmatchlen_impl(pattern + 1, patternLen - 1, string, stringLen, nocase, skipLongerMatches)) + if (stringmatchlen_impl(pattern + 1, patternLen - 1, string, stringLen, nocase, skipLongerMatches, + nesting + 1)) return 1; /* match */ if (*skipLongerMatches) return 0; /* no match */ string++; @@ -179,7 +184,7 @@ static int stringmatchlen_impl(const char *pattern, 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/acl-v2.tcl b/tests/unit/acl-v2.tcl index 9827c0ba0..a509bc0ff 100644 --- a/tests/unit/acl-v2.tcl +++ b/tests/unit/acl-v2.tcl @@ -116,6 +116,11 @@ start_server {tags {"acl external:skip"}} { assert_match "*NOPERM*key*" $err } + test {Validate read and write permissions format} { + catch {r ACL SETUSER key-permission-RW %~} err + set err + } {ERR Error in ACL SETUSER modifier '%~': Syntax error} + test {Test separate read and write permissions on different selectors are not additive} { r ACL SETUSER key-permission-RW-selector on nopass "(%R~read* +@all)" "(%W~write* +@all)" $r2 auth key-permission-RW-selector password diff --git a/tests/unit/keyspace.tcl b/tests/unit/keyspace.tcl index c8bdcac98..ba55c1b8e 100644 --- a/tests/unit/keyspace.tcl +++ b/tests/unit/keyspace.tcl @@ -547,4 +547,10 @@ foreach {type large} [array get largevalue] { assert_no_match "*db2:keys=*" [r info keyspace] r flushall } {OK} {singledb:skip} + + test {Regression for pattern matching very long nested loops} { + r flushdb + r SET [string repeat "a" 50000] 1 + r KEYS [string repeat "*?" 50000] + } {} } diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl index 1a73b9d1a..db3712910 100644 --- a/tests/unit/scripting.tcl +++ b/tests/unit/scripting.tcl @@ -733,6 +733,12 @@ start_server {tags {"scripting"}} { set e } {ERR *Attempt to modify a readonly table*} + 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