Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libinput for openSUSE:Factory 
checked in at 2026-04-04 19:05:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libinput (Old)
 and      /work/SRC/openSUSE:Factory/.libinput.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libinput"

Sat Apr  4 19:05:27 2026 rev:130 rq:1344309 version:1.31.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/libinput/libinput.changes        2026-02-16 
13:22:58.896203081 +0100
+++ /work/SRC/openSUSE:Factory/.libinput.new.21863/libinput.changes     
2026-04-04 19:06:45.567506483 +0200
@@ -1,0 +2,8 @@
+Thu Apr  2 07:22:08 UTC 2026 - Jan Engelhardt <[email protected]>
+
+- Update to release 1.31.1
+  * Fixed sandbox escape in libinput plugins [CVE-2026-35093]
+  * Use after free allowing information leak in libinput plugins
+    [CVE-2026-35094]
+
+-------------------------------------------------------------------

Old:
----
  libinput-1.31.0.tar.gz

New:
----
  libinput-1.31.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libinput.spec ++++++
--- /var/tmp/diff_new_pack.7x0hJ0/_old  2026-04-04 19:06:48.203614564 +0200
+++ /var/tmp/diff_new_pack.7x0hJ0/_new  2026-04-04 19:06:48.239616039 +0200
@@ -37,7 +37,7 @@
 %define lname  libinput10
 %define pname  libinput
 Name:           libinput%{?xsuffix}
-Version:        1.31.0
+Version:        1.31.1
 Release:        0
 Summary:        Input device and event processing library
 License:        MIT

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.7x0hJ0/_old  2026-04-04 19:06:48.591630472 +0200
+++ /var/tmp/diff_new_pack.7x0hJ0/_new  2026-04-04 19:06:48.619631620 +0200
@@ -1,5 +1,5 @@
-mtime: 1771003500
-commit: 53dd0d605bbfab5b31b2f4d9e405601ad6561edf1e13b236b083ae58295b0915
+mtime: 1775114676
+commit: 6cfb5d9611a339e3f447be0287373aed1776c9a947e0c8c8296b75ee548aa3f1
 url: https://src.opensuse.org/jengelh/libinput
 revision: master
 

++++++ build.specials.obscpio ++++++

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-04-02 09:24:44.000000000 +0200
@@ -0,0 +1 @@
+.osc

++++++ libinput-1.31.0.tar.gz -> libinput-1.31.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libinput-1.31.0/meson.build 
new/libinput-1.31.1/meson.build
--- old/libinput-1.31.0/meson.build     2026-02-13 00:25:46.000000000 +0100
+++ new/libinput-1.31.1/meson.build     2026-04-02 03:04:12.000000000 +0200
@@ -1,5 +1,5 @@
 project('libinput', 'c',
-       version : '1.31.0',
+       version : '1.31.1',
        license : 'MIT/Expat',
        default_options : [ 'c_std=gnu99', 'warning_level=2' ],
        meson_version : '>= 0.64.0')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libinput-1.31.0/src/libinput-plugin-lua.c 
new/libinput-1.31.1/src/libinput-plugin-lua.c
--- old/libinput-1.31.0/src/libinput-plugin-lua.c       2026-02-13 
00:25:46.000000000 +0100
+++ new/libinput-1.31.1/src/libinput-plugin-lua.c       2026-04-02 
03:04:12.000000000 +0200
@@ -563,6 +563,12 @@
 }
 
 static int
+readonly_newindex(lua_State *L)
+{
+       return luaL_error(L, "attempt to modify a read-only table");
+}
+
+static int
 libinputplugin_gc(lua_State *L)
 {
        LibinputPlugin *p = luaL_checkudata(L, 1, PLUGIN_METATABLE);
@@ -673,7 +679,28 @@
        return libinputplugin_log(L, LIBINPUT_LOG_PRIORITY_ERROR);
 }
 
-static const struct luaL_Reg libinputplugin_vtable[] = {
+static void
+setup_vfuncs(lua_State *L,
+            const char *metatable_name,
+            const struct luaL_Reg *vfuncs,
+            const struct luaL_Reg *public_methods)
+{
+       luaL_newmetatable(L, metatable_name);
+       luaL_setfuncs(L, vfuncs, 0);
+
+       lua_newtable(L);
+       luaL_setfuncs(L, public_methods, 0);
+       lua_setfield(L, -2, "__index");
+
+       /* set metatable.__metatable = false to prevent a script from 
getmetatable(),
+          which is blocked anyway but safe and sorry and whatnot */
+       lua_pushboolean(L, 0);
+       lua_setfield(L, -2, "__metatable");
+
+       lua_pop(L, 1);
+}
+
+static const struct luaL_Reg libinputplugin_methods[] = {
        { "now", libinputplugin_now },
        { "version", libinputplugin_version },
        { "connect", libinputplugin_connect },
@@ -685,18 +712,18 @@
        { "log_debug", libinputplugin_log_debug },
        { "log_info", libinputplugin_log_info },
        { "log_error", libinputplugin_log_error },
-       { "__gc", libinputplugin_gc },
        { NULL, NULL }
 };
 
+static const struct luaL_Reg libinputplugin_meta[] = { { "__gc", 
libinputplugin_gc },
+                                                      { "__newindex",
+                                                        readonly_newindex },
+                                                      { NULL, NULL } };
+
 static void
 libinputplugin_init(lua_State *L)
 {
-       luaL_newmetatable(L, PLUGIN_METATABLE);
-       lua_pushstring(L, "__index");
-       lua_pushvalue(L, -2); /* push metatable */
-       lua_settable(L, -3);  /* metatable.__index = metatable */
-       luaL_setfuncs(L, libinputplugin_vtable, 0);
+       setup_vfuncs(L, PLUGIN_METATABLE, libinputplugin_meta, 
libinputplugin_methods);
 }
 
 static int
@@ -1073,7 +1100,7 @@
        return 0;
 }
 
