From: Christopher Faulet Date: Fri, 16 Feb 2024 14:00:54 +0000 (+0100) Subject: BUG/MEDIUM: hlua: Be able to garbage collect uninitialized lua sockets X-Git-Tag: v3.0-dev4~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=38534d344bdcdbfee72291b847087d0424f56529;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: hlua: Be able to garbage collect uninitialized lua sockets It is poosible to create a lua socket without performing any connect. In this case, the lua socket is released because of the garbage collector. However, the garbarge collector does not release the applet, it wakes it up. Since commit 751b59c40b ("BUG/MEDIUM: hlua: Initialize appctx used by a lua socket on connect only"), the applet initialization is performed on connect. So, here, it is possible to wake an uninitialized applet. It is an unexpected case for the applet's I/O handler, leading to a segfault because some resources are not initialized (the stream's target in this case). So, now, in the lua socket GC function, we take care to immediately release uninitialized applets. At worst, the release itself is delayed. But it is safe because we are sure the applet's I/O handler will never be executed. In addition, we take case to increment the GC counter when the lua socket is created. The way, uninitialized lua socket are released more quickly. This patch should fix the issue #2451. It must be backported as far as 2.6. --- diff --git a/src/hlua.c b/src/hlua.c index fb04602b4e..dcc8b6a81c 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -2434,12 +2434,19 @@ __LJMP static int hlua_socket_gc(lua_State *L) ctx = container_of(peer, struct hlua_csk_ctx, xref); - /* Set the flag which destroy the session. */ - ctx->die = 1; - appctx_wakeup(ctx->appctx); - /* Remove all reference between the Lua stack and the coroutine stream. */ xref_disconnect(&socket->xref, peer); + + if (se_fl_test(ctx->appctx->sedesc, SE_FL_ORPHAN)) { + /* The applet was never initialized, just release it */ + appctx_free(ctx->appctx); + } + else { + /* Otherwise, notify it that is must die and wake it up */ + ctx->die = 1; + appctx_wakeup(ctx->appctx); + } + return 0; } @@ -3276,8 +3283,6 @@ __LJMP static int hlua_socket_connect(struct lua_State *L) applet_have_more_data(appctx); appctx_wakeup(appctx); - hlua->gc_count++; - if (!notification_new(&hlua->com, &csk_ctx->wake_on_write, hlua->task)) { xref_unlock(&socket->xref, peer); WILL_LJMP(luaL_error(L, "out of memory")); @@ -3388,6 +3393,12 @@ __LJMP static int hlua_socket_new(lua_State *L) struct hlua_socket *socket; struct hlua_csk_ctx *ctx; struct appctx *appctx; + struct hlua *hlua; + + /* Get hlua struct, or NULL if we execute from main lua state */ + hlua = hlua_gethlua(L); + if (!hlua) + return 0; /* Check stack size. */ if (!lua_checkstack(L, 3)) { @@ -3427,6 +3438,8 @@ __LJMP static int hlua_socket_new(lua_State *L) LIST_INIT(&ctx->wake_on_write); LIST_INIT(&ctx->wake_on_read); + hlua->gc_count++; + /* Initialise cross reference between stream and Lua socket object. */ xref_create(&socket->xref, &ctx->xref); return 1;