Lua actions and services allocate a `struct hlua_rule` (and sometimes an
arguments array) while parsing the configuration. The resulting private
structure is stored in the generic `act_rule` structure.

However, these parsers failed to register a `release_ptr` callback. As a
result, when `free_act_rule()` destroys the parent rule during proxy
teardown (e.g. at process exit or soft-reload deinit), it leaks the
Lua-private allocation. This is exposed by LeakSanitizer when validating
configurations that use Lua rules (e.g. `examples/games.cfg -c`).

This is a configuration/process-lifetime data leak rather than a
per-request or per-connection leak. It does not accumulate during normal
runtime operation.

This patch fixes the issue by adding a common release callback and
assigning it in all three Lua parsers that allocate this structure
(`action_register_lua`, `action_register_service_http`, and
`action_register_service_tcp`). The callback frees the `hlua_rule`
and any owned argument strings, while deliberately leaving the borrowed
`hlua_function` untouched.

This fixes issue #3480.

Backport status: may be backported to all supported versions.
---
 src/hlua.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/src/hlua.c b/src/hlua.c
index 1882db98a..bcfef7d57 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -11131,6 +11131,21 @@ static void hlua_applet_http_release(struct appctx 
*ctx)
        http_ctx->hlua = NULL;
 }
 
+/* Release the private data attached to a Lua action or service rule. */
+static void release_hlua_rule(struct act_rule *rule)
+{
+       if (rule->arg.hlua_rule) {
+               if (rule->arg.hlua_rule->args) {
+                       int i;
+
+                       for (i = 0; rule->arg.hlua_rule->args[i]; i++)
+                               ha_free(&rule->arg.hlua_rule->args[i]);
+                       ha_free(&rule->arg.hlua_rule->args);
+               }
+               ha_free(&rule->arg.hlua_rule);
+       }
+}
+
 /* global {tcp|http}-request parser. Return ACT_RET_PRS_OK in
  * success case, else return ACT_RET_PRS_ERR.
  *
@@ -11179,6 +11194,7 @@ static enum act_parse_ret action_register_lua(const 
char **args, int *cur_arg, s
 
        rule->action = ACT_CUSTOM;
        rule->action_ptr = hlua_action;
+       rule->release_ptr = release_hlua_rule;
        return ACT_RET_PRS_OK;
 
   error:
@@ -11232,6 +11248,7 @@ static enum act_parse_ret 
action_register_service_http(const char **args, int *c
        rule->applet.fct = hlua_applet_http_fct;
        rule->applet.release = hlua_applet_http_release;
        rule->applet.timeout = hlua_timeout_applet;
+       rule->release_ptr = release_hlua_rule;
 
        return ACT_RET_PRS_OK;
 }
@@ -11420,6 +11437,7 @@ static enum act_parse_ret 
action_register_service_tcp(const char **args, int *cu
        rule->applet.fct = hlua_applet_tcp_fct;
        rule->applet.release = hlua_applet_tcp_release;
        rule->applet.timeout = hlua_timeout_applet;
+       rule->release_ptr = release_hlua_rule;
 
        return 0;
 }
-- 
2.55.0



Reply via email to