-static const struct luaL_Reg evdevdevice_vtable[] = {
+static const struct luaL_Reg evdevdevice_methods[] = {
        { "info", evdevdevice_info },
        { "name", evdevdevice_name },
        { "usages", evdevdevice_usages },
@@ -1087,18 +1114,17 @@
        { "prepend_frame", evdevdevice_prepend_frame },
        { "append_frame", evdevdevice_append_frame },
        { "disable_feature", evdevdevice_disable_feature },
-       { "__gc", evdevdevice_gc },
        { NULL, NULL }
 };
 
+static const struct luaL_Reg evdevdevice_meta[] = { { "__gc", evdevdevice_gc },
+                                                   { "__newindex", 
readonly_newindex },
+                                                   { NULL, NULL } };
+
 static void
 evdevdevice_init(lua_State *L)
 {
-       luaL_newmetatable(L, EVDEV_DEVICE_METATABLE);
-       lua_pushstring(L, "__index");
-       lua_pushvalue(L, -2); /* push metatable */
-       lua_settable(L, -3);  /* metatable.__index = metatable */
-       luaL_setfuncs(L, evdevdevice_vtable, 0);
+       setup_vfuncs(L, EVDEV_DEVICE_METATABLE, evdevdevice_meta, 
evdevdevice_methods);
 }
 
 static void
@@ -1336,7 +1362,7 @@
                return NULL;
        }
 
-       int ret = luaL_loadfile(L, path);
+       int ret = luaL_loadfilex(L, path, "t");
        if (ret == LUA_OK) {
                plugin->L = steal(&L);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libinput-1.31.0/test/test-plugins-lua.c 
new/libinput-1.31.1/test/test-plugins-lua.c
--- old/libinput-1.31.0/test/test-plugins-lua.c 2026-02-13 00:25:46.000000000 
+0100
+++ new/libinput-1.31.1/test/test-plugins-lua.c 2026-04-02 03:04:12.000000000 
+0200
@@ -526,6 +526,38 @@
 }
 END_TEST
 
+START_TEST(lua_gc_not_accessible)
+{
+       _destroy_(tmpdir) *tmpdir = tmpdir_create(NULL);
+       const char *lua =
+               "libinput:register({1})\n"
+               "assert(libinput.__gc == nil)\n"
+               "function check_device_gc(device)\n"
+               "  assert(device.__gc == nil)\n"
+               "  libinput:log_info(\"gc_not_accessible: ok\")\n"
+               "end\n"
+               "libinput:connect(\"new-evdev-device\", check_device_gc)\n";
+
+       _autofree_ char *path = litest_write_plugin(tmpdir->path, lua);
+       _litest_context_destroy_ struct libinput *li =
+               litest_create_context_with_plugindir(tmpdir->path);
+       if (libinput_log_get_priority(li) > LIBINPUT_LOG_PRIORITY_INFO)
+               libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_INFO);
+
+       litest_with_logcapture(li, capture) {
+               libinput_plugin_system_load_plugins(li,
+                                                   
LIBINPUT_PLUGIN_SYSTEM_FLAG_NONE);
+               litest_drain_events(li);
+
+               _destroy_(litest_device) *device = litest_add_device(li, 
LITEST_MOUSE);
+               litest_drain_events(li);
+
+               litest_assert_logcapture_no_errors(capture);
+               litest_assert_strv_substring(capture->infos, 
"gc_not_accessible: ok");
+       }
+}
+END_TEST
+
 START_TEST(lua_frame_handler)
 {
        _destroy_(tmpdir) *tmpdir = tmpdir_create(NULL);
@@ -1172,10 +1204,79 @@
 }
 END_TEST
 
