BUG/MEDIUM: hlua: improper lock usage with SET_SAFE_LJMP()
authorAurelien DARRAGON <adarragon@haproxy.com>
Mon, 4 Mar 2024 10:17:58 +0000 (11:17 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Mon, 4 Mar 2024 15:47:20 +0000 (16:47 +0100)
commit19b016f9f8b921b40f5ab0496254f7cbb9103488
tree52a0b452c6ce5e972115c3ba30e978f4f53b8c4b
parentd81c2205a30cad57fa4e38a019417b85e097a5c8
BUG/MEDIUM: hlua: improper lock usage with SET_SAFE_LJMP()

When we want to perform some unsafe lua stack manipulations from an
unprotected lua environment, we use SET_SAFE_LJMP() RESET_SAFE_LJMP()
combination to lock lua stack and catch potential lua exceptions that
may occur between the two.

Hence, we regularly find this pattern (duplicated over and over):

  |if (!SET_SAFE_LJMP(hlua)) {
  |        const char *error;
  |
  |        if (lua_type(hlua->T, -1) == LUA_TSTRING)
  |                error = hlua_tostring_safe(hlua->T, -1);
  |         else
  |                error = "critical error";
  |        SEND_ERR(NULL, "*: %s.\n", error);
  |}

This is wrong because when SET_SAFE_LJMP() returns false (meaning that an
exception was caught), then the lua lock was released already, thus the
caller is not expected to perform lua stack manipulations (because the
main lua stack may be shared between multiple threads). In the pattern
above we only want to retrieve the lua exception message which may be
found at the top of the stack, to do so we now explicitly take the lua
lock before accessing the lua stack. Note that hlua_lock() doesn't catch
lua exceptions so only safe lua functions are expected to be used there
(lua functions that may NOT raise exceptions).

It should be backported to every stable versions.

[ada: some ctx adj will be required for older versions as event_hdl
 doesn't exist prior to 2.8 and filters were implemented in 2.5, thus
 some chunks won't apply, but other fixes should stay relevant]
src/hlua.c