]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: hlua: fix format-string vulnerability in Patref error path
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 7 Apr 2026 07:48:13 +0000 (09:48 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Tue, 7 Apr 2026 12:18:13 +0000 (14:18 +0200)
hlua_error() is a printf-family function (calls vsnprintf), but
hlua_patref_set, hlua_patref_add, and _hlua_patref_add_bulk pass
errmsg directly as the format string. errmsg is built by pattern.c
helpers that embed the user-supplied key or value verbatim, e.g.
pat_ref_set_elt() generates "unable to parse '<value>'".

A Lua script calling:

    ref:set("key", "%p.%p.%p.%p.%p.%p.%p.%p")

against a map with an integer output type (where the parse fails)
gets stack/register contents formatted into the (nil, err) return
value -> ASLR/canary leak. With %n and no _FORTIFY_SOURCE this
becomes an arbitrary write primitive.

This must be backported as far as the Patref Lua API exists.

src/hlua_fcn.c

index 36c5f98d021fb4d084098d316ef65005de18d9e8..f204c0a048c4900baa880b3d14fceb6ce1475fb9 100644 (file)
@@ -2870,7 +2870,7 @@ int hlua_patref_add(lua_State *L)
 
 
        if (!ret) {
-               ret = hlua_error(L, errmsg);
+               ret = hlua_error(L, "%s", errmsg);
                ha_free(&errmsg);
                return ret;
        }
@@ -2919,7 +2919,7 @@ static int _hlua_patref_add_bulk(lua_State *L, int status, lua_KContext ctx)
 
                if (!pat_ref_load(ref->ptr, curr_gen, key, value, -1, &errmsg)) {
                        HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &ref->ptr->lock);
-                       ret = hlua_error(L, errmsg);
+                       ret = hlua_error(L, "%s", errmsg);
                        ha_free(&errmsg);
                        return ret;
                }
@@ -3023,7 +3023,7 @@ int hlua_patref_set(lua_State *L)
        HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &ref->ptr->lock);
 
        if (!ret) {
-               ret = hlua_error(L, errmsg);
+               ret = hlua_error(L, "%s", errmsg);
                ha_free(&errmsg);
                return ret;
        }