Files
meta-openembedded/meta-oe/recipes-devtools/luajit/luajit/CVE-2024-25178-0003.patch
T
Changqing Li f1d6f37efc luajit: fix several CVEs
fix CVE-2024-25176, CVE-2024-25177, CVE-2024-25178

For apply CVE-2024-25178-0003.patch more smoothly,
CVE-2024-25178-0001.patch and CVE-2024-25178-0002.patch is backported.

Signed-off-by: Changqing Li <changqing.li@windriver.com>
Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
2025-09-06 16:27:30 +02:00

164 lines
6.2 KiB
Diff

From 891bd078750312746541327332071a8fc354c10b Mon Sep 17 00:00:00 2001
From: Mike Pall <mike>
Date: Sun, 4 Feb 2024 16:34:30 +0100
Subject: [PATCH] Rework stack overflow handling.
Reported by pwnhacker0x18. Fixed by Peter Cawley. #1152
CVE: CVE-2024-25178
Upstream-Status: Backport [https://github.com/LuaJIT/LuaJIT/commit/defe61a56751a0db5f00ff3ab7b8f45436ba74c8
https://github.com/LuaJIT/LuaJIT/commit/0d313b243194a0b8d2399d8b549ca5a0ff234db5]
Signed-off-by: Changqing Li <changqing.li@windriver.com>
---
src/lj_debug.c | 1 +
src/lj_err.c | 22 +++++++++++++++++---
src/lj_err.h | 1 +
src/lj_state.c | 56 +++++++++++++++++++++++++++++++++-----------------
4 files changed, 58 insertions(+), 22 deletions(-)
diff --git a/src/lj_debug.c b/src/lj_debug.c
index 112f5358..861fac6b 100644
--- a/src/lj_debug.c
+++ b/src/lj_debug.c
@@ -64,6 +64,7 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
if (cf == NULL || (char *)cframe_pc(cf) == (char *)cframe_L(cf))
return NO_BCPOS;
ins = cframe_pc(cf); /* Only happens during error/hook handling. */
+ if (!ins) return NO_BCPOS;
} else {
if (frame_islua(nextframe)) {
ins = frame_pc(nextframe);
diff --git a/src/lj_err.c b/src/lj_err.c
index 283c3d18..b514df57 100644
--- a/src/lj_err.c
+++ b/src/lj_err.c
@@ -777,7 +777,14 @@ LJ_NOINLINE void lj_err_mem(lua_State *L)
{
if (L->status == LUA_ERRERR+1) /* Don't touch the stack during lua_open. */
lj_vm_unwind_c(L->cframe, LUA_ERRMEM);
- if (curr_funcisL(L)) L->top = curr_topL(L);
+ if (curr_funcisL(L)) {
+ L->top = curr_topL(L);
+ if (LJ_UNLIKELY(L->top > tvref(L->maxstack))) {
+ /* The current Lua frame violates the stack. Replace it with a dummy. */
+ L->top = L->base;
+ setframe_gc(L->base - 1 - LJ_FR2, obj2gco(L), LJ_TTHREAD);
+ }
+ }
setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM));
lj_err_throw(L, LUA_ERRMEM);
}
@@ -838,9 +845,11 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L)
{
ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L);
if (ef) {
- TValue *errfunc = restorestack(L, ef);
- TValue *top = L->top;
+ TValue *errfunc, *top;
+ lj_state_checkstack(L, LUA_MINSTACK * 2); /* Might raise new error. */
lj_trace_abort(G(L));
+ errfunc = restorestack(L, ef);
+ top = L->top;
if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) {
setstrV(L, top-1, lj_err_str(L, LJ_ERR_ERRERR));
lj_err_throw(L, LUA_ERRERR);
@@ -865,6 +874,13 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode)
}
#endif
+/* Stack overflow error. */
+void LJ_FASTCALL lj_err_stkov(lua_State *L)
+{
+ lj_debug_addloc(L, err2msg(LJ_ERR_STKOV), L->base-1, NULL);
+ lj_err_run(L);
+}
+
/* Formatted runtime error message. */
LJ_NORET LJ_NOINLINE static void err_msgv(lua_State *L, ErrMsg em, ...)
{
diff --git a/src/lj_err.h b/src/lj_err.h
index bd4de9ae..a3aaa756 100644
--- a/src/lj_err.h
+++ b/src/lj_err.h
@@ -23,6 +23,7 @@ LJ_DATA const char *lj_err_allmsg;
LJ_FUNC GCstr *lj_err_str(lua_State *L, ErrMsg em);
LJ_FUNCA_NORET void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode);
LJ_FUNC_NORET void lj_err_mem(lua_State *L);
+LJ_FUNC_NORET void LJ_FASTCALL lj_err_stkov(lua_State *L);
LJ_FUNC_NORET void LJ_FASTCALL lj_err_run(lua_State *L);
#if LJ_HASJIT
LJ_FUNCA_NORET void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode);
diff --git a/src/lj_state.c b/src/lj_state.c
index ccdfa381..74725bbc 100644
--- a/src/lj_state.c
+++ b/src/lj_state.c
@@ -102,27 +102,45 @@ void lj_state_shrinkstack(lua_State *L, MSize used)
/* Try to grow stack. */
void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need)
{
- MSize n;
- if (L->stacksize >= LJ_STACK_MAXEX) {
- /* 4. Throw 'error in error handling' when we are _over_ the limit. */
- if (L->stacksize > LJ_STACK_MAXEX)
+ MSize n = L->stacksize + need;
+ if (LJ_LIKELY(n < LJ_STACK_MAX)) { /* The stack can grow as requested. */
+ if (n < 2 * L->stacksize) { /* Try to double the size. */
+ n = 2 * L->stacksize;
+ if (n > LJ_STACK_MAX)
+ n = LJ_STACK_MAX;
+ }
+ resizestack(L, n);
+ } else { /* Request would overflow. Raise a stack overflow error. */
+ if (curr_funcisL(L)) {
+ L->top = curr_topL(L);
+ if (L->top > tvref(L->maxstack)) {
+ /* The current Lua frame violates the stack, so replace it with a
+ ** dummy. This can happen when BC_IFUNCF is trying to grow the stack.
+ */
+ L->top = L->base;
+ setframe_gc(L->base - 1 - LJ_FR2, obj2gco(L), LJ_TTHREAD);
+ }
+ }
+ if (L->stacksize <= LJ_STACK_MAXEX) {
+ /* An error handler might want to inspect the stack overflow error, but
+ ** will need some stack space to run in. We give it a stack size beyond
+ ** the normal limit in order to do so, then rely on lj_state_relimitstack
+ ** calls during unwinding to bring us back to a convential stack size.
+ ** The + 1 is space for the error message, and 2 * LUA_MINSTACK is for
+ ** the lj_state_checkstack() call in lj_err_run().
+ */
+ resizestack(L, LJ_STACK_MAX + 1 + 2 * LUA_MINSTACK);
+ lj_err_stkov(L); /* May invoke an error handler. */
+ } else {
+ /* If we're here, then the stack overflow error handler is requesting
+ ** to grow the stack even further. We have no choice but to abort the
+ ** error handler.
+ */
+ GCstr *em = lj_err_str(L, LJ_ERR_STKOV); /* Might OOM. */
+ setstrV(L, L->top++, em); /* There is always space to push an error. */
lj_err_throw(L, LUA_ERRERR); /* Does not invoke an error handler. */
- /* 1. We are _at_ the limit after the last growth. */
- if (!L->status) { /* 2. Throw 'stack overflow'. */
- L->status = LUA_ERRRUN; /* Prevent ending here again for pushed msg. */
- lj_err_msg(L, LJ_ERR_STKOV); /* May invoke an error handler. */
}
- /* 3. Add space (over the limit) for pushed message and error handler. */
- }
- n = L->stacksize + need;
- if (n > LJ_STACK_MAX) {
- n += 2*LUA_MINSTACK;
- } else if (n < 2*L->stacksize) {
- n = 2*L->stacksize;
- if (n >= LJ_STACK_MAX)
- n = LJ_STACK_MAX;
- }
- resizestack(L, n);
+ }
}
void LJ_FASTCALL lj_state_growstack1(lua_State *L)
--
2.34.1