+/* Pre-compiled Lua 5.4 bytecode for the following source:
+ *
+ *   libinput:register({1})
+ *   libinput:connect("new-evdev-device", function(device)
+ *       libinput:log_info("loaded from binary lua file")
+ *   end)
+ *
+ * To regenerate:
+ *   luac5.4 -o /dev/stdout /tmp/plugin.lua | xxd -i
+ */
+static const unsigned char binary_lua_plugin[] = {
+       0x1b, 0x4c, 0x75, 0x61, 0x54, 0x00, 0x19, 0x93, 0x0d, 0x0a, 0x1a, 0x0a, 
0x04,
+       0x08, 0x08, 0x78, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00,
+       0x00, 0x00, 0x28, 0x77, 0x40, 0x01, 0x9b, 0x40, 0x74, 0x65, 0x73, 0x74, 
0x2f,
+       0x31, 0x30, 0x2d, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x2d, 0x70, 0x6c, 
0x75,
+       0x67, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x80, 0x80, 0x00, 0x01, 0x04, 
0x8e,
+       0x51, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x01, 
0x13,
+       0x01, 0x00, 0x01, 0x52, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x80, 0x4e, 
0x01,
+       0x01, 0x00, 0x44, 0x00, 0x03, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x14, 0x80, 
0x00,
+       0x02, 0x03, 0x81, 0x01, 0x00, 0xcf, 0x01, 0x00, 0x00, 0x44, 0x00, 0x04, 
0x01,
+       0x46, 0x00, 0x01, 0x01, 0x84, 0x04, 0x89, 0x6c, 0x69, 0x62, 0x69, 0x6e, 
0x70,
+       0x75, 0x74, 0x04, 0x89, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 
0x04,
+       0x88, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x04, 0x91, 0x6e, 0x65, 
0x77,
+       0x2d, 0x65, 0x76, 0x64, 0x65, 0x76, 0x2d, 0x64, 0x65, 0x76, 0x69, 0x63, 
0x65,
+       0x81, 0x01, 0x00, 0x00, 0x81, 0x80, 0x8d, 0x8f, 0x01, 0x00, 0x04, 0x85, 
0x8b,
+       0x00, 0x00, 0x00, 0x94, 0x80, 0x01, 0x01, 0x83, 0x01, 0x01, 0x00, 0xc4, 
0x00,
+       0x03, 0x01, 0xc7, 0x00, 0x01, 0x00, 0x83, 0x04, 0x89, 0x6c, 0x69, 0x62, 
0x69,
+       0x6e, 0x70, 0x75, 0x74, 0x04, 0x89, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x6e, 
0x66,
+       0x6f, 0x04, 0x9c, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, 0x66, 0x72, 
0x6f,
+       0x6d, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x6c, 0x75, 0x61, 
0x20,
+       0x66, 0x69, 0x6c, 0x65, 0x81, 0x00, 0x00, 0x00, 0x80, 0x85, 0x01, 0x00, 
0x00,
+       0x00, 0x01, 0x80, 0x81, 0x87, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x80, 
0x85,
+       0x81, 0x85, 0x5f, 0x45, 0x4e, 0x56, 0x8e, 0x01, 0x0b, 0x00, 0x00, 0x00, 
0x00,
+       0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xfe, 0x02, 0x80, 0x80, 0x81, 0x85, 
0x5f,
+       0x45, 0x4e, 0x56,
+};
+
+START_TEST(lua_reject_precompiled_files)
+{
+       _destroy_(tmpdir) *tmpdir = tmpdir_create(NULL);
+
+       /* Write the binary bytecode to a .lua file in the tmpdir.
+        * Binary (pre-compiled) Lua files must be rejected by the
+        * plugin loader for security reasons. */
+       _autofree_ char *path = strdup_printf("%s/10-binary-plugin.lua", 
tmpdir->path);
+       _autoclose_ int fd = open(path, O_WRONLY | O_CREAT, 0644);
+       litest_assert_errno_success(fd);
+
+       ssize_t written = write(fd, binary_lua_plugin, 
sizeof(binary_lua_plugin));
+       litest_assert_int_eq((int)written, (int)sizeof(binary_lua_plugin));
+       fsync(fd);
+
+       _litest_context_destroy_ struct libinput *li =
+               litest_create_context_with_plugindir(tmpdir->path);
+
+       litest_with_logcapture(li, capture) {
+               libinput_plugin_system_load_plugins(li,
+                                                   
LIBINPUT_PLUGIN_SYSTEM_FLAG_NONE);
+               litest_drain_events(li);
+
+               size_t index = 0;
+               litest_assert(
+                       strv_find_substring(capture->errors, "Failed to load", 
&index));
+               litest_assert_str_in(path, capture->errors[index]);
+       }
+}
+END_TEST
+
 TEST_COLLECTION(lua)
 {
        /* clang-format off */
        litest_add_no_device(lua_load_failure);
+       litest_add_no_device(lua_reject_precompiled_files);
        litest_with_parameters(params,
                               "content", 'I', 6,
                                        litest_named_i32(EMPTY),
@@ -1219,6 +1320,7 @@
        litest_add_no_device(lua_register_multiversions);
        litest_add_no_device(lua_allowed_functions);
        litest_add_no_device(lua_disallowed_functions);
+       litest_add_no_device(lua_gc_not_accessible);
 
        litest_add_no_device(lua_frame_handler);
        litest_add_no_device(lua_device_info);

Reply via email to