]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: hlua_fcn: ensure systematic bref cleanup for patref list iterator
authorAurelien DARRAGON <adarragon@haproxy.com>
Fri, 7 Aug 2026 15:07:36 +0000 (17:07 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 10 Aug 2026 09:08:39 +0000 (11:08 +0200)
Similar bug as aeff2a3b2a ("BUG/MEDIUM: hlua_fcn: ensure systematic watcher
cleanup for server list iterator") but this time it affects patref list
iterator.

If the patref list iteration is interrupted (ie: break away from the loop
or lua error), we still need to unlink the bref we set earlier because
the hlua_patref_iterator_context is a temporary object so we cannot
let a reference once the object is dead. Obviously this can corrupt
the pattern reference element bref "users" list and lead to invalid
reads as well.

Reported-by: Claude (ANT-2026-DARC9AY8)
It should be backported up to 3.2 where hlua patref API was implemented.

src/hlua_fcn.c

index 6424fe2bb9b58e5fa79cf3f3fc56aa2d0bf9c214..44f37b1996b31c99711067f57618e14976ea7c56 100644 (file)
@@ -3203,6 +3203,25 @@ int hlua_listable_patref_pairs_iterator(lua_State *L)
        return _hlua_listable_patref_pairs_iterator(L, LUA_OK, 0);
 }
 
+/* ensure proper cleanup for listable_patref_pairs */
+int hlua_listable_patref_pairs_gc(lua_State *L)
+{
+       struct hlua_patref_iterator_context *ctx;
+
+       ctx = lua_touserdata(L, 1);
+
+       /* we need to make sure that bref is unlinked even if the
+        * iterator was interrupted (ie: "break" from the loop), else the
+        * patref iterator element may still be accessed while it is no
+        * longer in memory scope (this can lead to invalid reads as well
+        * as pat_ref_elt list corruption).
+        */
+       HA_RWLOCK_WRLOCK(PATREF_LOCK, &ctx->ref->ptr->lock);
+       LIST_DEL_INIT(&ctx->bref.users);
+       HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &ctx->ref->ptr->lock);
+       return 0;
+}
+
 /* init the iterator context, return iterator function
  * with context as closure. The only argument is a
  * patref list object.
@@ -3215,6 +3234,12 @@ int hlua_listable_patref_pairs(lua_State *L)
        ref = hlua_checkudata(L, 1, class_patref_ref);
 
        ctx = lua_newuserdata(L, sizeof(*ctx));
+
+       /* add gc metamethod to the newly created userdata */
+       lua_newtable(L);
+       hlua_class_function(L, "__gc", hlua_listable_patref_pairs_gc);
+       lua_setmetatable(L, -2);
+
        ctx->ref = ref;
        LIST_INIT(&ctx->bref.users);