summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVijay Anusuri <vanusuri@mvista.com>2025-10-16 15:40:18 +0530
committerGyorgy Sarvari <skandigraun@gmail.com>2025-10-17 10:51:27 +0200
commitabe7f83cc6316818b31d44022ad50fa94117300f (patch)
tree815588022c3a010efe4d79363497b905493dc01b
parent4450ab743041b883388fdf37b574e609143040f2 (diff)
downloadmeta-openembedded-abe7f83cc6316818b31d44022ad50fa94117300f.tar.gz
redis: Fix CVE-2025-46818
Upstream-Status: Backport from https://github.com/redis/redis/commit/dccb672d838f05c940f040c27b74fde6fb47b2a7 Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
-rw-r--r--meta-oe/recipes-extended/redis/redis-7.0.13/CVE-2025-46818.patch283
-rw-r--r--meta-oe/recipes-extended/redis/redis_7.0.13.bb1
2 files changed, 284 insertions, 0 deletions
diff --git a/meta-oe/recipes-extended/redis/redis-7.0.13/CVE-2025-46818.patch b/meta-oe/recipes-extended/redis/redis-7.0.13/CVE-2025-46818.patch
new file mode 100644
index 0000000000..0f7fc15cfc
--- /dev/null
+++ b/meta-oe/recipes-extended/redis/redis-7.0.13/CVE-2025-46818.patch
@@ -0,0 +1,283 @@
1From dccb672d838f05c940f040c27b74fde6fb47b2a7 Mon Sep 17 00:00:00 2001
2From: Ozan Tezcan <ozantezcan@gmail.com>
3Date: Mon, 23 Jun 2025 12:10:12 +0300
4Subject: [PATCH] Lua script can be executed in the context of another user
5 (CVE-2025-46818)
6
7Upstream-Status: Backport [https://github.com/redis/redis/commit/dccb672d838f05c940f040c27b74fde6fb47b2a7]
8CVE: CVE-2025-46818
9Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
10---
11 src/config.c | 1 +
12 src/eval.c | 2 ++
13 src/function_lua.c | 2 ++
14 src/script_lua.c | 59 +++++++++++++++++++++++++++++----
15 src/script_lua.h | 1 +
16 src/server.h | 1 +
17 tests/unit/scripting.tcl | 70 ++++++++++++++++++++++++++++++++++++++++
18 7 files changed, 129 insertions(+), 7 deletions(-)
19
20diff --git a/src/config.c b/src/config.c
21index bfb49ef..d232eaf 100644
22--- a/src/config.c
23+++ b/src/config.c
24@@ -3011,6 +3011,7 @@ standardConfig static_configs[] = {
25 createBoolConfig("latency-tracking", NULL, MODIFIABLE_CONFIG, server.latency_tracking_enabled, 1, NULL, NULL),
26 createBoolConfig("aof-disable-auto-gc", NULL, MODIFIABLE_CONFIG, server.aof_disable_auto_gc, 0, NULL, updateAofAutoGCEnabled),
27 createBoolConfig("replica-ignore-disk-write-errors", NULL, MODIFIABLE_CONFIG, server.repl_ignore_disk_write_error, 0, NULL, NULL),
28+ createBoolConfig("lua-enable-deprecated-api", NULL, IMMUTABLE_CONFIG | HIDDEN_CONFIG, server.lua_enable_deprecated_api, 0, NULL, NULL),
29
30 /* String Configs */
31 createStringConfig("aclfile", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, server.acl_filename, "", NULL, NULL),
32diff --git a/src/eval.c b/src/eval.c
33index a562335..f39ccc9 100644
34--- a/src/eval.c
35+++ b/src/eval.c
36@@ -261,6 +261,8 @@ void scriptingInit(int setup) {
37 /* Recursively lock all tables that can be reached from the global table */
38 luaSetTableProtectionRecursively(lua);
39 lua_pop(lua, 1);
40+ /* Set metatables of basic types (string, number, nil etc.) readonly. */
41+ luaSetTableProtectionForBasicTypes(lua);
42
43 lctx.lua = lua;
44 }
45diff --git a/src/function_lua.c b/src/function_lua.c
46index aedadb0..9450437 100644
47--- a/src/function_lua.c
48+++ b/src/function_lua.c
49@@ -490,6 +490,8 @@ int luaEngineInitEngine() {
50 lua_enablereadonlytable(lua_engine_ctx->lua, -1, 1); /* protect the new global table */
51 lua_replace(lua_engine_ctx->lua, LUA_GLOBALSINDEX); /* set new global table as the new globals */
52
53+ /* Set metatables of basic types (string, number, nil etc.) readonly. */
54+ luaSetTableProtectionForBasicTypes(lua_engine_ctx->lua);
55
56 engine *lua_engine = zmalloc(sizeof(*lua_engine));
57 *lua_engine = (engine) {
58diff --git a/src/script_lua.c b/src/script_lua.c
59index 33ed2aa..25a798f 100644
60--- a/src/script_lua.c
61+++ b/src/script_lua.c
62@@ -65,7 +65,6 @@ static char *redis_api_allow_list[] = {
63 static char *lua_builtins_allow_list[] = {
64 "xpcall",
65 "tostring",
66- "getfenv",
67 "setmetatable",
68 "next",
69 "assert",
70@@ -86,15 +85,16 @@ static char *lua_builtins_allow_list[] = {
71 "loadstring",
72 "ipairs",
73 "_VERSION",
74- "setfenv",
75 "load",
76 "error",
77 NULL,
78 };
79
80-/* Lua builtins which are not documented on the Lua documentation */
81-static char *lua_builtins_not_documented_allow_list[] = {
82+/* Lua builtins which are deprecated for sandboxing concerns */
83+static char *lua_builtins_deprecated[] = {
84 "newproxy",
85+ "setfenv",
86+ "getfenv",
87 NULL,
88 };
89
90@@ -116,7 +116,6 @@ static char **allow_lists[] = {
91 libraries_allow_list,
92 redis_api_allow_list,
93 lua_builtins_allow_list,
94- lua_builtins_not_documented_allow_list,
95 lua_builtins_removed_after_initialization_allow_list,
96 NULL,
97 };
98@@ -1323,7 +1322,22 @@ static int luaNewIndexAllowList(lua_State *lua) {
99 break;
100 }
101 }
102- if (!*allow_l) {
103+
104+ int allowed = (*allow_l != NULL);
105+ /* If not explicitly allowed, check if it's a deprecated function. If so,
106+ * allow it only if 'lua_enable_deprecated_api' config is enabled. */
107+ int deprecated = 0;
108+ if (!allowed) {
109+ char **c = lua_builtins_deprecated;
110+ for (; *c; ++c) {
111+ if (strcmp(*c, variable_name) == 0) {
112+ deprecated = 1;
113+ allowed = server.lua_enable_deprecated_api ? 1 : 0;
114+ break;
115+ }
116+ }
117+ }
118+ if (!allowed) {
119 /* Search the value on the back list, if its there we know that it was removed
120 * on purpose and there is no need to print a warning. */
121 char **c = deny_list;
122@@ -1332,7 +1346,7 @@ static int luaNewIndexAllowList(lua_State *lua) {
123 break;
124 }
125 }
126- if (!*c) {
127+ if (!*c && !deprecated) {
128 serverLog(LL_WARNING, "A key '%s' was added to Lua globals which is not on the globals allow list nor listed on the deny list.", variable_name);
129 }
130 } else {
131@@ -1384,6 +1398,37 @@ void luaSetTableProtectionRecursively(lua_State *lua) {
132 }
133 }
134
135+/* Set the readonly flag on the metatable of basic types (string, nil etc.) */
136+void luaSetTableProtectionForBasicTypes(lua_State *lua) {
137+ static const int types[] = {
138+ LUA_TSTRING,
139+ LUA_TNUMBER,
140+ LUA_TBOOLEAN,
141+ LUA_TNIL,
142+ LUA_TFUNCTION,
143+ LUA_TTHREAD,
144+ LUA_TLIGHTUSERDATA
145+ };
146+
147+ for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); i++) {
148+ /* Push a dummy value of the type to get its metatable */
149+ switch (types[i]) {
150+ case LUA_TSTRING: lua_pushstring(lua, ""); break;
151+ case LUA_TNUMBER: lua_pushnumber(lua, 0); break;
152+ case LUA_TBOOLEAN: lua_pushboolean(lua, 0); break;
153+ case LUA_TNIL: lua_pushnil(lua); break;
154+ case LUA_TFUNCTION: lua_pushcfunction(lua, NULL); break;
155+ case LUA_TTHREAD: lua_newthread(lua); break;
156+ case LUA_TLIGHTUSERDATA: lua_pushlightuserdata(lua, (void*)lua); break;
157+ }
158+ if (lua_getmetatable(lua, -1)) {
159+ luaSetTableProtectionRecursively(lua);
160+ lua_pop(lua, 1); /* pop metatable */
161+ }
162+ lua_pop(lua, 1); /* pop dummy value */
163+ }
164+}
165+
166 void luaRegisterVersion(lua_State* lua) {
167 lua_pushstring(lua,"REDIS_VERSION_NUM");
168 lua_pushnumber(lua,REDIS_VERSION_NUM);
169diff --git a/src/script_lua.h b/src/script_lua.h
170index 4c2b348..d8a3688 100644
171--- a/src/script_lua.h
172+++ b/src/script_lua.h
173@@ -71,6 +71,7 @@ void luaRegisterGlobalProtectionFunction(lua_State *lua);
174 void luaSetErrorMetatable(lua_State *lua);
175 void luaSetAllowListProtection(lua_State *lua);
176 void luaSetTableProtectionRecursively(lua_State *lua);
177+void luaSetTableProtectionForBasicTypes(lua_State *lua);
178 void luaRegisterLogFunction(lua_State* lua);
179 void luaRegisterVersion(lua_State* lua);
180 void luaPushErrorBuff(lua_State *lua, sds err_buff);
181diff --git a/src/server.h b/src/server.h
182index 82e4db9..952135f 100644
183--- a/src/server.h
184+++ b/src/server.h
185@@ -1900,6 +1900,7 @@ struct redisServer {
186 mstime_t busy_reply_threshold; /* Script / module timeout in milliseconds */
187 int pre_command_oom_state; /* OOM before command (script?) was started */
188 int script_disable_deny_script; /* Allow running commands marked "no-script" inside a script. */
189+ int lua_enable_deprecated_api; /* Config to enable deprecated api */
190 /* Lazy free */
191 int lazyfree_lazy_eviction;
192 int lazyfree_lazy_expire;
193diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl
194index d2fd6da..58f2028 100644
195--- a/tests/unit/scripting.tcl
196+++ b/tests/unit/scripting.tcl
197@@ -1021,6 +1021,27 @@ start_server {tags {"scripting"}} {
198 set _ $e
199 } {*Attempt to modify a readonly table*}
200
201+ test "Try trick readonly table on basic types metatable" {
202+ # Run the following scripts for basic types. Either getmetatable()
203+ # should return nil or the metatable must be readonly.
204+ set scripts {
205+ {getmetatable(nil).__index = function() return 1 end}
206+ {getmetatable('').__index = function() return 1 end}
207+ {getmetatable(123.222).__index = function() return 1 end}
208+ {getmetatable(true).__index = function() return 1 end}
209+ {getmetatable(function() return 1 end).__index = function() return 1 end}
210+ {getmetatable(coroutine.create(function() return 1 end)).__index = function() return 1 end}
211+ }
212+
213+ foreach code $scripts {
214+ catch {run_script $code 0} e
215+ assert {
216+ [string match "*attempt to index a nil value script*" $e] ||
217+ [string match "*Attempt to modify a readonly table*" $e]
218+ }
219+ }
220+ }
221+
222 test "Test loadfile are not available" {
223 catch {
224 run_script {
225@@ -1049,6 +1070,55 @@ start_server {tags {"scripting"}} {
226 } {*Script attempted to access nonexistent global variable 'print'*}
227 }
228
229+# Start a new server to test lua-enable-deprecated-api config
230+foreach enabled {no yes} {
231+start_server [subst {tags {"scripting external:skip"} overrides {lua-enable-deprecated-api $enabled}}] {
232+ test "Test setfenv availability lua-enable-deprecated-api=$enabled" {
233+ catch {
234+ run_script {
235+ local f = function() return 1 end
236+ setfenv(f, {})
237+ return 0
238+ } 0
239+ } e
240+ if {$enabled} {
241+ assert_equal $e 0
242+ } else {
243+ assert_match {*Script attempted to access nonexistent global variable 'setfenv'*} $e
244+ }
245+ }
246+
247+ test "Test getfenv availability lua-enable-deprecated-api=$enabled" {
248+ catch {
249+ run_script {
250+ local f = function() return 1 end
251+ getfenv(f)
252+ return 0
253+ } 0
254+ } e
255+ if {$enabled} {
256+ assert_equal $e 0
257+ } else {
258+ assert_match {*Script attempted to access nonexistent global variable 'getfenv'*} $e
259+ }
260+ }
261+
262+ test "Test newproxy availability lua-enable-deprecated-api=$enabled" {
263+ catch {
264+ run_script {
265+ getmetatable(newproxy(true)).__gc = function() return 1 end
266+ return 0
267+ } 0
268+ } e
269+ if {$enabled} {
270+ assert_equal $e 0
271+ } else {
272+ assert_match {*Script attempted to access nonexistent global variable 'newproxy'*} $e
273+ }
274+ }
275+}
276+}
277+
278 # Start a new server since the last test in this stanza will kill the
279 # instance at all.
280 start_server {tags {"scripting"}} {
281--
2822.25.1
283
diff --git a/meta-oe/recipes-extended/redis/redis_7.0.13.bb b/meta-oe/recipes-extended/redis/redis_7.0.13.bb
index e3a302e582..be4e90564d 100644
--- a/meta-oe/recipes-extended/redis/redis_7.0.13.bb
+++ b/meta-oe/recipes-extended/redis/redis_7.0.13.bb
@@ -28,6 +28,7 @@ SRC_URI = "http://download.redis.io/releases/${BP}.tar.gz \
28 file://CVE-2025-32023.patch \ 28 file://CVE-2025-32023.patch \
29 file://CVE-2025-48367.patch \ 29 file://CVE-2025-48367.patch \
30 file://CVE-2025-46817.patch \ 30 file://CVE-2025-46817.patch \
31 file://CVE-2025-46818.patch \
31 " 32 "
32SRC_URI[sha256sum] = "97065774d5fb8388eb0d8913458decfcb167d356e40d31dd01cd30c1cc391673" 33SRC_URI[sha256sum] = "97065774d5fb8388eb0d8913458decfcb167d356e40d31dd01cd30c1cc391673"
33 34