Skip to content

Commit 0fc44b4

Browse files
gregkhwtarreau
authored andcommitted
BUG/MINOR: hlua: fix use-after-free of HTTP reason string
hlua_applet_http_status() stored the result of luaL_optlstring() directly in http_ctx->reason. The pointer references Lua-managed string storage which is only guaranteed valid until the C function returns to Lua. If the GC runs between applet:set_status(200, str) and applet:start_response(), the pointer dangles. hlua_applet_http_send_response() then calls ist(http_ctx->reason) which does strlen() on freed memory, followed by memcpy into the HTX status line. The freed-and-reallocated chunk contents are sent verbatim to the HTTP client. Trigger: applet:set_status(200, table.concat({"Reason ", str:rep(50)})) collectgarbage("collect"); collectgarbage("collect") applet:start_response() With heap grooming, adjacent allocation contents (session data, TLS material from the same thread) leak into the response status line. Anchor the Lua string in the registry keyed by the http_ctx field address so it survives until the applet is done with it. The registry entry is overwritten on each call (handles repeated set_status) and naturally cleaned up when the lua_State is closed. This patch should be backported to all stable versions. (cherry picked from commit 4ad200f) Signed-off-by: Willy Tarreau <w@1wt.eu> (cherry picked from commit 2687db7) Signed-off-by: Willy Tarreau <w@1wt.eu>
1 parent f4fc5bb commit 0fc44b4

1 file changed

Lines changed: 11 additions & 0 deletions

File tree

src/hlua.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6253,6 +6253,17 @@ __LJMP static int hlua_applet_http_status(lua_State *L)
62536253
}
62546254

62556255
http_ctx->status = status;
6256+
/* Anchor the reason string in the registry so the Lua GC can't
6257+
* collect it before start_response() reads it back. The previous
6258+
* direct pointer assignment was a use-after-free if a GC ran
6259+
* between set_status() and start_response().
6260+
*/
6261+
lua_pushlightuserdata(L, &http_ctx->reason);
6262+
if (reason)
6263+
lua_pushvalue(L, 3);
6264+
else
6265+
lua_pushnil(L);
6266+
lua_settable(L, LUA_REGISTRYINDEX);
62566267
http_ctx->reason = reason;
62576268
lua_pushboolean(L, 1);
62586269
return 1;

0 commit comments

Comments
 (0)